Monday, September 10, 2007

Using VFP Resource File

There are several ways to use the resource file. To load a bitmap from RT_BITMAP resource section, you can use GDI or GDI+ to load directly into a (handle) bitmap
[CODE]
*** Updated: Nov 23, 2007 - 07:45 AM


*** API Declaration
Declare Long LoadLibrary in Kernel32 String cFilename
Declare Long FreeLibrary in Kernel32 Long hModule

Declare Long LoadImage in User32 ;
Long hInstance, String lpszName, Long uType, ;
Integer cxDesired, Integer cyDesired, Long nLoadFlags

Declare Long GdipCreateBitmapFromResource in GdiPlus.dll ;
Long hInstance, String cBitmapName, Long @O_Bitmap

hBitmap = 0
hLibrary = LoadLibrary( 'myResource.LIB' )
If (hLibrary != 0)
** Use GDI
cResName = 'myImage' && Resource name
hBitmap = LoadImage( hLibrary, cResName, 0, 0, 0, 0 )

** Use GDI+
wResName = strconv( strconv( cResName + chr(0), 1 ), 5 )
GdipCreateBitmapFromResource( hLibrary, wResName, @hBitmap )

FreeLibrary( hLibrary )
endif

If (hBitmap != 0)
** We have a bitmap, do what you want to do here
** Don't forget to delete the bitmap,
** DeleteObject() for GDI, GdipDisposeImage() for GDI+
endif
[/CODE]

I also shown you about putting an image (PNG) to custom resource section. Since the image was put as a raw data, you can only load it back as raw data. After you get the raw data, you can save it to a file, or you can also create a stream data to create the bitmap from the stream. GdipCreateBitmapFromResource() doesn't work for this resource type.
[CODE]
*** API Declaration
Declare Long FindResource in Kernel32 as FindResourceStr ;
Long hModule, String lpName, String lpType

Declare Long SizeofResource in Kernel32 Long hModule, Long hResource
Declare Long LoadResource in Kernel32 Long hModule, Long hResource
Declare Long LockResource in Kernel32 Long hResData

cData = ''
hLibrary = LoadLibrary( 'myResource.LIB' )
If (hLibrary != 0)
cResName = 'myPNG'
hResource = FindResourceStr( hLibrary, cResName, 'MYIMAGES' )
If (hResource != 0)
nSize = SizeofResource( hLibrary, hResource )
hData = LoadResource( hLibrary, hResource )
pData = LockResource( hData )
cData = sys( 2600, pData, nSize )
endif
FreeLibrary( hLibrary )

endif

If !empty( cData )
** We got the raw data, do what you want to do here
endif
[/CODE]

In my last tips, I didn't show you all the predefined resources. there are several others actually, such as RT_ICON, RT_CURSOR, etc. It is my intention to not using resource file for other images type. Because those images are usually use only with VFP Image object. So, you can still use your project to put other images. Just consider to use the resource file when you have to distribute files physically that you can't put in your project.

Happy coding!


Monday, September 03, 2007

Creating a VFP Resource File

What is a resource file? A resource file is sort of a container file. Using resource file, you only have to distribute one single file instead of distribute many files. You can use this file to put any file such as image (BMP, JPG, PNG, etc). You can use this to distribute a hidden report file. You can also use this file in conjunction with my OwnerDrawn menu class. In short, you can use this file for many purposes.

How to create it? Very simple! Here is the step:
1. Create a new program (for the Main program)
2. Put a QUIT command into it
3. Create a new project.
4. Add the Main program into the project
5. Uncheck the project debug info
6. Build the project as an EXE, but name it as "myResource.LIB" (give the extension yourself)

Once you created your LIB file, how can you put your file into it? You must put the raw data into the resource file. There are three WinAPI functions to help you to put the raw data into it. BeginUpdateResource(), UpdateResource() and EndUpdateResource().

Let's look at the example. Suppose you want to put an image file ("myPNG.PNG") into it, here's how you do it:
[CODE]

*** Updated: Nov 23, 2007 - 07:45 AM

*** API Declaration
Declare Long BeginUpdateResource in Kernel32 ;
String cFileName, Long bDeleteExistingResources

Declare Long UpdateResource in Kernel32 as UpdateResourceStr ;
Long hUpdate, String lpType, String lpName, ;
Short wLanguage, String lpData, Long nLenData

Declare Long UpdateResource in Kernel32 as UpdateResourceStr2 ;
Long hUpdate, Long lpType, String lpName, ;
Short wLanguage, String lpData, Long nLenData

Declare Long EndUpdateResource in Kernel32 ;
Long hUpdate, Long fDiscard

*** Start code
cImageFile = 'myPNG.PNG'
cResFile = 'myResource.LIB'
cResGroup = 'MYIMAGES' && a resource section group, make uppercase
cResName = upper( JustStem( cImageFile ))
&& a resource name, make uppercase


cRawData = FileToStr( cImageFile )
hResFile = BeginUpdateResource( cResFile, .F. )

If (hResFile != 0)
UpdateResourceStr( hResFile, cResGroup, cResName, 0, ;
cRawData, len( cRawData))
EndUpdateResource( hResFile, .F. )

endif
[/CODE]

Suppose you want to put an image file that has a BMP extension, you better put it into the predefined resource section group. Change the code above into this:

[CODE]
*** Start code
cImageFile = 'myImage.BMP'
cResFile = 'myResource.LIB'
nResGroup = 2 && RT_BITMAP, a predefined resource section group
cResName = upper( JustStem( cImageFile ))
&& a resource name, make uppercase

cRawData = FileToStr( cImageFile )
cRawData = substr( cRawData, 15 ) && eliminate BITMAPFILEHEADER structure (14 chars)
hResFile = BeginUpdateResource( cResFile, .F. )
If (hResFile != 0)

UpdateResourceStr2( hResFile, nResGroup, cResName, 0, ;
cRawData, len( cRawData))
EndUpdateResource( hResFile, .F. )

endif
[/CODE]

That's it, try and experiment yourself. In the next tips, I will show you how to use the resource file.

Happy coding!