Displaying a bitmap as background on a window or MDI client (32bit, 19 jan 1998)

Back Up Next

Author: Eric Aling
Download: Download wallpaper.zip ( wallpaper.zip 97Kb ):

There are cases that you might want to have a bitmap as background on your window. Normally, you would take a picture object for this. However, there is another possibility to do, using Windows API functions. Second advantage is that you can use this technique also for on a MDI client. Best thing to do is to subclass the window's procedure and intercept the WM_ERASEBKGND message. In that message, paint your bitmap instead. This seems nice however, we are not able to do this with PowerBuilder. You have to build it in i.e. C++ (DLL). I succeeded it in this way but also wanted it to do without an external DLL. So, I used some Windows API functions. For you, I've created a small PBL ( PB5 ). This pibble contains a non visualobject n_cst_wallpaper which does all the painting for you.Check out the example. I'll explain it a bit here.

One thing you have to do is in your POSTOPEN (important) event of your MDI frame code ( inv_wallpaper is an instance variable of type n_cs_wallpaper ):

inv_wallpaper = create n_cst_wallpaper
inv_wallpaper.of_SetWindow ( this, this.mdi_1 )
inv_wallpaper.of_SetBitmap ( 'alfa.bmp' ) 

If you want to display the bitmap on a normal window, use another of_SetWindow() method:

inv_wallpaper.of_SetWindow ( this )

Right. Now, there are some cases when the bitmap has to be repainted. First of all, when you resize the window. and secondly, when it gets activated again ( i.e. a messagebox is closed ). In these case, call the ue_paint event of the n_cst_wallpaper object like :

if IsValid(inv_WallPaper) then inv_WallPaper.event post ue_Paint()

Same thing for the sheets. When it gets resized, call that event of you MDI frame. Same thing when it is closed. That's all there is to it. Now, the object itself. It contains the following windows API functions, which are declared locally in the nonvisual userobject:

FUNCTION int ReleaseDC(ulong handle, ulong hDC) LIBRARY "User32.dll"
FUNCTION ulong SelectObject(ulong hDC, ulong hGDIObj) LIBRARY "Gdi32.dll"
FUNCTION int BitBlt(ulong hDC, int num, int num, int num, int num, ulong hDC, int num, int num, ulong lParam) LIBRARY "Gdi32.dll"
FUNCTION ulong CreateCompatibleDC(ulong hDC) LIBRARY "Gdi32.dll"
FUNCTION ulong GetDC(ulong handle) LIBRARY "User32.dll"
FUNCTION ulong LoadImageA( ulong hints, ref string lpszName, UINT uType, int cxDesired,int cyDesired,UINT fuLoad ) library "user32.dll" 
FUNCTION ulong GetObjectBitmap( ulong hgdiobj, int cbBuffer, ref s_bitmap bm ) library "gdi32.dll" alias for GetObjectA
FUNCTION boolean DeleteObject ( ulong hgdiobj ) library "gdi32.dll" 
FUNCTION boolean StretchBlt(ulong hDCdest, int x1, int y1, int w1, int h1, ulong hDCsrc, int x2, int y2, int w2, int h2, ulong lParam) LIBRARY "Gdi32.dll"

That seems to be a lot, well, it is. Most important function is the LoadImage() function, which creates a bitmapobject in memory and provides you the handle to it. Only thing to now is to show this bitmapobject. Therefore, we use the StretchBlt(), which displays a bitmap object on the device we want. I use the StretchBlt() function because this function can also be used to show the bitmap in other dimensions. Check out the object function of_SetWallPaper(). First the bitmap is created in memory using the LoadImage(). Then, with the GetObjectBitmap() function, a bitmap structure is filled so we knoe everything about the bitmap itself such as width and height. Secondly, the device is created, based on the window we want it on. On this device, the bitmap will be painted.

iul_hBitmap  = loadImageA(lul_Null,ls_Bitmap,0,0,0,80)
iul_hMdi     = handle( iw_Window )
iul_DcMdi    = GetDC( iul_hMdi )
iul_hDcMem    = CreateCompatibleDC(iul_DcMdi)

Then in the ue_paint event, the bitmap is painted on the device. Check out the instance boolean variables ib_Centre and ib_Resize. You can set only one at the time to TRUE. ib_Resize resizes the bitmap so that it fits in the window. ib_Centre centers the bitmap. In this case, you better use a big bitmap so that is fill the biggest possible window size.

There was a small problem that the background wasn't repainted properly and I costed me quite some time to solve it. The answer is remarkable simple: window.backcolor = window.backcolor !!!

Hope you enjoy this object. Good luck.

Back Up Next