Chapter 11. The Windows API

The Windows API has a bad rap among many Access programmers who think it’s too hard to figure out, too hard to call, or just plain mysterious. We’re here to prove that none of these is the case—even if you’ve never seen the Windows API programmer’s reference, you can use the Windows API, given some help. In this chapter, we’ll present some interesting uses of the Windows API from within Access, with example forms and modules for each solution. In most cases, using these in your own applications entails little more than simply importing a module or two and then calling the functions. We’ve divided the solutions in this chapter into three broad categories, as follows:

The Windows user interface

You’ll learn how to remove a form’s system menu, how to maximize and minimize buttons at runtime, and how to draw attention to a specific form by flashing its titlebar or icon. We’ll discuss language-independent classification of keypresses, so you can monitor exactly what keys have been pressed. We’ll also show how to restrict mouse movement to a specific area on the screen.

The Windows shell

You’ll learn how to have asynchronous code run another program and pause until the other program is done before continuing. We’ll demonstrate a method for shutting down Windows under program control and show you all the options of the associated API functions. You’ll learn to find and run an application, given an associated data file, and how to determine if the application is already running. You’ll see how to retrieve a list of all open top-level windows (generally, one per application) and how to close a window from your VBA code.

Files, drives, and hardware

You’ll learn how to set file date and time stamp information, which is useful if you’re moving files around from within applications or making backups based on dates. You’ll also learn how to retrieve information about your disk drives, hardware, and the current Windows environment as well as how to connect and disconnect from remote network devices programmatically or using standard dialogs.

Tip

Most of the solutions in this chapter instruct you to import one or more modules from the example databases. In each case, the module contains the Windows API user-defined types and function declarations you need for the example. If you’ve already imported a module with the specified name for a previous solution, you can skip it, since all modules with matching names contain the same code.

Remove a Form’s System Menu and Maximize/Minimize Buttons

Problem

Access makes it easy to remove the control box (often called the system menu) and the minimize and maximize buttons when you design forms, but there doesn’t seem to be a way to do this at runtime. You have an application for which you’d like to be able to remove these buttons to control how users interact with the application. Is there a way to remove these items and then replace them later?

Solution

Removing or replacing these window controls requires changing the style bits for the particular window. Every window maintains a 32-bit value that describes its physical characteristics: for example, its border type and the existence of scrollbars, a system menu, and the minimize and maximize buttons. The values are stored as bit flags, in which the state of a single bit in the 32-bit value indicates the value of some characteristic of the window. In general, you can’t change the state of many of these flags without recreating the window; by setting or clearing the bits in the window’s style value, however, you can force the system menu and the minimize/maximize buttons to appear or disappear.

Load and run frmSystemItems from 11-01.MDB. This form, shown in Figure 11-1, allows you to add or remove the control menu, the minimize button, and the maximize button from the current form. Select items on the form to make the corresponding items visible, or deselect to remove them. Once you’ve made your choices, click on the Execute button, and the code will remove or replace the items you’ve chosen.

frmSystemItems allows you to remove or replace any of the system items

Figure 11-1. frmSystemItems allows you to remove or replace any of the system items

To include this functionality in your own applications, follow these steps:

  1. Import the module basControl from 11-01.MDB.

  2. To remove or replace a form’s system items, call the acbFormSystemItems subroutine, passing to it the four parameters shown in Table 11-1.

    Table 11-1. Parameters for acbFormSystemItems

    Parameter

    Type

    Value

    frm

    Form

    Reference to the current form

    fSystemMenu

    Integer

    True = Show system menu; False = Hide

    fMaxButton

    Integer

    True = Show maximize button; False = Hide

    fMinButton

    Integer

    True = Show minimize button; False = Hide

    For example, the following statement, called from a button’s Click event in a form’s module, will show the system menu but will hide the minimize and maximize buttons:

    acbFormSystemItems Me, True, False, False

    Though Access does provide the ControlBox, MaxButton, and MinButton properties for forms, they’re read-only once the form is in use; if you need to alter these properties at runtime, you’ll need to use acbFormSystemItems instead of changing the properties directly.

Discussion

The bulk of the work in controlling these system items takes place in the private HandleStyles function in the basControl module. This function accepts a window handle (the hWnd property of a form) and three True/False values indicating which options you want to see and which you want removed. Like every window, the window you want to alter maintains a 32-bit value, its style value. Within that long integer, each of the 32 positions represents one of the possible styles for the window. If the bit is 1, the style is set on; if it’s 0, the style is set off. HandleStyles builds up two long integers, each containing a series of 32 bits. The first, lngStylesOn, contains all 0s, except for the bits representing the styles you want turned on, which contain 1s. The other, lngStylesOff, contains all 1s, except for the bits representing the styles you want turned off, which contain 0s.

Using the AND operator to combine the current window style with lngStylesOff sets each style whose bit contains 0 in lngStylesOff to be 0. Using the OR operator to combine the current window style with lngStylesOn sets each style whose bit contains 1 in lngStylesOn to be 1. For example, suppose the current window style value is this:

10001000 10001010 10101011 01101101

The value in lngStylesOff contains 1s in all positions except the ones you want turned off, which contain 0s. If the value of lngStylesOff is this:

11111111 11111111 11111111 11111011

the result of using the AND operator with the original style and lngStylesOff will be this:

10001000 10001010 10101011 01101001

The value in lngStylesOn contains 0s in all positions except the ones you want turned on, which contain 1s. If the value of lngStylesOn is this:

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 = acb_apiSetWindowLong(hWnd, GWL_STYLE, _
  (acb_apiGetWindowLong(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, fSystemMenu As Boolean, _
   fMaxButton As Boolean, fMinButton 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 fSystemMenu Then
      lngStylesOn = lngStylesOn Or WS_SYSMENU
   Else
      lngStylesOff = lngStylesOff And Not WS_SYSMENU
   End If
   If fMinButton Then
      lngStylesOn = lngStylesOn Or WS_MINIMIZEBOX
   Else
      lngStylesOff = lngStylesOff And Not WS_MINIMIZEBOX
   End If
   If fMaxButton Then
      lngStylesOn = lngStylesOn Or WS_MAXIMIZEBOX
   Else
      lngStylesOff = lngStylesOff And Not WS_MAXIMIZEBOX
   End If

   ' Set the attributes as necessary.
   HandleStyles = acb_apiSetWindowLong(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 acb_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)
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.191.218.84