问题
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:
- Can I specify where the window shown in a new process starts up?
- Can I specify that a window shown in a new process will be shown maximized?
- Can I detect more than two monitors using this Win32 Function?
- 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!
回答1:
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
来源:https://stackoverflow.com/questions/6739052/is-it-possible-to-launch-a-browser-window-in-vba-maximized-in-the-current-monito