Moving a Glass Object


Now you have everything necessary to draw a transparent image anywhere. The Draw method does the work. Users can call the Draw method themselves, but generally, they won’t. Instead, they’ll call the Move method or modify the Left and Top properties, which will, in turn, call the Draw method.


Conceptually, the Draw method works a lot like the GDI DrawIcon function. The code is on the following page.

Public Sub Draw()
With cvsDst
BugAssert fExist
If fVisible = False Then Exit Sub

‘ Copy old background to its last location
If xOld <> -1 Then
Call BitBlt(hdcDst, xOld, yOld, dxSrc, dySrc, _
hdcBack, 0, 0, vbSrcCopy)
End If
‘ Save current background and position for next time
Call BitBlt(hdcBack, 0, 0, dxSrc, dySrc, _
hdcDst, xLeft, yTop, vbSrcCopy)
‘ Create cache copy of background to work on
Call BitBlt(hdcCache, 0, 0, dxSrc, dySrc, _
hdcDst, xLeft, yTop, vbSrcCopy)
xOld = xLeft: yOld = yTop
‘ Save color and set to white and black
Dim clrBack As Long, clrFore As Long
clrBack = GetBkColor(hdcCache)
clrFore = GetTextColor(hdcCache)
Call SetBkColor(hdcCache, vbWhite)
Call SetTextColor(hdcCache, vbBlack)
‘ Mask the background
Call BitBlt(hdcCache, 0, 0, dxSrc, dySrc, hdcMask, 0, 0, vbSrcAnd)
‘ Put image in hole created by mask
Call BitBlt(hdcCache, 0, 0, dxSrc, dySrc, hdcImage, 0, 0, vbSrcPaint)
‘ Restore color
Call SetBkColor(hdcCache, clrBack)
Call SetTextColor(hdcCache, clrFore)
‘ Put finished cache on screen
Call BitBlt(hdcDst, xLeft, yTop, dxSrc, dySrc, _
hdcCache, 0, 0, vbSrcCopy)
End With
End Sub

This method, like every other method and property in CPictureGlass, starts out by asserting that the object exists. This assertion will fail if the user declares a CPictureGlass object but then tries to use it before initializing with the Create method. Draw also terminates without doing anything if fVisible (controlled by the Visible property) is False.


Draw next restores the previous background (if there is one) and saves two copies of the current background—one to work on and one to restore next time. Without this step, each drawing would work but wouldn’t erase itself; you’d see a trail of image “droppings.” Finally you mask out the shape of the image on the background of the temporary copy and plunk the image (with its inverted


Transparent Blits


It has been alleged that some video drivers support transparent blits. I have never come across one, and so, being unable to test the feature, I didn’t build it into CPictureGlass. However, the Video tab in the All About program (ALLABOUT­.VBP) will tell you whether your system supports transparent blits. If so, you could do faster, smoother animation with the following code:

If GetDeviceCaps(hdcDst, CAPS1) And C1_TRANSPARENT Then
ordModeOld = GetBkMode(hdcDst, NEWTRANSPARENT)
clrOld = SetBkColor(hdcDst, clrMask)
Call BitBlt(hdcDst, xLeft, yTop, dxSrc, dySrc, _
hdcImage, 0, 0, NEWTRANSPARENT)
Call SetBkMode(hdcDst, ordModeOld)
Call SetBkColor(hdcDst, clrOld)
End If

This is air code because I had nothing to test it with. This feature has been around long enough that hardware vendors ought to support it, and maybe some do. But not for the hardware I use.


background) into the hole. Only when the whole image and background have been assembled off-screen do you copy the temporary hdcCache to the screen. You could do all this blitting and color changing directly on the container, but you’d end up with a whole lot of flicker.