vba 如何在 MS-Access 中找到父窗口的宽度

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1290125/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-11 10:41:58  来源:igfitidea点击:

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

ms-accessvba

提问by BIBD

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.,

我试图强制 MS-Access 窗体相对于主窗口的右边缘占据某个位置(实际上我想将它居中,但我也可以看到想要将它停靠在一侧或另一侧)。我可以重新定位这个表格Me.Move,例如,

    Me.Move newWindowLeft, newWindowTop, newWidth, newHeight

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

但是,我怎样才能知道父窗口的宽度?

回答by DJ.

You can use a windows API:

您可以使用 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

回答by Stewbob

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.

不确定您使用的是哪个版本的 Access,但在 Access 2003 中,似乎没有直接获取此信息的方法。

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.

如果有办法关闭 Access 中的 ScreenUpdating,您可以在最大化和测量代码之前执行此操作,然后将其重新打开,就用户而言,它不会花费任何明显的时间。

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.

这是一个丑陋的黑客,但它确实有效。

回答by BIBD

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

回答by DaveRandom

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 moduleexposes 3 functions:

该模块公开了 3 个函数:



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 Dimensionenum, 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.

这些只是在一种计量单位和另一种计量单位之间进行转换。两者都接受一个长整数参数输入和一个来自Dimension枚举的值,X 或 Y,可用于指定是否应根据水平或垂直显示设置进行转换。值得注意的是,在 99.99999% 的情况下,两个维度的值都相同,因此通常可以省略第二个参数。两者都返回一个长整数。

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 _
)
  • hWndis the handle of the window to be positioned (for example, to position a form window this can be obtained using objForm.hWnd).
  • Modeis a bit mask constructed from the options in the PositionModeenum (see below).
  • OffsetXis the number of pixels to adjust the position by in the horizontal dimension, after Modehas been evaluated.
  • OffsetYis the number of pixels to adjust the position by in the vertical dimension, after Modehas been evaluated.
  • hWnd是要定位的窗口的句柄(例如,定位一个窗体窗口,这可以使用 获得objForm.hWnd)。
  • Mode是从PositionMode枚举中的选项构造的位掩码(见下文)。
  • OffsetXMode经过评估后在水平维度上调整位置的像素数。
  • OffsetY是在Mode评估后在垂直维度上调整位置的像素数。

Modes

模式

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

每个定位调用都需要一个 X 分量和一个 Y 分量。这些组件由两个子组件组成,一个基数和一个位置。

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 PositionModeenum.

基础是用作计算新位置的参考的实体,可以是DISPLAY(机器上的活动物理显示)、WINDOW(主访问窗口)或CURSOR(鼠标指针)之一。为方便起见,将这些值组合到PositionMode枚举中。

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, RIGHTor X_CENTER. The Y component has TOP, BOTTOMand Y_CENTER.

X 分量的位置可以是LEFTRIGHT或 之一X_CENTER。Y 分量具有TOPBOTTOMY_CENTER

Using LEFTcauses 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, TOPand BOTTOM. The CENTERpositions cause the center-line of the target window to be aligned with the center-line of the base entity.

UsingLEFT导致目标窗口最左边的像素与基本实体的最左边的像素对齐,并且这种模式遵循RIGHT,TOPBOTTOM。这些CENTER位置使目标窗口的中心线与基础实体的中心线对齐。

The values from the PositionModeenum are combined with the bitwise Oroperator to achieve the desired expression.

PositionMode枚举中的值与按位运算Or符组合以实现所需的表达式。

Handling display overflow

处理显示溢出

Sometimes when WINDOWor CURSORare 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_Xand PREVENT_OVERFLOW_Yflags. These can simply be included in the bit mask passed to the Modeargument using the bitwise Oroperator.

有时,当WINDOW或被CURSOR用作组件之一的基础时,目标窗口可能会被定位成使其部分或全部不在可见显示器上。为避免这种情况,您可以使用PREVENT_OVERFLOW_XPREVENT_OVERFLOW_Y标志。这些可以简单地包含在Mode使用按位运算Or符传递给参数的位掩码中。

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_OVERFLOWitem is also included in the enum, this is the same as specifying both PREVENT_OVERFLOW_Xand PREVENT_OVERFLOW_Y.

为方便起见,PREVENT_OVERFLOW枚举中还包含一个项目,这与同时指定PREVENT_OVERFLOW_X和相同PREVENT_OVERFLOW_Y

Oveflow prevention is not applied to DISPLAY-based positions.

溢出预防不适用于DISPLAY基于位置。

Offsets

偏移量

The OffsetXand OffsetYarguments 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.

OffsetXOffsetY参数可以使用它已在通过指定的方式进行了对准后,调整窗口的位置Mode。两者都可以是正数或负数,表示在相关维度中改变位置的像素数。

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.
  • 虚拟显示区域(所有显示器的组合被视为单个显示器)是统一的 - 因此它不会与 L 形设置或其他此类荒谬的配置配合使用。
  • 所有活动显示器都使用相同的分辨率。

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.

不支持同时重新定位和重新调整大小(与 一样objForm.Move)。您需要将这些视为单独的任务。

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

回答by Fionnuala

This may be of interest: http://www.mvps.org/access/downloads/clFormWindow.bas

这可能很有趣:http: //www.mvps.org/access/downloads/clFormWindow.bas

It says it:

它说:

 '' Moves and resizes a window in the coordinate system        *
 '' of its parent window.                                      *
 '' N.B.: This class was developed for use on Access forms     *
 ''       and has not been tested for use with other window    *
 ''       types.                                               *