Access Cookbook - Ken Getz [226]
00000000 00000000 00010000 10000000
the result of using the OR operator with lngStylesOn and the result of ANDing the original style with lngStylesOff will be this:
10001000 10001010 10111011 11101001
This final result will have three changed values: one bit that was 1 is now 0 due to the settings in lngStylesOff, and two bits that were are now 1 due to the settings in lnStylesOn.
To retrieve and replace the window's style information, the code uses the GetWindowLong and SetWindowLong API functions. Given a window handle and a flag (GWL_STYLE) indicating which 32-bit value to retrieve or set, these functions allow you to get the current value, do your work with it, and then set it back. This is the line of code that does all the work:
HandleStyles = SetWindowLong(hWnd, GWL_STYLE, _
(GetWindowLong(hWnd, GWL_STYLE) And lngStylesOff) _
Or lngStylesOn)
It sets the window style to be the value GetWindowLong retrieved, combined with the two style flags the code previously built up based on your choices.
The entire HandleStyles procedure looks like this:
Private Function HandleStyles(ByVal hWnd As Long, blnShowSystemMenu As Boolean, _
blnShowMaxButton As Boolean, blnShowMinButton As Boolean) As Long
Dim lngStylesOn As Long
Dim lngStylesOff As Long
On Error GoTo HandleStylesExit
' Set all bits off.
lngStylesOn = 0
' Set all bits on.
lngStylesOff = &HFFFFFFFF
' Turn ON bits to set attribute; turn OFF bits to turn attribute off.
If blnShowSystemMenu Then
lngStylesOn = lngStylesOn Or WS_SYSMENU
Else
lngStylesOff = lngStylesOff And Not WS_SYSMENU
End If
If blnShowMinButton Then
lngStylesOn = lngStylesOn Or WS_MINIMIZEBOX
Else
lngStylesOff = lngStylesOff And Not WS_MINIMIZEBOX
End If
If blnShowMaxButton Then
lngStylesOn = lngStylesOn Or WS_MAXIMIZEBOX
Else
lngStylesOff = lngStylesOff And Not WS_MAXIMIZEBOX
End If
' Set the attributes as necessary.
HandleStyles = SetWindowLong(hWnd, GWL_STYLE, _
(acb_apiGetWindowLong(hWnd, GWL_STYLE) And lngStylesOff) _
Or lngStylesOn)
' The 1 in the third parameter tells the window
' to repaint its entire border.
Call SendMessage(hwnd, WM_NCPAINT, 1, 0)
HandleStylesExit:
Exit Function
End Function
After the style bits are set, there's still one issue left: you must coerce the window into repainting itself so the changes become visible. Simply changing the styles isn't enough, because they don't become visible until the next time the window repaints its border.
If you resize the form, Access repaints the border, but there's no reasonable programmatic way to do this. To solve the problem, the procedure adds one more line. It calls the SendMessage API, which sends a specific message to any window (this time, it sends a message to the form itself ). The message it sends, a constant named WM_NCPAINT, tells the form to repaint its non-client area (that is, its border):
' The 1 as the third parameter tells the window
' to repaint its entire border.
Call acb_SendMessage(hwnd, WM_NCPAINT, 1, 0)
11.2. Flash a Window's Titlebar or Icon
Problem
With so many windows open in your Access applications, it can be difficult to force your user's attention to a specific form. Is there a way to make the titlebar flash so that a form really stands out?
Solution
Windows supplies a simple API call, FlashWindow, that allows you to flash the titlebar of a form or its icon (if it's iconized) on and off. This solution will demonstrate how you can use the FlashWindow API call to draw attention to a specific form.
To include this functionality in your own applications, follow these steps:
Add this API declaration to your code in the declarations section of the form's module:
Private Declare Function FlashWindow Lib "User32" _
(ByVal hWnd As Long, ByVal lngInvert As Long) As Long
In our example, the declaration is in the module for frmControlFlash.
Create a module-level variable (mhWnd in our example) to hold the flashed form's window handle:
Dim mhWnd As Long
Create a procedure attached