Style bits
If you were writing programs for Windows in C, you’d need to specify style bit flags in the CreateWindow function every time you wanted a new window. C doesn’t have a form properties window. You’ll recognize some of the style bits because many of them correspond directly to form properties.
WinWatch gets the style bits for each window and displays them in the Window information area. GetWndStyle converts the bit flags to a string:
Function GetWndStyle(hWnd) As String
Dim af As Long, s As String
BugAssert hWnd <> hNull
‘ Get normal style
af = GetWindowLong(hWnd, GWL_STYLE)
If af And WS_BORDER Then s = s & “Border “
If af And WS_CAPTION Then s = s & “Caption “
If af And WS_CHILD Then s = s & “Child “
§
Windows provides shortcut functions to get style information about the current view state of the window. GetWndView uses these functions to create the View heading:
Public Function GetWndView(hWnd) As String
Dim s As String
BugAssert hWnd <> hNull
s = IIf(IsWindowVisible(hWnd), “Visible “, “Invisible “)
s = s & IIf(IsWindowEnabled(hWnd), “Enabled “, “Disabled “)
s = s & IIf(IsZoomed(hWnd), “Zoomed “, sEmpty)
s = s & IIf(IsIconic(hWnd), “Iconic “, sEmpty)
GetWndView = s
End Function
You can learn a lot about how forms really work by studying the WinWatch display. Run a compiled version of WinWatch and a test form with test controls in the Visual Basic environment. Change various properties and see how they affect the Window information display (after you click the Refresh button). You can probably guess most of the effects, but some might surprise you. For example, the ClipChildren style bit corresponds to the form’s ClipControls property.
You can also change style bits, but it’s not as easy as you might expect. Changing the state of the bits doesn’t necessarily change the state of the window; it just knocks the bits and the state out of sync. But there is a way.
The Fun ’n Games project in Chapter 7 has a Clip Controls check box that determines whether the graphics drawn by the program write over or under the controls on the form. In theory you should be able to toggle the ClipControls property, but in reality Visual Basic lets you change the ClipControls property only at design time. It turns out, though, that ClipControls is nothing more than the WS_CLIPCHILDREN style bit. To change the ClipControls functionality (but not the property), you simply call this procedure:
Sub ChangeStyleBit(hWnd As Long, f As Boolean, afNew As Long)
Dim af As Long, hParent As Long
af = GetWindowLong(hWnd, GWL_STYLE)
If f Then
af = af Or afNew
Else
af = af And (Not afNew)
End If
Call SetWindowLong(hWnd, GWL_STYLE, af)
' Reset the parent so that change will "take"
hParent = GetParent(hWnd)
SetParent hWnd, hParent
' Redraw for added insurance
Call SetWindowPos(hWnd, HWND_NOTOPMOST, 0, 0, 0, 0, _
SWP_NOZORDER Or SWP_NOSIZE Or _
SWP_NOMOVE Or SWP_DRAWFRAME)
End Sub
The first part of the code is straightforward, but what the heck is that call at the end? The SetWindowPos API function sets the window position and, as a side effect, renews all of the style bits. The trick to this hack is getting the function to perform the side effect without performing the primary effect. The second through sixth parameters of SetWindowPos change the z-order, location, or size of a window, and the final parameter tells how to interpret the earlier parameters. In this case, you pass three NO flags telling the function to ignore it all. By themselves, these flags would simply disable the function, so you must add the SWP_DRAWFRAME flag to ensure that the window gets updated. Pretty slimy, huh? I haven’t experimented much with this function, so don’t blame me if it doesn’t always work for all style bits or for windows without frames.
I got most of this hack from an article called “Slimy Windows Hacks” in the February 1995 issue of Visual Basic Programmer’s Journal. The masked author identified himself only as Escher.
I can’t reveal his identity (although he has given broad hints
at speeches at the VBITS conference), but I will note that the
Acknowledgments section of this book gives proper credit to all contributors. Later I added the part about resetting the parent
to the current parent. I borrowed this insurance technique from similar code in the Microsoft Foundation Classes (MFC) library. I’m not sure whether it makes any difference.