“.MoveSize”或“.Move”用于弹出表单定位

Posted

技术标签:

【中文标题】“.MoveSize”或“.Move”用于弹出表单定位【英文标题】:".MoveSize" or ".Move" for a popup form positioning 【发布时间】:2021-11-27 12:52:02 【问题描述】:

我创建了一个点击按钮事件,它应该将我的弹出表单移动到屏幕的左上角。我使用的功能是:

Private Sub Command1_Click()
    DoCmd.MoveSize(0 ,0)
End Sub

我注意到,如果我的弹出式表单位于我的第二台显示器上,它会将弹出式表单发送到我的主显示器的左上角。

有没有办法将表单发送到正在打开表单的监视器的左上角?

我尝试了一个不同的想法,我将使用一个函数来使用表单的“.Move”属性。我想出了这个:

Private Sub Command1_Click()
    Form.Move(0, 0)
End Sub

这也不起作用,因为“0, 0”坐标似乎是相对于 Access Window 在屏幕上的位置,而不是显示器的左上角。

这是 Access VBA 的限制还是可以使用其他技术?

【问题讨论】:

我读到一个线程表明未设置弹出模式已解决问题。 这只是给你(和你的显示器配置)?或者对于具有各种配置(主显示器左侧或右侧,可能不同的分辨率等)的众多用户?如果是后者,最好尝试以不同的方式来做,那一点也不好玩。 @June7,我也看到一些cmets在研究这个话题时提出了这个建议。 @Andre,这只是我想出的尝试熟悉 VBA 的方法。因此,没有其他用户将使用该表单。但是,与此同时,我宁愿代码涵盖各种配置,而不仅仅是我的。我找到了一种替代方法,可以使用 x 和 y 的负值将表单推送到另一个监视器。这就是说,我觉得这比实际的解决方案太浮夸了。 也许这会有所帮助? thespreadsheetguru.com/the-code-vault/…我不知道这是否适用于与excel相同的访问方式,但值得一看 【参考方案1】:

虽然这看起来微不足道,但不幸的是,事实并非如此,我们将需要使用相当多的 WinAPI。这对初学者来说真的很难。

我们需要一些东西:

    我们需要能够确定表单在哪个监视器上 我们需要能够确定该显示器在“虚拟屏幕”中的位置(考虑相对于彼此定位显示器) 我们需要能够确定当前窗口的大小(以像素为单位) 我们需要能够将表​​单定位在“虚拟屏幕”上。

为此,我们需要几个声明。这些最好保存在单独的模块中,但如果您 100% 确定它们只会在此表单上使用,它们也可以在表单上使用。

一、类型和值声明:

'https://docs.microsoft.com/en-us/windows/win32/api/windef/ns-windef-rect
Public Type RECT
    left As Long
    top As Long
    right As Long
    bottom As Long
End Type

'https://docs.microsoft.com/en-us/windows/win32/api/winuser/ns-winuser-monitorinfo
Public Type MONITORINFO
    cbSize As Long
    rcMonitor As RECT
    rcWork As RECT
    dwFlags As Long
End Type

'Either look this one up by Googling, or create a C++ program that references winuser.h and print it
Public Const MONITOR_DEFAULTTONEAREST = &H2

然后,函数声明:

'https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getmonitorinfow
Public Declare PtrSafe Function GetMonitorInfoW Lib "User32.dll" (ByVal hMonitor As LongPtr, ByRef lpmi As MONITORINFO) As Boolean

'https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-monitorfromwindow
Public Declare PtrSafe Function MonitorFromWindow Lib "User32.dll" (ByVal hWnd As LongPtr, ByVal dwFlags As Long) As LongPtr

'https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-movewindow
Public Declare PtrSafe Function MoveWindow Lib "User32.dll" (ByVal hWnd As LongPtr, ByVal x As Long, ByVal y As Long, ByVal nWidth As Long, ByVal nHeight As Long, ByVal bRepaint As Boolean) As Boolean

'https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getwindowrect
Public Declare PtrSafe Function GetWindowRect Lib "User32.dll" (ByVal hWnd As LongPtr, ByRef lpRect As RECT) As Boolean

然后,在表单上,​​将所有内容付诸实践:

Private Sub Command0_Click()
    Dim mi As MONITORINFO
    Dim monitor As LongPtr
    Dim myrect As RECT
    'Get the current size and position of the window
    GetWindowRect Me.hWnd, myrect
    'Determine which monitor it is on
    monitor = MonitorFromWindow(Me.hWnd, MONITOR_DEFAULTTONEAREST)
    'Make sure WinAPI knows the size of the MONITORINFO struct we're working with
    mi.cbSize = LenB(mi)
    'Get the monitor info
    GetMonitorInfoW monitor, mi
    'Move the window to the top right, keep width and height equal to the current values
    MoveWindow Me.hWnd, mi.rcMonitor.left, mi.rcMonitor.top, myrect.right - myrect.left, myrect.bottom - myrect.top, True
End Sub

不幸的是,这比DoCmd.MoveSize(0 ,0) 更多的代码和更复杂的概念,但我不知道更简单的方法。 VBA 并不真正支持多显示器,因此您通常必须使用 WinAPI 来处理它们。

【讨论】:

非常感谢您提供的解决方案。它就像一个魅力。另外,非常感谢您添加的 cmets,以及文章链接。阅读每个 WinApi 可以做什么是非常有帮助和有趣的。再次非常感谢您!

以上是关于“.MoveSize”或“.Move”用于弹出表单定位的主要内容,如果未能解决你的问题,请参考以下文章

用于付款的 PayPal 自定义表单,而不是默认的弹出窗口

where move 子句可用于重新定位一个或多个文件

怎么写程序使提交表单后弹出框显示成功或失败,页面不跳转?

Jquery移动弹出表单未提交或触发点击

将 webbrowser 控件渲染到屏幕外(或隐藏)

在提交实际表单之前接受弹出窗口中的输入