Welcome To The Home Of The Visual FoxPro Experts  
home. signup. forum. archives. search. google. articles. downloads. faq. members. weblogs. file info. rss. print.
THUMBNAILS, ANYONE? (PART 2 OF 2)

The first part of this article talks about using Kodak Imaging Thumbnail along with other Kodak Imaging Active-X controls to display and print multi-pages graphic files. Of course, the Kodak Thumbnail can also display single-page files such as JPGs and BMPs but you cannot add or delete image pages on-the-fly from VFP using the said control. Although, it’s not the Thumbnail’s limitation; it’s by design. TIFF, DCX and WIFF are just among the few file formats that can handle one or more images while JPGs and BMPs don’t. It’s simple as that.

Yet, our real-life applications are not as “simple as that”. Agree? How many of you feel being pushed against the wall when writing an application that MUST include or must be CAPABLE of this and that feature? And you are pressured to do so by some commitments written on papers that you signed called… “contracts”? Or maybe by your boss who is barking to and fro at your back like a mad dog readying to kick your ass if you cannot deliver because he was the one who signed those contracts? On the other hand… self-inflected challenge cannot be ruled out, am I correct? Trying to prove to your ownself that you can outperform your previous work is such a sweet temptation. Are we nuts to compete against ourselves? Call it ego-tripping or whatever and, yes, we are crazy but I bet we are not a few.

So taking into account this predicament, it’s comforting to realize that we have other alternatives to reach our objectives. This article is another workaround to display thumbnails using VFP's native control objects. We basically need a grid, an image control and an OLE-bound control.

First Thing’s First
Before you run the sample form (Thumb2.SCX), be sure to change VFP’s current directory to where the sample form is located at your local machine. It is likely that some images will be displayed as icons or you will receive “OLE error code 0x80080005: Server execution failed” when you first run it. If one or both of these happen, don't fret. We will work out a solution for this matter a little later.



The Components
If you want to start from scratch, drag and drop a grid and an image control to a new form. In our sample, I gave the grid a name of “grdThumbnail” and the image as “imgViewport”.

In the form's Load event, let's create a cursor at run-time to handle the images to be displayed on the grid.
*** LOAD EVENT ***
LOCAL lcCurrentDir
WAIT WINDOW AT WROWS('Screen') / 2,(WCOLS('Screen') - LEN("Loading...")) / 2 "Loading..." NOWAIT
lcCurrentDir = ADDBS(SYS(5) + SYS(2003))
CREATE CURSOR CursImages (pImage G,mPath M)
APPEND BLANK
APPEND GENERAL pImage FROM 'DaleBust.Bmp'
REPLACE mPath WITH lcCurrentDir + 'DaleBust.Bmp'
APPEND BLANK
APPEND GENERAL pImage FROM 'Boseng1.Jpg'
REPLACE mPath WITH lcCurrentDir + 'Boseng1.Jpg'
APPEND BLANK
APPEND GENERAL pImage FROM 'Sample4.Gif'
REPLACE mPath WITH lcCurrentDir + 'Sample4.Gif'
LOCATE
KEYBOARD CHR(32)

*** END LOAD EVENT ***

Note that you have to load Foxtools.FLL in VFP5 prior to calling AddBS() function or, in this case, simply re-write it as Sys(5) + Sys(2003) + "\".

The cursor CursImages is made up of a general and a memo field to capture a copy of an image to a temporary handle and its corresponding path, respectively. A cursor is ideal for use in this instance so that you don't have to worry about memo bloat. Once you issue a CLOSE ALL or USE IN (ALIAS) commands, you can wave goodbye to cursors without extra housekeeping chores.

The commands that follow after Create Cursor… show how to populate CursImages with various types of image files programmatically but our sample form also includes a button to capture other images interactively.

Keyboard Chr(32) is just a lazy approach to remove the "Loading…" message from the screen.

In the form’s Init event, let’s refresh and set the focus to grdThumbnail.
*** INIT EVENT ***
WITH THISFORM.grdThumbnail
	.REFRESH
	.SETFOCUS
ENDWITH
*** END INIT EVENT ***


Let’s close the cursor once the form exits. In the Unload event, add the line Use In CursImages.

Going back to our grid and image controls, I modified their attributes in an attempt to mimic the appearances of Kodak Thumbnail and Image Edit controls. Naturally, you may change those non-critical properties based on your judgments. If you are designing the form visually, you don’t need to include the double quotes (“) when you enter character values in the Properties box.
*** grdThumbnail Properties ****
COLUMNCOUNT = 1
DELETEMARK = .F.
HEADERHEIGHT = 0
HEIGHT = 205
LEFT = 24
NAME = "grdThumbnail"
RECORDMARK = .F.
RECORDSOURCE = "cursImages"
ROWHEIGHT = 60
SCROLLBARS = 2 &&(vertical only)
TOP = 24
WIDTH = 120

*** grdThumbnail AfterRowColChange event ***
LPARAMETERS nColIndex
WITH THISFORM.imgViewport
	.PICTURE = ALLTRIM(CursImages.mPath)
ENDWITH

*** imgViewport Properties ****
BORDERSTYLE = 1 &&(fixed single)
HEIGHT = 204
LEFT = 180
NAME = "imgViewport"
STRETCH = 1 &&(isometric)
TOP = 24
WIDTH = 216




Make the grid’s column as the current control object (its name must be the one that appears on the Properties box). Click (select) the OLE bound control from the Form Control toolbar as shown in Figure 1 and drop it on the grid’s column. Remove the column’s textbox control since we don’t need it. Scan the Foxite forum for such posts on how to delete an object from the column – if you have a need of it.

Change the following column properties:
BackColor = RGB(192,192,192)
Sparse = .F.

In the Properties box, enter only 192,192,192 for the BackColor’s value. Transfer the focus to the OLE-bound control of the column and edit its following properties:
AutoActivate = 0 &&(manual)
ControlSource = "cursImages.pImage"
Stretch = 1 &&(isometric)


Isometric is somewhat similar to Kodak Image Edit’s FitTo method.

I rename the button which is used to add images to the grid as btnAddImage, the button to preview and print the images as btnPrnPreview and the checkbox to change the report mode as chkPreviewMode.
I created two report formats: one is to print the images as thumbnails (multiple images in a page) and the other prints one image on each page. ChkPreviewMode serves as our flag to determine which report format the user wants to preview or print. So make the value of the checkbox as boolean instead of the default numeric type. In the Init event of chkPreviewMode, add the line This.Value = .F.

The Click method of btnAddImage should contain codes similar to these:
LOCAL lcPicFile
lcPicFile = GETPICT('VFP6 graphic files:JPG,BMP,GIF,DIB;JPG;BMP;GIF;DIB',;
	'Get Picture','OK')
IF !EMPTY(lcPicFile)
	APPEND BLANK
	APPEND GENERAL pImage FROM (lcPicFile)
	REPLACE mPath WITH lcPicFile
	WITH THISFORM.grdThumbnail
		.AFTERROWCOLCHANGE
		.REFRESH
		.SETFOCUS
	ENDWITH
ENDIF


… And the Click method of btnPrnPreview checks the value of chkPreviewMode to determine the type of the report.

IF THISFORM.chkPreviewMode.VALUE
	REPORT FORM AsThumbs PREVIEW NOCONSOLE
ELSE
	REPORT FORM ImagePerPage PREVIEW NOCONSOLE
ENDIF


On the Sample Reports
Create a new report or open the sample reports and examine the controls. I dropped the Picture/ActiveX bound control on the Detail band and set its properties:

1. Picture from field: cursImages.pImage
2. Scale picture, retain shape. This is the same as isometric.
3. Fixed relative to the top of the band
4. Center picture checkbox is checked

Both reports have similar Picture/ActiveX bound control settings whose only difference is the layout of images that can fit on each page. See Figure 2 for the final output of the sample form and report.



An Error, a Quirk and a Workaround



The OLE error I mentioned a while ago is likely to take place if you associate an application to open a particular type of files based on their extensions and when this application can no longer be located. For example, MS-Word is usually associated to open DOC files. If, for some reasons, Word is removed from your system without proper updating of the Windows registry information on such particular file association, an error or a warning will occur whenever you try to open a DOC file. In Windows, a dialog box appears prompting you with a list of available applications to open the file with. However, in VFP, OLE error will be triggered and there is no second chance after that.

File association has also something to do with images being displayed as icons. It seems that only Paint-associated files (yes, the free Paint app that goes along with Windows) are perfectly recognized by VFP’s OLE-bound control object. This maybe a drawback since this means that your choice of format files are only limited to what Paint accepts. In my test, the sample TIFF used in my previous article can be opened with Paint without error but a black or empty screen is displayed instead of the assumed first page. Paint’s documentation explicitly specifies that it works with BMP, JPG and GIF but is silent about other formats. I would suggest that before you try to implement a certain graphic file format using OLE-bound control, try to open it first with Paint to see if the latter supports it. Otherwise, you may be putting yourself in a tight situation in order to find that the only way out is to use Active-X components which may not perfectly serve your purpose at all.

Now, to remove those icons on the grid, some VFP gurus advise that you find your target file via the Explorer, right-click it, select Properties and under the General tab, click the button Change and select Paint in the list. This SHOULD BE the safest and the easiest workaround. The bad news is, in all my conducted tests, this doesn’t work. So I’m afraid we have to take the risk to force our way in right into the heart of Windows registry.

Well, I know it’s pretty dangerous… if you don’t know what you’re doing. Still, I CAUTION you to take extra care when fiddling the Registry. A single misstep may lead you to re-install the operating system. Although, I’ve done this more than a dozen of times, follow my lead at your own risk. Honestly, by doing this, I’ve only crashed 6 hard disks so far… no, let me rewind it fast! I was just kidding, alright? The truth is, not a single system was ever been down. I swear I’m telling the truth this time.

Run the (dreaded) REGEDIT program. Click on “HKEY_CLASSES_ROOT” folder. Select “Edit” and “Find” from the menu and type in the “Find what:” box the file extension you want to edit (e.g. “bmp”, “jpg” or “gif”). After the value is searched and found, you will see the associated application under the Data column (see Figure 3).



Double-click “(Default)” under the Name column and edit the data value to “Paint.Picture” and click OK. Run the program again and, gee… pray that it will work.

Fox And Theories
VFP’s OLE-bound control can handle small animated GIFs (displayed as stills) but not large ones. Each time I try to append a considerably sized animated GIF, my VFP instance crashes. You can create a separate button for report printing from previewing rather than merge the two with one button as shown in our sample form and provide the …PROMPT clause when printing to give your users more options. Likewise, you can store the copy of images or just their paths into a permanent table.

Before I Retreat Graciously Towards My Foxhole…
VFP Image control doesn’t have zooming capabilities like the Kodak Image Edit control. Yet, personally, I think that grid, if properly managed, offers more flexibility than Kodak Thumbnail. You can mix the two approaches to have the best of both worlds, though, -- Active-X and pure native controls. The bottom line is, it all depends on your raw resources. If you use TIFF and other formats not supported by Paint, use Active-X. Otherwise, if the native controls can suffice just fine, then go for it. It will save you some extra pounds of application overhead.

Download code
Click here to download the code that is discussed in this article. The download is a zipfile. Its size is 76.650 bytes.

ABOUT THE AUTHOR: DALE DEDOROY

Dale Dedoroy Dale is a poor boy who finds joy in programming. He is currently the I.T. Officer of C.W. Mosser Environment Corporation.

FEEDBACK


Your Name: 
Your Feedback: 

Spam Protection:
Enter the code shown: