Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations Chriss Miller on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Persistent error in storing JPG in general field VFP 9.0: OLE error code 0x80040011: Not able to convert object.

dmusicant

Programmer
Mar 29, 2005
257
US
I've experienced same or similar errors in the past but lately had no problem except today. I use Irfanview 64 a free image program to view and edit (usually just crop and save) JPGs from my digital cameras including my Android phone.

I have viewed a saved file in Irfanview, copied it to the Windows 10 clipboard, gone to a general field in one of my VFP 9.0 tables, opened it and pasted the photo. I see it, but not its totality. Usually I close the memo field, and when I reopen it I see the entire photo, not just a portion of it. But now I close it, reopen it and get this error:

OLE error code 0x80040011: Not able to convert object.

Even accessing the record will cause this, not opening the general field. I couldn't see a memo field in the record without the error occurring. Only way to fix the snafu was to delete the record. Happens every time I try to embed that JPG in the general field. What could be afoot here? I'm not doing anything differently than I usually do.
 
It has been recommended to not use General fields for decades by now. If you google for it, image storage in a General field depends on MS Paint and more precisely either Paint.Picture or Package OLE classes. So the General field depends on OLE object, it does not store a clipboard object, therefore the conversion. I think whatever the file is you edit in Irfanview within the clipboard you have a picture representation as a BMP or even DIB (device independent bitmap). Anyway, that's what's converted.

I guess you could fix that by using a Shell Window in administrator mode and run this command:
Code:
ASSOC BMP=Paint.Picture

Otherwise alternatives to bring an image into a dbf are APPEND GENERAL FROM fileaname and then using an OleBound control for displaying it, also can be the basis for reports. But we have BLOB fields by now for storing the fie content read in from FILETOSTR() and PictureVal="Blobfieldname" for diplay in an image control, besides using an image control Picture property set to a filename. Especially the ability to view the image in a General field by double click on it demands an uncompressed DIB and that's bloat of the fpt file, do you really need to store your images in a DBF or its FPT? You don't need to answer this, the answer is no. Even in reports you can use a picture/olebound control and don't use the olebound to general field feature but point to an image file by using the default control source type image file name, instead of General field name.

1746166907916.png

To stress it once more: This is the default. The General field is dead. Don't use it.
 
Last edited:
... and some demo code (pictures in a grid) to illustrate Chriss's advice

Code:
Public oForm

oForm = Createobject('myForm')
oForm.Show()

READ EVENTS

CLOSE ALL
CLEAR ALL

**********

DEFINE Class myForm As Form
  Height = 360
  Width = 840
  MinWidth = This.Width
  MaxWidth = This.Width
 
  Add Object myGrid As Grid With Height = 360, Width = 840, RecordSource = 'tblImageList'

  Procedure Load
    Local Array laImageList[1]
    Local lcPath
    
    lcPath = Home()+'Graphics\Bitmaps\Offctlbr\Large\Color'
    
    Create Cursor tblImageList (FileName M)
    
    For lix = 1 To Adir(laImageList, Addbs(m.lcPath) + '*.*')
      Insert Into tblImageList Values (Addbs(m.lcPath) ++ laImageList[lix,1])
    Endfor
 
*!*        For lix = 1 To Adir(laImageList, "*.jpg")
*!*          Insert Into tblImageList Values (laImageList[lix,1])
*!*        Endfor
    
    Go Top
  Endproc

  Procedure Init
    With This.myGrid
      .ColumnCount = 2
      .RowHeight = 24
      .Anchor = 15

      With .Columns(1)
        .AddObject('edtBox','EditBox')
        .CurrentControl = 'edtBox'
        .Width = 720
        .Sparse = .F.
        .edtBox.Visible = .T.
      Endwith

      With .Columns(2)
          .Header1.Caption = ""
        .AddObject('imgImage','myImage')
        .CurrentControl = 'imgImage'
        .Width = 24
        .Sparse = .F.
        .imgImage.ImageFilename = "tblImageList.FileName"
        .imgImage.Visible = .T.
      Endwith
    Endwith
  ENDPROC
 
  PROCEDURE Destroy()
      ThisForm.Release()
      CLEAR EVENTS()
  ENDPROC
 
ENDDEFINE

**********

DEFINE Class myImage as Image
   ImageFileName = ""
  
   PROCEDURE Backstyle_Access()
      This.Picture = Evaluate(this.ImageFileName)
      Return This.BackStyle
   ENDPROC
  
ENDDEFINE

***********

hth

MarK
 
The app I use to access the DBFs in my system was created using FPW 2.6a. I only use FPW to modify the screens of the app, which I only rarely do. I use VFP 9.0 when I use the app (which is a lot!), have made some modifications in the app so this works. The opening screen I use was FPW created. It blows up in VFP quite often and I have to restart the app. I created a VFP form to use instead of the FPW created one to start the app, but that blows up frequently too, but in a different way. There's something(s) wrong with it. I haven't chased it down, I'm just living with the fact that I have to restart it.

Anyway, I'm saying this to illustrate that I'm not doing anything fancy here, I just browse the tables, typically with a BROWSE LAST in the code. When I place a JPG in a general field I do it while browsing. Most of my tables don't have a general field, but several do. Usually there's no problem. I have no idea why VFP is choking on that JPG. I didn't do anything different.
 
As said, this depends on something outside of VFP. So there's nothing unusual about it failing once the outside changes. And it changes all the time through many things like Windows Updates, software installations and updates, etc.

Have you tried ASSOC BMP=Paint.Picture?

I can paste an image into a General field on Windows 10, but I also did the ASSOC command a while ago. There's an older thread about that, actually. It doesn't depend on that JPG or any file at all when you paste from the clipboard. All that matters is that an image on the clipboard can be converted to a Paint.Picture stored in the General field. Lacking that association you get such an error. You might still be able to APPEND GENERAL FROM a file, but I think it will require the same association. This is not a file associaiton, this is an association of which OLE class hosts the type of image, and in Windows clipboard that's always BMP, not anything else. Anything else could become important when you APPEND GENERAL FROM a file, but not from the clipboard.
 
Last edited:
Windows 10/11 have a different paint program and need a couple of regedits to use general fields...
 

Attachments

  • BitmapImage.zip
    1.9 KB · Views: 6
As said, this depends on something outside of VFP. So there's nothing unusual about it failing once the outside changes. And it changes all the time through many things like Windows Updates, software installations and updates, etc.

Have you tried ASSOC BMP=Paint.Picture?

I can paste an image into a General field on Windows 10, but I also did the ASSOC command a while ago. There's an older thread about that, actually. It doesn't depend on that JPG or any file at all when you paste from the clipboard. All that matters is that an image on the clipboard can be converted to a Paint.Picture stored in the General field. Lacking that association you get such an error. You might still be able to APPEND GENERAL FROM a file, but I think it will require the same association. This is not a file associaiton, this is an association of which OLE class hosts the type of image, and in Windows clipboard that's always BMP, not anything else. Anything else could become important when you APPEND GENERAL FROM a file, but not from the clipboard.
So I'd put the command ASSOC BMP=Paint.Picture in a setup file when I start VFP? That would allow me to copy/paste a JPG into a general field? I've never used BLOB fields in my dbfs before. I just created one 1/2 hour ago and when I tried pasting in a JPG on my clipboard nothing happened. I'm not doing this stuff in code, I'm simply trying to copy/paste a JPG into a field in a dbf so I can view it later by double clicking on it or keyboard combo Crtl+PgUp.

I'd really prefer to be able to work with DBFs that will work with FPW 2.6a because the app was created with FPW 2.6a. Not that I use FPW for anything other than modifying screens of the app, but I'd prefer to be able to use FPW with the app and not have it blow when it uses DBFs. I created a little PRG that converts VFP compliant DBFs to FPW compliant DBFs that I have used on my tables.
 
So I'd put the command ASSOC BMP=Paint.Picture in a setup file when I start VFP?
No, you just start cmd.exe in administrator elevation and once run ASSOC BMP=Paint.Picture
Then this is settled until it stops working again.

I understand you're just using some legacy code within the VPF9 IDE and are not interested in upgrading anything to new UI etc. So just try that. If it does not help you'll be quite lost.

And regarding BLOB fields: Nobody said they can get images pasted into them. They're also not displaying images. The just can hold any type of binary content of any length up to 2GB and that can be used as data source for things like a report image control or a form image control. It works totally different. So if you want to get back to what you're used to your chances are with the ASSOC command, only. Or what Griff posted in more detail.
 
Last edited:
Windows 10/11 have a different paint program and need a couple of regedits to use general fields...
When I unzip and attempt to run the registry edit I get this message:

X Cannot import W:\Downloads-P1Gen3\BitmapImage\Paint.Picture.reg: Error opening the file. There may be a disk or file system error.

[ OK ]

The directory cited is off the directory on my NAS server where I send downloads made to this laptop (I do this to ensure I have backups of downloads and so my other machines can see the downloads I make). Conceivably it's a temporary network problem. I'll try to run it later.
 
It probably elevates you and loses the drive mapping.
unzip locally and run...

but check it first - i'm not responsible for what you run in reg files
 
One thing is true: Griffs reg files might not make it work on your PC, because values might need to differ, like the path to mspaint.exe.

Though that itelf is the same even across many OS versions. ASSOC will add the right keys, so I would try it and if that already solves the problem, you didn't risk anything. I'm also sure all these keys will do no harm to your system, worst case scenario is you don't get pasting into a general field working with them and would need to take more steps, like reinstalling Windows to get this feature to its default state.

I can only add to this that I only did ASSOC and nothing else.
 
... and some demo code (pictures in a grid) to illustrate Chriss's advice

Code:
Public oForm

oForm = Createobject('myForm')
oForm.Show()

READ EVENTS

CLOSE ALL
CLEAR ALL

**********

DEFINE Class myForm As Form
  Height = 360
  Width = 840
  MinWidth = This.Width
  MaxWidth = This.Width
 
  Add Object myGrid As Grid With Height = 360, Width = 840, RecordSource = 'tblImageList'

  Procedure Load
    Local Array laImageList[1]
    Local lcPath
   
    lcPath = Home()+'Graphics\Bitmaps\Offctlbr\Large\Color'
   
    Create Cursor tblImageList (FileName M)
   
    For lix = 1 To Adir(laImageList, Addbs(m.lcPath) + '*.*')
      Insert Into tblImageList Values (Addbs(m.lcPath) ++ laImageList[lix,1])
    Endfor
 
*!*        For lix = 1 To Adir(laImageList, "*.jpg")
*!*          Insert Into tblImageList Values (laImageList[lix,1])
*!*        Endfor
   
    Go Top
  Endproc

  Procedure Init
    With This.myGrid
      .ColumnCount = 2
      .RowHeight = 24
      .Anchor = 15

      With .Columns(1)
        .AddObject('edtBox','EditBox')
        .CurrentControl = 'edtBox'
        .Width = 720
        .Sparse = .F.
        .edtBox.Visible = .T.
      Endwith

      With .Columns(2)
          .Header1.Caption = ""
        .AddObject('imgImage','myImage')
        .CurrentControl = 'imgImage'
        .Width = 24
        .Sparse = .F.
        .imgImage.ImageFilename = "tblImageList.FileName"
        .imgImage.Visible = .T.
      Endwith
    Endwith
  ENDPROC
 
  PROCEDURE Destroy()
      ThisForm.Release()
      CLEAR EVENTS()
  ENDPROC
 
ENDDEFINE

**********

DEFINE Class myImage as Image
   ImageFileName = ""
 
   PROCEDURE Backstyle_Access()
      This.Picture = Evaluate(this.ImageFileName)
      Return This.BackStyle
   ENDPROC
 
ENDDEFINE

***********

hth

MarK
Great code! And a great example.
I did not know Evaluate() could see a picture file name and display the image. What does it use to do this? Can it reduce the image size?
 
The evaluate step only is necessary as MarKs code sets ImageFileName to a field name, instead of some field value. And there's a good reason for this, as you want each row to display its image, not just one for all rows. EVALUATE(fieldname) results in the field value, the filename.

>Can it reduce the image size?
In comparison with storing images in General fields, the image files are smaller most of the time, much smaller. Cases where this difference is not big are unimportant cases of very small images.

When I used dmusicants method of pasting an image via clipboard I got from snipping tool, vs saving the snipped image to a file, the file size was 5KB, vs the FPT General field size being 175KB, which is becuase it's the uncompressed BMP image in the clipboard. Just one example, you can experiment yourself with how large General field values are, just look at the fpt file size growth per image you paste.

General fields are okay in dmusicants situation of using legacy code he's not maintaining when it is what serves as storing them for him. It's not meaning, there's no alternative. Even @ SAY can display images from files, you're not depending on Generalfields storing and displaying images. I don't know what hinders him from creating a simple char field for an image name and make use of an image control instead. And as he's using something in the VFP9 IDE you could start make use of anything of VFP, like the image control with its Picture property, where you only need to set a filename of an image file to display it. So data would only need to have the filename, as in MarKs sample code.

MarKs code is also already addressing an advanced feature of displaying images in a grid, using a tricky way with the backstyle property, which is accessed by VFP when it paints a grid, so you can define an access method for it that then can set the Picture and you get individual pictures in the grid row. And that's where the magic of this is, not in EVALUATE, in an access method and backstyle and the insider knowledge the backstyle property is accessed by VFP whan painting a grid.

You usally would only display a single image outside of a grid control, say you have some textboxes about an employee displaying name, etc. and then one image control you set to display a photo. That's just needing an image control created on the _screen, for example, or on any form, with its Picture set to the filename.
 
Last edited:

Part and Inventory Search

Sponsor

Back
Top