是否可以在当前监视器中最大化的 VBA 中启动浏览器窗口?

发布于 2024-11-24 16:01:41 字数 647 浏览 0 评论 0原文

我需要能够从 VBA 代码启动浏览器窗口(这部分很简单),但我还需要它在当前监视器上最大化显示。为了让事情变得更好(读作:更糟),我需要支持四显示器显示。因此,用户可以在 4 个独立的显示器上激活 4 个窗口,并且根据哪个窗口/显示器触发网站打开,网站应该在该显示器中最大化。

正如我之前提到的,启动一个网站是微不足道的(是的,IE 是必需的。嘘。):

Shell ("cmd /c start c:\progra~1\intern~1\iexplore.exe http://www.google.com")

但是,围绕此的几个细节很麻烦,即:

  1. 我可以指定吗新进程中显示的窗口在哪里启动?
  2. 我可以指定新进程中显示的窗口将最大化显示吗?
  3. 我可以使用 此 Win32 函数检测两个以上的显示器
  4. 知道当前是哪台显示器后,我可以指定在哪台显示器上显示新窗口吗?

任何为我指明正确方向的建议都会很有帮助!

I need to be able to launch a browser window from VBA code (that part's easy), but I also need it to display maximized on the current monitor. To make things better (read: worse), I need to support a quad-monitor display. So, the user could have 4 windows active on 4 separate monitors, and depending on which window/monitor triggers the website to open, it should be maximized in that monitor.

As I mentioned before, launching a website is trivial (yes, IE is a requirement. Boo.):

Shell ("cmd /c start c:\progra~1\intern~1\iexplore.exe http://www.google.com")

However, several details surrounding this are troublesome, namely:

  1. Can I specify where the window shown in a new process starts up?
  2. Can I specify that a window shown in a new process will be shown maximized?
  3. Can I detect more than two monitors using this Win32 Function?
  4. Knowing which monitor is the current one, can I specify which monitor to show the new window on?

Any advice pointing me in the right direction would be helpful!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

月下客 2024-12-01 16:01:41

我以为这将从 Excel 中调用。这个想法是,您传递 Excel 对象窗口句柄 (hWnd) 并从 User32 检索其“矩形”对象。然后,您可以使用此矩形数据创建一个 IE 实例,并使用 SetWindowPos API 调用将 IE 对象覆盖在目标矩形之上。最后,我们使用 ShowWindowAsync API 命令发出 Maximize 命令,然后在网站中加载。我目前无法在双​​显示器上进行测试,但它应该给您一个良好的开始。

Public Type RECT
   x1 As Long
   y1 As Long
   x2 As Long
   y2 As Long
End Type

Public Enum SetWindowPosFlags
     SWP_ASYNCWINDOWPOS = &H4000
     SWP_DEFERERASE = &H2000
     SWP_DRAWFRAME = &H20
     SWP_FRAMECHANGED = &H20
     SWP_HIDEWINDOW = &H80
     SWP_NOACTIVATE = &H10
     SWP_NOCOPYBITS = &H100
     SWP_NOMOVE = &H2
     SWP_NOOWNERZORDER = &H200
     SWP_NOREDRAW = &H8
     SWP_NOREPOSITION = SWP_NOOWNERZORDER
     SWP_NOSENDCHANGING = &H400
     SWP_NOSIZE = &H1
     SWP_NOZORDER = &H4
     SWP_SHOWWINDOW = &H40
End Enum

Public Enum SpecialWindowHandles
    HWND_TOP = 0
    HWND_BOTTOM = 1
    HWND_TOPMOST = -1
    HWND_NOTOPMOST = -2
End Enum

    Const SW_SHOWNORMAL As Integer = 1
    Const SW_SHOWMINIMIZED As Integer = 2
    Const SW_SHOWMAXIMIZED As Integer = 3

'taken from IE's ReadyState MSDN Specs
Enum READYSTATE
    READYSTATE_UNINITIALIZED = 0
    READYSTATE_LOADING = 1
    READYSTATE_LOADED = 2
    READYSTATE_INTERACTIVE = 3
    READYSTATE_COMPLETE = 4
End Enum

Declare Function GetWindowRect Lib "user32.dll" (ByVal hWnd As Long, rectangle As RECT) As Boolean

Declare Function SetWindowPos Lib "user32.dll" (ByVal hWnd As Long, ByVal hWndInsertAfter As SpecialWindowHandles, ByVal X As Integer, ByVal Y As Integer, ByVal cx As Integer, ByVal cy As Integer, ByVal uFlags As SetWindowPosFlags) As Boolean

Declare Function ShowWindowAsync Lib "user32.dll" (ByVal hWnd As Long, ByVal windowMode As Integer) As Boolean

Public Sub Test()

    BrowseIEMaxFromParent Application.hWnd, "www.google.com"
End Sub

Public Sub BrowseIEMaxFromParent(targetHWND As Long, url As String)

    Dim ie As Object
    Dim xlRect As RECT

    Set ie = CreateObject("InternetExplorer.Application")

    If GetWindowRect(targetHWND, xlRect) Then

        ie.Visible = True

        'HWND_TOP sets the Z Order to our IE Object
        'x2 - x1 ==> Width (In Pixels)
        'y2 - y2 ==> Height (In Pixels)
        If SetWindowPos(ie.hWnd, HWND_TOP, xlRect.x1, xlRect.y1, (xlRect.x2 - xlRect.x1), (xlRect.y2 - xlRect.y1), SWP_ASYNCWINDOWPOS) Then

            'use constants from above for size mode, enums won't work as it needs integer type
            ShowWindowAsync ie.hWnd, SW_SHOWMAXIMIZED

            ie.Navigate url

            'wait until navigated
            While ie.Busy Or ie.READYSTATE <> READYSTATE.READYSTATE_COMPLETE
                DoEvents
            Wend

        Else
            MsgBox "Failed to Set Position"
        End If
    Else
        MsgBox "Failed to Find HWND"
    End If
End Sub

I assumed this is going to be called from Excel. The Idea is that you pass your Excel Objects window Handle (hWnd) and retrieve its 'Rectangle' Object from User32. Using this rectangle data, You then create an IE instance and overlay your IE object overtop of the target Rectangle using the SetWindowPos API call. Finally, we issue the Maximize command with the ShowWindowAsync API command, then load in the website. I currently cannot test on dual monitors, but it should give you a good start.

Public Type RECT
   x1 As Long
   y1 As Long
   x2 As Long
   y2 As Long
End Type

Public Enum SetWindowPosFlags
     SWP_ASYNCWINDOWPOS = &H4000
     SWP_DEFERERASE = &H2000
     SWP_DRAWFRAME = &H20
     SWP_FRAMECHANGED = &H20
     SWP_HIDEWINDOW = &H80
     SWP_NOACTIVATE = &H10
     SWP_NOCOPYBITS = &H100
     SWP_NOMOVE = &H2
     SWP_NOOWNERZORDER = &H200
     SWP_NOREDRAW = &H8
     SWP_NOREPOSITION = SWP_NOOWNERZORDER
     SWP_NOSENDCHANGING = &H400
     SWP_NOSIZE = &H1
     SWP_NOZORDER = &H4
     SWP_SHOWWINDOW = &H40
End Enum

Public Enum SpecialWindowHandles
    HWND_TOP = 0
    HWND_BOTTOM = 1
    HWND_TOPMOST = -1
    HWND_NOTOPMOST = -2
End Enum

    Const SW_SHOWNORMAL As Integer = 1
    Const SW_SHOWMINIMIZED As Integer = 2
    Const SW_SHOWMAXIMIZED As Integer = 3

'taken from IE's ReadyState MSDN Specs
Enum READYSTATE
    READYSTATE_UNINITIALIZED = 0
    READYSTATE_LOADING = 1
    READYSTATE_LOADED = 2
    READYSTATE_INTERACTIVE = 3
    READYSTATE_COMPLETE = 4
End Enum

Declare Function GetWindowRect Lib "user32.dll" (ByVal hWnd As Long, rectangle As RECT) As Boolean

Declare Function SetWindowPos Lib "user32.dll" (ByVal hWnd As Long, ByVal hWndInsertAfter As SpecialWindowHandles, ByVal X As Integer, ByVal Y As Integer, ByVal cx As Integer, ByVal cy As Integer, ByVal uFlags As SetWindowPosFlags) As Boolean

Declare Function ShowWindowAsync Lib "user32.dll" (ByVal hWnd As Long, ByVal windowMode As Integer) As Boolean

Public Sub Test()

    BrowseIEMaxFromParent Application.hWnd, "www.google.com"
End Sub

Public Sub BrowseIEMaxFromParent(targetHWND As Long, url As String)

    Dim ie As Object
    Dim xlRect As RECT

    Set ie = CreateObject("InternetExplorer.Application")

    If GetWindowRect(targetHWND, xlRect) Then

        ie.Visible = True

        'HWND_TOP sets the Z Order to our IE Object
        'x2 - x1 ==> Width (In Pixels)
        'y2 - y2 ==> Height (In Pixels)
        If SetWindowPos(ie.hWnd, HWND_TOP, xlRect.x1, xlRect.y1, (xlRect.x2 - xlRect.x1), (xlRect.y2 - xlRect.y1), SWP_ASYNCWINDOWPOS) Then

            'use constants from above for size mode, enums won't work as it needs integer type
            ShowWindowAsync ie.hWnd, SW_SHOWMAXIMIZED

            ie.Navigate url

            'wait until navigated
            While ie.Busy Or ie.READYSTATE <> READYSTATE.READYSTATE_COMPLETE
                DoEvents
            Wend

        Else
            MsgBox "Failed to Set Position"
        End If
    Else
        MsgBox "Failed to Find HWND"
    End If
End Sub
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文