JanetTerra
Mar 19, 2007
- "Changed 3 instances of handles passed as Long to handles passed as Ulong"
JanetTerra
Mar 19, 2007
- "Changed 3 instances of handles passed as Long to handles passed as Ulong"
Fun With Transparent Windows
Janet Terra with inspiration from Alyce Watson and Stefan Pendl
Windows 2000 and Windows XP both support transparent and semi-transparent windows. If you are designing a program for others, you will want to be sure the host computer supports transparent windows. This function, available at Alyce's Restaurant, will retrieve the OS version. A returned MajorVer of 5, setting the OSVersionFlag value to 1, indicates the required Windows 2000 or XP.
Once the programmer has established the host machine will support a transparent window, the window can be opened. Prior to Liberty BASIC v4.0 and Stylebits, the only way to code a transparent window was after opening the window and then issuing a SetWindowLongA to the User32.dll to give that window a layered quality. After the layered message was sent, a call to SetLayeredWindowAttributes was issued, again to the User32.dll to define the amount of transparency, more correctly called opacity. This is the technique used in John Richardson's LB Spier and discussed in the Transparent Window article at the Liberty BASIC Programming Wiki Site.
A more recent, and perhaps more effective, method of coding a transparent window is by including WS_EX_LAYERED in the window's addExtendedBits, the third parameter of the Stylebits command. As in the previous method, a call is then made to SetLayeredWindowAttributes in the User32.dll to define the amount of opacity.
The WS_EX_LAYERED addExtendedBits Stylebit
WS_EX_LAYERED is one of the Windows constants that is not recognized by Liberty BASIC. This doesn't mean that the style can't be used, though. It just means the numerical value of that Windows constant will need to be determined and assigned as either a literal or a variable. See Stylebits and Windows Constants for further discussion if needed. Here, we'll assign the correct value of 524288 to the variable WS.EX.LAYERED.
WS.EX.LAYERED = 524288 Stylebits #w, 0, 0, WS.EX.LAYERED, 0Having given the layered quality to the window, the opacity is then determined after the window is opened. This is done with a call to "SetLayeredWindowAttributes."
Looking at the four passed parameters more closely -
LWA_COLORKEY assigns one color of the window to be transparent. If the value of dwFLAGS is set to LWA_COLORKEY, then that one assigned color is the color passed in ColorRef and bAlpha is ignored. If the value of dwFLAGS is set to LWA_ALPHA, then the degree of opacity of the entire window is set to the value passed in bAlpha and ColorRef is ignored.
Demo of LWA_ALPHA
The Transparent Window demo works with the action LWA_ALPHA. The numerical value of the Windows constant LWA_ALPHA is 2. Since LWA_ALPHA is not a Liberty BASIC recognized constant, then that value (2) will be assigned to the user defined variable LWA.ALPHA.
Here is a simple modification of Transparent Window using the previously described constants and variables. This demo requires Windows 2000, Windows XP, or better.
Stefan Pendl's Demo Using LWA_COLORKEY
The inspiration for this article came from Stefan Pendl-
The Request: "I have read in the news letter 132 about how to make shaped windows, but it is a little bit confusing, is there a way faster then reading pixle by pixle, like setting one color as the part to be deleted, and if thats what the other examples do, can i make the drawing without haveing to use api calls for
drawing. my whole goal in total is to make an icon sized animal walk around on the screen. I have a program that does it already, but i would like to make my
own thing. Thanks in advance." Message #31512
Stefan's Reply: "How about making a fullscreen graphic window, make it transparent and use simple sprites ???"Message #31533
Stefan's Demo Message #31576 Be sure to run this demo from your Liberty BASIC root directory so the /SPRITES folder and cave1.bmp can be found.
† A recently identified bug in with a Timer Sub Event using Liberty BASIC is easily fixed by adding a WAIT statement in that fired sub event.
How cool is this!!
Closing Stefan's Demo
It may be difficult to regain focus of a transparent window. If you are finding difficulty closing Stefan's demo, press Alt - Tab until Sprite on Transparent Background is selected. Then press Alt - F4.
How Does Stefan's Demo Work?
In Stefan's Demo, a popup window is used. The background is white. White (&FFFFFF or 16777215) is set as the transparent color and no white pixels are drawn. Since the entire window is white, effectively, no pixel of the window is drawn. The window still provides a background for the sprite, though, and the sprite is content to bounce around that invisible window.
If you change
to
you'll see more clearly how only the white pixels (and the graphicbox is comprised of all white pixels) are not drawn. All non-white pixels, in this case, the window caption and borders are drawn as usual. Notice the distortion of the title bar as the white pixels of the title have not been drawn.
In Stefan's demo, the Stylebits _WS_EX_TOPMOST is used to keep the invisible window on top of all other windows, even if that window isn't the window with focus. This is essential to keeping the sprite visible to the viewer. Since the invisible window spans the entire display screen and remains topmost, how then is the user able to interact with other programs? Simply stated, the "SetLayeredWindowsAttributes" allows all mouseclicks to filter down through the invisible pixels to the window underneath.
Reversing Transparency
There may be times when you will want to restore the translucent window to the default opacity of 255 or undo the single color transparency. To restore opacity, simply issue another call to "SetLayeredWindowAttributes" passing the parameters bAlpha with the value of 255 and dwFLAGS with the value of LWA_ALPHA, or 2.
When the passed dwFLAGS parameter is LWA_COLORKEY, the transparent color can be made opaque by assigning ColorKey a value of a non present color or even by passing bAlpha with a value of 255 and dwFLAGS with the value of LWA.COLORKEY or 2. Either might be effective in many cases, but the best method is to simply remove the Layered attribute. Get the current value of the extendedAddBits of the window with "GetWindowLongA". To this result, subtract the value of WS.EX.LAYERED using the Bitwise Operand XOR. Write the new value back to the window by calling "SetWindowLongA".
A special Thank You to Alyce Watson -