Introduction
Controlling Form and Report Views with Windows API
In Microsoft Access, forms and reports can normally be shown in four modes: Hidden, Minimized, Maximized, or Normal. While Access provides built-in commands ( DoCmd.Maximize
, DoCmd.Minimize
, etc.), using Windows API functions gives much more direct control over the Access window itself.
A Past Encounter with Windows APIs
My first exposure to Windows API usage in MS Access was with a simple but striking visual effect: a form that fades in and then slowly disappears after a few seconds. That piece of VBA code is still with me today. At the time, I didn’t pursue API programming further — but it planted the seed of curiosity about what else could be done.
Revisiting APIs for Form Control
Recently, while exploring discussions about Access window handles, I revisited this subject. To control a form’s window state at the Windows API level, the window handle (hWnd) of the form must first be obtained. This handle is then passed to other API functions (such as ShowWindow
) to manipulate the window’s display state.
The Limitation of FindWindow
The FindWindow() API
function can locate a window handle by searching for the window’s class name and/or caption. However, in Access, there is an important limitation:
-
FindWindow
only succeeds in locating forms if their Popup or Modal property is set to Yes. -
For standard forms (Popup = No),
FindWindow
cannot directly retrieve the window handle.
This means that if we want to control a form’s state through APIs, the form must be configured as a Popup (or a Modal).
The ShowWindow
API
Once the form’s handle is available, the ShowWindow() API
function can be used to change its state. For example:
Const SW_HIDE As Long = &H0
Const SW_NORMAL As Long = &H1
Const SW_MINIMIZED As Long = &H2
Const SW_MAXIMIZED As Long = &H3
Const SW_CLOSE As Long = &H10 '16
By combining FindWindow
(to get the handle) and ShowWindow
(to set the state), We can achieve effects similar to Windows Explorer window management — but inside Access forms.
The Windows API Functions.
We will learn the usage of the following Windows API Functions in our trial runs to know how they work in MS-Access:
Public Const SW_HIDE As Long = &H0 Public Const SW_NORMAL As Long = &H1 Public Const SW_MINIMIZED As Long = &H2 Public Const SW_MAXIMIZED As Long = &H3 Public Const SW_CLOSE As Long = &H10 '16 Public Declare PtrSafe Function FindWindow Lib "user32" Alias "FindWindowA" _ (ByVal lpClassName As String, ByVal lpWindowName As String) As Long Public Declare PtrSafe Function ShowWindow Lib "user32.dll" ( _ ByVal hwnd As Long, _ ByVal nCmdShow As Long) As Long Public Declare PtrSafe Function PostMessage Lib "user32" Alias "PostMessageA" _ (ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, _ ByVal lParam As Long) As Long
Experiments in the VBA Debug Window.
Adding the API Declarations to Your Database
-
Open one of your Access databases.
-
Create a new standard module (or open an existing one) and paste the API declaration code into the global declarations area at the top of the module.
-
Save the module.
⚠️ Note on 32-bit vs 64-bit Access
-
If you are running 64-bit Microsoft Access, the API declarations must include the keyword
PtrSafe
. -
If your system is 32-bit, the
PtrSafe
keyword will cause errors. In that case, simply remove itPtrSafe
from the declaration before saving the module.
Open one of your existing Forms in Normal View.
Note down the Title of the open Form.
Come back to the VBA Window (Alt+F11).
Select the Immediate Window (Ctrl+G) option from the View Menu.
Now, type the following command (to run the FindWindow() API Function) directly on the Immediate Window to obtain the Windows Identification Number of the open Form.
? FindWindow(vbNullString,"Form1") 0
The FindWindow API requires two parameters:
-
Class Name – A string that specifies the application’s window class. For Microsoft Access, this value is
"OMain"
. -
Window Title – A string representing the exact title text of the window (for example, the caption of a form).
Although both parameters are mandatory, you only need to supply one value. The other parameter can be passed as a null string (vbNullString
).
In the example above, we passed vbNullString
the Class Name parameter and used the form’s title as the second parameter.
⚠️ Important Limitation:
The FindWindow() Function
will not locate the title of a form unless the form’s Popup property is set to Yes. If the form is not a pop-up, the function fails and returns 0
.
Now, open Form1 in Design View.
Open the Form's Property Sheet and change the Popup property value to Yes.
Save the Form and Open it in Normal View again.
Try the above FindWindow command in the Debug Window one more time.
? FindWindow(vbNullString,"Form1")Result: 197654
If the FindWindow()
call succeeds, it returns a non-zero value — the unique window handle (hWnd) of the form. This means you’ve successfully identified the form’s window in memory.
Once you have this handle, you can call the ShowWindow() API to change the form’s view state. For example, you can test it directly from the Immediate (Debug) Window in the VBA editor:
Where:
-
SW_MINIMIZE (6) → Minimizes the form window.
-
SW_MAXIMIZE (3) → Maximizes the form window.
-
SW_RESTORE (9) → Restores the form to its previous size/state.
-
SW_HIDE (0) → Hides the form from view.
-
SW_SHOW (5) → Makes the form visible again if hidden.
x = ShowWindow(197654, SW_MINIMIZED)
Form1 is minimized and stationed at the bottom of the Application Window.
Application, Forms/Reports Windows Handle Property hwnd.
The MS-Access Application Object has a property that holds the Access Application Window's handle value. From within the Access Application, we can read the Application Window's Handle value as shown below:
hwnd = Application.hwndAccessApp
OR
hwnd = FindWindow("OMain",vbNullString)
We cannot make all Forms and Reports into Popups for the sake of the ShowWindow API or for any other.
The Built-in .hwnd Property
Fortunately, we don’t need to rely on the Popup property or the FindWindow API to get the window handle of a Form or Report.
Every open Form or Report in Access already exposes its .hWnd
property, which stores the window handle assigned by Windows. You can directly read this value and pass it to the ShowWindow API to change the window’s view mode to any of the supported constants (except SW_CLOSE
).
Example:
-
Open your form (e.g., Employees) in Normal View.
-
Open the Immediate Window in the VBA editor (Alt+F11 → Ctrl+G).
-
Type the following command to display the window handle of the Employees form:
This will print a numeric value — the window’s handle.
Once you have this value, you can call ShowWindow with one of the constants to minimize, maximize, restore, or hide the form.
hndl = Forms("Employees").hwnd ? hndl Result: 1508749
If you want to change the Employees form from its current Normal View to Minimized, call the ShowWindow API function and pass the form’s window handle (hWnd
) along with the constant for minimizing.
From the Immediate Window in the VBA editor, type:
This command tells Windows to minimize the Employees form directly.
whndl = Forms("Employees").hwnd rtn = ShowWindow(whndl, SW_MINIMIZED) OR rtn = ShowWindow(Forms("Employees").hwnd,2)
Once you have the window handle (hWnd
) of a Form or Report, you can experiment with the following ShowWindow options:
Constant | Value | Effect on Window |
---|---|---|
SW_HIDE | 0 | Hides the window. |
SW_SHOWNORMAL | 1 | Restores or shows the window in its normal state. |
SW_SHOWMINIMIZED | 2 | Minimizes the window. |
SW_SHOWMAXIMIZED | 3 | Maximizes the window. |
Example in the Immediate Window:
This maximizes the Employees' form. You can replace SW_SHOWMAXIMIZED
with any of the constants above to test other states.
Using it with Reports
Reports also have the .hWnd
property.
Open a Report in Print Preview mode and try:
This will minimize the SalesReport window.
Closing a Window with PostMessage
To close a Form or Report programmatically using Windows messages, declare the PostMessage API and call it with the window handle and the WM_CLOSE
message:
Then, to close an open Form (say Employees) using its handle:
This sends the WM_CLOSE message to the form’s window, effectively closing it — similar to clicking the X button.
The Sample Demo Database.
A Demo Database with a few sample Forms and Reports is attached for download.
The main form in the demo provides buttons to experiment with different window states (Hide, Normal, Minimize, Maximize) and to close Forms/Reports using the API functions described above.
Open the demo and try out the options:
-
Select a Form or Report from the list.
-
Click the desired action button (e.g., Minimize, Maximize).
-
Observe how the API functions interact with the Access windows in real time.
This makes it easier to understand how Windows handles, and the ShowWindow / PostMessage APIs can be used to control Form and Report windows directly from VBA.
When the Main Form opens, both ListBoxes are initially empty.
-
Click the Open Forms command button to open the sample forms and load their names into the first ListBox.
-
The second ListBox is reserved for sample Reports. Only one of these ListBoxes will be active at a time.
At the top of the form, there is a button labeled “Click to Enable a Disabled ListBox.” Use this button to toggle access between the two ListBoxes.
Once you select an item (Form or Report) from the active ListBox, the Window State option buttons will become available. You can then choose the state you want to apply (Hide, Normal, Minimize, or Maximize).
Tip: If you switch to another Form or Report and want to apply the same window state, you must click the desired Window State option again to apply it.
Finally, the Close All command button will close every open Form and Report—including the Main Form itself.