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 gkittelson on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Definitive APPEND GENERAL workaround for .bmp files (hopefully)

Status
Not open for further replies.

GriffMG

Programmer
Mar 4, 2002
6,335
FR
I have been increasingly getting problems with end-users importing .bmp files into my applications getting a 'corrupted' image (a bit of a squiggle and the file name below it).

In the past I've been able to resolve this with an 'assoc' command on the command line - but recently this has ceased to work on some machines. I've ended up fixing the problem remotely and sending back the data. Not ideal, looks naff too.

So research has been done and the problem lies in a registry key entry:

HKEY_LOCAL_MACHINE\SOFTWARE\CLASSES\.bmp

It needs to 'point' to Paint.Picture and sometimes doesn't.

So, in the code that does the import and APPEND GENERAL I now use this:

Code:
	#DEFINE HKEY_LOCAL_MACHINE          -2147483646  && BITSET(0,31)+2
	PRIVATE m.LOGO
	PRIVATE m.OLDVALUE
	M.LOGO = GETPICT("BMP","Select Logo file","OK")
	SELECT POPPJ
	IF !EMPTY(m.LOGO)
		IF MYFILE(m.LOGO)
			M.OLDVALUE = SETKEYVALUE(HKEY_LOCAL_MACHINE,"SOFTWARE\classes\.bmp","",'Paint.Picture')
			APPEND GENERAL LOGO FROM (m.LOGO) CLASS PAINT.PICTURE
			SETKEYVALUE(HKEY_LOCAL_MACHINE,"SOFTWARE\classes\.bmp","",m.OLDVALUE)
		ENDIF
	ENDIF

The important bit is the SETKEYVALUE bit, which returns the original setting of the spacified key. I use this to set the key value (remembering the old one) then do the APPEND GENERAL immediately afterwards and then restore the setting to the earlier one - in case that matters to some other piece of software I know nothing about.

In my main procedures file I have this function (you can put the #defines at the top of the procedure file if you like):

Code:
#DEFINE HKEY_CLASSES_ROOT           -2147483648  && BITSET(0,31)
#DEFINE HKEY_CURRENT_USER           -2147483647  && BITSET(0,31)+1
#DEFINE HKEY_LOCAL_MACHINE          -2147483646  && BITSET(0,31)+2
#DEFINE HKEY_USERS                  -2147483645  && BITSET(0,31)+3
#DEFINE REG_SZ 				1	&& Data string



FUNCTION SETKEYVALUE
	* This routine sets a key value
	* Note: this routine only handles data strings (REG_SZ)
	LPARAMETER m.NREGKEY,m.CLOOKUPKEY,CVALUENAME,CVALUE
	LOCAL NVALUESIZE,NERRCODE,NSUBKEY,REGTYPE
	LOCAL m.OLDVALUE,NOLDVALUESIZE

	NSUBKEY = 0
	* Make sure we null terminate the value
	CVALUE = m.CVALUE+CHR(0)
	NVALUESIZE = LEN(m.CVALUE)
	REGTYPE = REG_SZ
	M.OLDVALUE = ""

	DECLARE INTEGER RegSetValueEx IN Win32API ;
		INTEGER hKey, STRING lpszValueName, INTEGER dwReserved,;
		INTEGER fdwType, STRING lpbData, INTEGER cbData

	DECLARE INTEGER RegOpenKey IN Win32API ;
		INTEGER nHKey, STRING @cSubKey, INTEGER @nResult

	DECLARE INTEGER RegQueryValueEx IN Win32API ;
		INTEGER nHKey, STRING lpszValueName, INTEGER dwReserved,;
		INTEGER @lpdwType, STRING @lpbData, INTEGER @lpcbData



	REGOPENKEY(m.NREGKEY,m.CLOOKUPKEY,@NSUBKEY)

	IF NSUBKEY <> 0

		NOLDVALUESIZE = 1
		* Get the size of the data in the value
		REGQUERYVALUEEX(NSUBKEY, CVALUENAME, 0, @REGTYPE, @m.OLDVALUE, @NOLDVALUESIZE)

		* Make the buffer big enough
		M.OLDVALUE = SPACE(NOLDVALUESIZE)
		REGQUERYVALUEEX(NSUBKEY, CVALUENAME, 0, @REGTYPE, @m.OLDVALUE, @NOLDVALUESIZE)


		* Set the key value here
		M.NERRCODE = REGSETVALUEEX(NSUBKEY,m.CVALUENAME,0,REG_SZ,m.CVALUE,m.NVALUESIZE)
	ENDIF
	CLEAR DLLS REGQUERYVALUEEX
	CLEAR DLLS REGSETVALUEEX
	CLEAR DLLS REGOPENKEY

	RETURN(m.OLDVALUE)

And it seems to work.

Please excuse a) the scruffy coding and b) anyone who recognises their plagurised code!

B-)

Regards

Griff
Keep [Smile]ing
 
Isn't it easier, just:
APPEND GENERAL LOGO FROM (m.LOGO) CLASS PAINT.PICTURE
w/o plaing with registry?
I am curious because I never keep Pictures in DataBase.

Borislav Borissov
VFP9 SP1, SQL Server 2000/2005.
 
Hi Borislav Borissov,

The APPEND GENERAL seems to ignore the specified class (certainly in VFP 5/6, I've not tested it above that yet) and takes an OLE reference from the registry in the key I noted above.

When people install camera software, or specialist picture editting/viewing or even some email software on their machines that key gets changed from Paint.Picture to something else (the test machine I was looking at had OSIBMP FILE) and then VFP seems to get a bit confused.

I don't store a lot of images in my databases, but I like to have the companies logo available for printing on all the reports and sometimes one or two others for 'branding' printed materials - or for electronic signatures.

Because there are relativey few images there really isn't a bloat problem and it mostly works quite well. Sometimes it doesn't though.

So, with about 400 remote users - some who have the problem and some who don't (yet) and some users IT departments which are more helpful than others, I just need a transparent solution. And this does seem to work thus far.



Regards

Griff
Keep [Smile]ing
 
What I do is to copy Image to some folder where all users ha access (usualy a subfolder of my Data Folder). Then I keep just path to that image in Table. That way you preseve youd Table from growing and preserve pictures if some corruption with table happens.
BUT your approach is great for these developers wich store Pictures in Tables. Thank you.

Borislav Borissov
VFP9 SP1, SQL Server 2000/2005.
 
Hi Borislav,

I do the same thing when I need a lot of images associated with the database.

One question though, how to you accommodate a report where each line (for example) needs an image associated with it - and printed?



Regards

Griff
Keep [Smile]ing
 
Now I use VFP9. When you insert OleBound Control in report, there is Choise what type you use for Picture. When you set it to Expression or Variable name and bind it to cursor Field all pictures are printed well.

When I used VFP8 (or smaller) I always added a general field to cursor and append general in that cursor with pictures. Becuase I always use cursors for my reports (never based a report directly to table from my DB) I didn't care what server is registered in user computer to handle pictures.

Borislav Borissov
VFP9 SP1, SQL Server 2000/2005.
 
Hi Borislav

So I take it VFP9 allows a kind of 'runtime evaluation' of the filename (to all intents and purposes) That is a good difference.

I'm not sure I follow the other bit though, am I to understand that an 'append general' into a cursor will always work properly, whereas one into a table won't sometimes?

Martin



Regards

Griff
Keep [Smile]ing
 
All,
1) Dump .bmp and use .jpg... it's been supported for AGES now, and is much smaller.
2) Set Control source to "Expression or Variable Name" button.
3) DON'T use general fields... use MEMO field instead, with just path and file name to your image file. (MUCH smaller .dbf, just a reference and does not give a WET SLAB about what vuewer is involved...
4) Print like the wind... NO OLE corruption EVER, no control issues EVER.

Extra: use the same thing in your form, only use the Image contorl instead of OLE bound control, and set the .Picture property = to the Memo field, (Which reslolves to <Path\Filename> and perfect images EVERY time, especially if you use .JPG...

Just my recommendation.


Best Regards,
Scott

&quot;Everything should be made as simple as possible, and no simpler.&quot;[hammer]
 
Scott,

That's all good advice.

I just tested it in VFP 6 - and even without my tweak it works ok for .jpg files!

Thank you.


Regards

Griff
Keep [Smile]ing
 
Hey,
The man provides solution for these developers that didn't use VFP9.

Borislav Borissov
VFP9 SP1, SQL Server 2000/2005.
 
That's ok Barislav - every contribution is gratefully received!



Regards

Griff
Keep [Smile]ing
 
Sorry Borislav!

B-(

Regards

Griff
Keep [Smile]ing
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top