How can I find the width of the parent window in MS-Access

16,310

Solution 1

You can use a windows API:

(UPDATED to return twips)

Type Rect
    x1 As Long
    y1 As Long
    x2 As Long
    y2 As Long
End Type

Declare Function GetClientRect Lib "user32" (ByVal hwnd As Long, lpRect As Rect) As Long

Declare Function GetDC Lib "user32" (ByVal hwnd As Long) As Long

Declare Function ReleaseDC Lib "user32" (ByVal hwnd As Long, ByVal hdc As Long) As Long

Declare Function GetDeviceCaps Lib "gdi32" (ByVal hdc As Long, ByVal nIndex As Long) As Long

Const LOGPIXELSX = 88
Const LOGPIXELSY = 90
Const DIRECTION_VERTICAL = 1
Const DIRECTION_HORIZONTAL = 0

Public Function GetMainWindowSize()

    Dim MDIRect As Rect
    Dim lWidthPixels As Long
    Dim lWidthTwips As Long

    ' Get the screen coordinates and window size of the MDIClient area'
    GetClientRect Application.hWndAccessApp, MDIRect

    lWidthPixels = MDIRect.x2 - MDIRect.x1
    lWidthTwips = PixelsToTwips(lWidthPixels, DIRECTION_HORIZONTAL)

    MsgBox "Width (Pixels) = " & lWidthPixels & "  Width (Twips) = " & lWidthTwips

End Function


Function PixelsToTwips(lPixels As Long, lDirection As Long) As Long

    Dim lDeviceHandle As Long
    Dim lPixelsPerInch As Long

    lDeviceHandle = GetDC(0)

    If lDirection = DIRECTION_HORIZONTAL Then
        lPixelsPerInch = GetDeviceCaps(lDeviceHandle, LOGPIXELSX)
    Else

        lPixelsPerInch = GetDeviceCaps(lDeviceHandle, LOGPIXELSY)
    End If

    lDeviceHandle = ReleaseDC(0, lDeviceHandle)

    PixelsToTwips = lPixels * 1440 / lPixelsPerInch

End Function

Solution 2

Not sure what version of Access you are using, but in Access 2003, there does not appear to be a way to directly get this information.

Here's a hack:

DoCmd.Maximize

w = Forms("yourForm").WindowWidth
h = Forms("yourForm").WindowHeight

This will maximize the current window, let's assume that it's your form. You can then measure the form to get the size of the parent window's display area, then un-maximize, and move the form based on the size of the parent window that you now know.

If there is a way to turn off ScreenUpdating in Access, you can do this before the maximize and measure code, then turn it back on, and it won't take any noticeable amount of time as far as the user is concerned.

EDIT: Even without hiding the maximize command from the user, the whole maximize and move operation happens more quickly than the user can see.

It's an ugly hack, but it does work.

Solution 3

Here's the actual code I used

Application.Echo False  'turn off screen updates

DoCmd.Maximize
w = Me.WindowWidth
h = Me.WindowHeight
DoCmd.Restore           'restore the window to it's old size

Application.Echo True   'turn on screen updates

DoCmd.MoveSize w / 2 - myWidth / 2, _
            h / 2 - myHeigth / 2, _
            myWidth, _
            myHeigth

Solution 4

I realise this is a very old question, but I want to share some code I've created to handle the desired end result of the original purpose of this question - repositioning windows so they are aligned with another existing entity.

This module exposes 3 functions:


TwipsToPixels ( _
    Twips As Long, _
    Optional Dimension As Dimension = DIMENSION_X _
) As Long

PixelsToTwips ( _
    Pixels As Long, _
    Optional Dimension As Dimension = DIMENSION_X _
) As Long

These simply convert between one unit of measurement and the other. Both accept a long integer argument input and a value from the Dimension enum, either X or Y, which can be used to specify whether the conversion should be done according the to horizontal or vertical display settings. It's worth noting that 99.99999% of the time, the value will be the same in both dimensions, so you can usually omit the second argument. Both return a long integer.

The module uses pixels for everything internally, so these conversion functions are only provided as a convenience for applications that prefer to work in twips.


PositionWindow ( _
    hWnd As Long, _
    Mode As PositionMode, _
    Optional OffsetX As Long = 0, _
    Optional OffsetY As Long = 0 _
)
  • hWnd is the handle of the window to be positioned (for example, to position a form window this can be obtained using objForm.hWnd).
  • Mode is a bit mask constructed from the options in the PositionMode enum (see below).
  • OffsetX is the number of pixels to adjust the position by in the horizontal dimension, after Mode has been evaluated.
  • OffsetY is the number of pixels to adjust the position by in the vertical dimension, after Mode has been evaluated.

Modes

Every positioning call requires an X component and a Y component. These components consist of two sub-components, a base and a position.

The base is an entity to use as a reference for calculating the new position, and can be one of DISPLAY (the active physical display on the machine), WINDOW (the main Access window) or CURSOR (the mouse pointer). For convenience, these are combined in the values from the PositionMode enum.

The active display is determined using the center pixel of the main Access window. If this falls outside the bounds of the area show on the physical displays attached to the machine, the value is adjusted to compensate, and the display with the largest visible part of the application on it will be used.

The position of the X component can be one of LEFT, RIGHT or X_CENTER. The Y component has TOP, BOTTOM and Y_CENTER.

Using LEFT causes the left-most pixel of the target window to be aligned with the left-most pixel of the base entity, and this pattern follows for RIGHT, TOP and BOTTOM. The CENTER positions cause the center-line of the target window to be aligned with the center-line of the base entity.

The values from the PositionMode enum are combined with the bitwise Or operator to achieve the desired expression.

Handling display overflow

Sometimes when WINDOW or CURSOR are used as a base for one of the components, the target window may be positioned so that some or all of it is not on a visible display. To avoid this, you can use the PREVENT_OVERFLOW_X and PREVENT_OVERFLOW_Y flags. These can simply be included in the bit mask passed to the Mode argument using the bitwise Or operator.

These flags cause the position to be adjusted, if necessary, to ensure that the entire of the target window is within the edges of the active monitor.

For convenience, a PREVENT_OVERFLOW item is also included in the enum, this is the same as specifying both PREVENT_OVERFLOW_X and PREVENT_OVERFLOW_Y.

Oveflow prevention is not applied to DISPLAY-based positions.

Offsets

The OffsetX and OffsetY arguments can be used to adjust the position of the window after it has been aligned in the manner specified by Mode. Both can be a positive or negative number, indicating a number of pixels to alter the position by in the relevant dimension.

Display overflow prevention will override offsets - the offsets will still be applied, but if the resulting position results in a portion or all of the target window being outside the active display, the position will be adjusted to bring it back inside the boundaries.

Limitations

The handling code for multiple displays makes 2 assumptions:

  • That the virtual display area (the combination of all displays treated as a single display) is uniform - so it won't play nice with L shaped setups or other such ridiculous configurations.
  • That all active displays use the same resolution.

In my experience, in the real world, these are fairly safe assumptions.

No support for simultaneously re-positioning and re-sizing is provided (as it is with objForm.Move). You will need to treat these as separate tasks.

Examples

' Get the window handle for frm_MyForm
Dim hWnd As Long
hWnd  = Forms("frm_MyForm").hWnd

' Align the form to the top left corner of the active display
PositionWindow hWnd, DISPLAY_LEFT Or DISPLAY_TOP

' Align the form to the center of the Access main window
PositionWindow hWnd, WINDOW_X_CENTER Or WINDOW_Y_CENTER

' Align the form to the bottom right of the mouse pointer position, prevent the
' window from disappearing off the screen
' This effectively sets the top left corner of the window to the pointer location
PositionWindow hWnd, CURSOR_RIGHT Or CURSOR_BOTTOM Or PREVENT_OVERFLOW

' Horizontally center the form on the display, vertically center on the mouse
PositionWindow hWnd, DISPLAY_X_CENTER Or CURSOR_Y_CENTER

' Center the window on the mouse pointer then move it 200px right and 30px up
PositionWindow hWnd, CURSOR_X_CENTER Or CURSOR_Y_CENTER, 200, -30
Share:
16,310
BIBD
Author by

BIBD

Oh gawd, I never fill these out

Updated on June 04, 2022

Comments

  • BIBD
    BIBD almost 2 years

    I'm trying to force an MS-Access form to take a certain position relative to the right edge of the main window (actually I want to center it, but I can see also wanting to dock it to one side or another). I can reposition the form this with Me.Move, e.g.,

        Me.Move newWindowLeft, newWindowTop, newWidth, newHeight
    

    However, how can I find out how wide the parent window is?

  • BIBD
    BIBD over 14 years
    On my machine, I can see the maximize and restore take place, so I had to turn off/on the updates (Application.echo false/true).
  • DJ.
    DJ. over 14 years
    It returns the number of pixels - you have to convert it to twips. twips = pixels * (1440/dpi) see: applecore99.com/api/api012.asp
  • David-W-Fenton
    David-W-Fenton over 14 years
    Er, what? TWIPS = PIXELS * INCHES, or whatever other measurement you are using -- you have to specify the measurement units. The position and sizing properties of forms/reports/controls (Top, Height, Left, Width) are returned in TWIPS to begin with, so if you're sizing to an existing object, you won't need to convert.
  • David-W-Fenton
    David-W-Fenton over 14 years
    Won't this return something other than accurate numbers because of chrome issues? That is, when you restore, you end up with a title bar, which wasn't part of the window when it as maximized. And different Windows skins (i.e., "Themes" in MS terminology) can produce different results.
  • BIBD
    BIBD over 14 years
    True, I do get a shift down of about the height of the tool bars. Let me rethink this.
  • DJ.
    DJ. over 14 years
    @David - you missed the point - the api returns the width of the main application window in pixels - but access only works in twips so hence the conversion - and to convert you to take into account the dpi of the device