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.

GetCanvas(): Convenience Function for Working with Windows API Calls in Access

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:

GetInnerAccessHwnd(): Retrieve the Window Handle to the Microsoft Access Canvas
This function returns the window handle to the Microsoft Access “canvas”, the inner portion of the application window where forms and reports are drawn.

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

All original code samples by Mike Wolfe are licensed under CC BY 4.0