GetCanvas(): Convenience Function for Working with Windows API Calls in Access
This simple function serves as a great foundation for manipulating the display of Microsoft Access forms and reports with a variety of Windows API calls.
When positioning forms and reports using Windows API calls in Microsoft Access, we usually need to know what physical space we are working with.
This area of the Access application is known as the canvas, and is highlighted in teal in the screenshots below.
For more information about the Access canvas itself, check out this article:
The RECT Structure
Many Windows API calls that deal with positioning windows or drawing objects rely on the following custom VBA type, which is a representation of the underlying C++ RECT structure.
Type Rect
Left As Long
Top As Long
Right As Long
Bottom As Long
End Type
Today's convenience function, GetCanvas(), returns this custom type for the Microsoft Access canvas.
The Function
Here's the very simple function which relies on the GetInnerAccessHwnd() function referenced above:
Function GetCanvas(Optional ByVal ChildHWnd As LongPtr) As Rect
Dim CanvasHwnd As LongPtr
CanvasHwnd = GetInnerAccessHwnd(ChildHWnd)
apiGetClientRect CanvasHwnd, GetCanvas
End Function
Full Code
Listed below is the full code plus minimum dependencies. You can copy and paste the code below into a standard module to immediately begin using this function in your applications:
Option Compare Database
Option Explicit
Public Type Rect
Left As Long
Top As Long
Right As Long
Bottom As Long
End Type
Private Declare PtrSafe Function apiFindWindowEx _
Lib "user32" Alias "FindWindowExA" (ByVal hWnd1 As LongPtr, _
ByVal hWnd2 As LongPtr, _
ByVal lpsz1 As String, _
ByVal lpsz2 As String) As LongPtr
Private Declare PtrSafe Function apiGetParent _
Lib "user32" Alias "GetParent" (ByVal hWnd As LongPtr) As LongPtr
Private Declare PtrSafe Function apiGetClientRect _
Lib "user32" Alias "GetClientRect" (ByVal hWnd As LongPtr, _
lpRect As Rect) As Long
'---------------------------------------------------------------------------------------
' Procedure : GetInnerAccessHwnd
' Date : 11/26/2014 - 12/12/2023
' Author : Mike Wolfe
' Source : https://nolongerset.com/getinneraccesshwnd/
' Purpose : Gets the window handle of the Access "canvas".
' Notes - We don't use hWndAccessApp here because that's the window handle for the
' full application; what we really want is the handle for the "inner container";
' i.e., the Access window minus the docked menus, docked toolbars, and status bar
'---------------------------------------------------------------------------------------
'
Function GetInnerAccessHwnd(Optional ByVal ChildHWnd As LongPtr = 0) As LongPtr
GetInnerAccessHwnd = apiFindWindowEx(hWndAccessApp, ByVal 0&, "MDIClient", vbNullString)
If GetInnerAccessHwnd <> 0 Then Exit Function
On Error Resume Next
If ChildHWnd = 0 Then ChildHWnd = Screen.ActiveForm.hWnd
If ChildHWnd = 0 Then ChildHWnd = Screen.ActiveReport.hWnd
If ChildHWnd = 0 Then ChildHWnd = Screen.ActiveDatasheet.hWnd
GetInnerAccessHwnd = apiGetParent(ChildHWnd)
End Function
'---------------------------------------------------------------------------------------
' Procedure : GetCanvas
' Date : 11/18/2011 - 12/14/2023
' Author : Mike Wolfe
' Source : https://nolongerset.com/getcanvas/
' Purpose : Returns the Left, Top, Right, and Bottom coordinates of the Access canvas.
' Notes - Convenience function normally used in conjunction with other API calls.
'---------------------------------------------------------------------------------------
'
Function GetCanvas(Optional ByVal ChildHWnd As LongPtr) As Rect
Dim CanvasHwnd As LongPtr
CanvasHwnd = GetInnerAccessHwnd(ChildHWnd)
apiGetClientRect CanvasHwnd, GetCanvas
End Function
Sample Usage and Notes
Normally, you will pass the results of the GetCanvas() function on to another Windows API that expects the RECT structure.
However, for demonstration purposes, you can simply display the coordinates of the canvas in the immediate window, as shown here:
Note that for the GetCanvas() function, the Left and Top values will always be zero. That's because the function is returning the coordinates of the Access canvas relative to the Access canvas itself. In other words, GetCanvas.Right
and GetCanvas.Bottom
are effectively aliases for the width and height of the Access canvas, respectively.
Also, note that these values are in pixels.
The above values were generated while my main Microsoft Access window was maximized on a 4K monitor.
Cover image generated with DALL-E-3