Transparent Image Static Class

While writing an about box recently, I added a image
using a static.  I used the standard gray for the background in the
image.  Looked great!  Alright, run over to the client and install the
application on his system.  Run the program and while testing the menus,
open the about box – puke.  Why?  The background was the standard gray
but the computer in question had a darker, redder gray.

Back to the drawing board.  Search through the documentation and find
MaskBlt().  Great!  Implement it and test it on my machine (Windows NT
– see where this is going?).  Looked great!  Alright run over to the
client and try again – worse, no image at all.

Scratch head for a while then see on the bottom of the documentation. 
MaskBlt() only works on Windows NT, not Windows 98 – duh Microsoft? 
Alright, this sucks, what now?  Read more documentation and see that
MaskBlt() is not done by the driver, but by GDI in NT…hmmm…can I do it for
GDI if GDI can’t?  Sure can.  Recode, test it on Windows 95, Windows
98, Windows NT and Windows 2000 – woohoo!

One note – DO NOT USE THIS FOR ANIMATION OR OTHER
TIME-CRITICAL USES.  This code uses three Blt’s under NT (and remember, MaskBlt() does some internal) and if the MaskBlt() fails (like
under Windows98), this code uses 7 (!!!) Blt’s.  One way to increase performance
if needed is to cache the buffer and mask and use these cached bitmaps.

How to use it?

The control itself is just a derived class from CStatic with an OnPaint()
handler.  So to use it in your code, just make the background (transparent
area) of the picture to light magenta (0xFF00FF) and add a CStatic member to the
dialog class.  Then change the definition from CStatic to
CTransparentImage.  Done!

Now, how does it work?


To draw transparently with NT, take the bitmap, blt it to a off-screen
DC.  Next create a mask using a monochrome DC with the background color set
to the transparent color by blt’ing from the off-screen DC.  Lastly, use
MaskBlt() to blt the off-screen to the paint DC using the mask bitmap using the
ROP4 code 0xCCAA0020 (mask is white where image does NOT paint).  If
MaskBlt() fails, then we need to do a bunch more work.  First, grab a copy
of the screen into a second off-screen (copy) DC.  ‘And’ the mask with this
copy DC to create black where the image will go.  Next, use the special
ROP3 code 0x00220326 to ‘and’ the inverse of the mask with the buffer DC to
create black around the image.  Now ‘or’ the copy and the buffer together
to make a complete picture.  Last, blt the whole mess to the screen.


To see the code for this, see the OnPaint() message handler in the
TranparentImage.cpp file.


One other note – this code does not handle stretching.  If you need to
stretch, create the buffer DC to the client size of the static, then the first
blt in the function which copies the bitmap to the buffer should use StretchBlt
instead.

Download demo project – 53.1KB

More by Author

Get the Free Newsletter!

Subscribe to Developer Insider for top news, trends & analysis

Must Read