Можно ли запустить окно браузера в VBA, развернутое в текущем мониторе? - PullRequest
1 голос
/ 19 июля 2011

Мне нужно иметь возможность запускать окно браузера из кода VBA (это легко), но мне также нужно, чтобы оно отображалось в развернутом виде на текущем мониторе. Чтобы сделать вещи лучше (читай: хуже), мне нужно поддерживать дисплей с четырьмя мониторами. Таким образом, у пользователя может быть 4 активных окна на 4 отдельных мониторах, и в зависимости от того, какое окно / монитор запускает веб-сайт, оно должно быть максимально развернуто на этом мониторе.

Как я упоминал ранее, запуск веб-сайта тривиален (да, IE является обязательным требованием. Boo.):

Shell ("cmd /c start c:\progra~1\intern~1\iexplore.exe <a href="http://www.google.com" rel="nofollow">http://www.google.com</a>")

Однако некоторые детали, связанные с этим, вызывают беспокойство, а именно:

  1. Можно ли указать, где запускается окно, отображаемое в новом процессе?
  2. Могу ли я указать, что окно, показанное в новом процессе, будет отображено в развернутом виде?
  3. Могу ли я обнаружить более двух мониторов, используя эту функцию Win32 ?
  4. Зная, какой монитор является текущим, можно ли указать, на каком мониторе будет отображаться новое окно?

Любой совет, указывающий мне правильное направление, был бы полезен!

1 Ответ

2 голосов
/ 19 июля 2011

Я предполагал, что это будет вызвано из Excel.Идея состоит в том, что вы передаете свой дескриптор окна объектов Excel (hWnd) и извлекаете его объект «Прямоугольник» из User32.Используя эти данные прямоугольника, вы затем создаете экземпляр IE и накладываете свой объект IE поверх целевого Rectangle с помощью вызова API SetWindowPos.Наконец, мы запускаем команду Maximize с помощью команды API ShowWindowAsync, а затем загружаем на веб-сайт.В настоящее время я не могу тестировать на двух мониторах, но это должно дать вам хорошее начало.

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