謝謝你史蒂夫 - 我很感激你花時間看這個。它證實我是在正確的路線上。
在瀏覽器打開並且只顯示一個默認選項卡的情況下,有4個「Chrome_WidgetWin_1」實例。
我還發現,如果瀏覽器打開但不在gmail中,類名「WrapperNativeWindowClass」不適合。我最終使用了類名「Chrome_RenderWidgetHostHWND」(下一個兄弟) - 但也有一個以上的實例。所以我必須確定父級的名稱(Chrome_WidgetWin_1),並且其中一個孩子擁有類名稱(RenderWidgetHostHWND)。
我想我已經管理它了。
另一件出現的問題是,Windows8並未將Chrome應用程序始終存儲在同一個地方。某些版本在程序(x86)下,其他版本在appdata下。不知道是否有切換回Windows7的位置或其他東西,但我已經將它包含在我的代碼中,任何人都可以使用它(代碼中標註了鏈接,因爲我傾向於將人們與我脫節的'風格「)。
BringWindowToFront還有一個宏,因爲API調用BringWindowToTop沒有管理它。 在可能的情況下,我已經注意到誰發佈了代碼,從哪裏來,儘管我確信我錯過了一些人。我仍然想說感謝讓我走得這麼遠。
我沒有時間充分評論我的代碼,如果它的工作,我可能不會因爲這是送我圈子。在用正確的類名識別href之後,我必須循環查找下一個父級,然後檢查href的最終父級是否具有適當的類名。
如果您發現任何問題,請告訴我,或者告訴我是否有任何問題會導致問題無法解決。
'Mark007 - VBA to find all Window Handles http://www.vbaexpress.com/kb/getarticle.php?kb_id=52
'Thanks to Ivan F Moala at MrExcel - I'm not sure if i used any of his code, but reading the comments on his code defiantely helped my understanding.
'Jaafar Tribak who posted the BringWindowToFront function at the start of the month
'Scott Huish who posted the GetFolder macro (helped with disparity in location of Chrome)
Option Explicit
Private Declare Function SHGetFolderPath Lib "shell32.dll" Alias "SHGetFolderPathA" (ByVal hwndOwner As Long, ByVal nFolder As Long, ByVal hToken As Long, ByVal dwFlags As Long, ByVal lpszPath As String) As Long
Private Declare Function SetForegroundWindow Lib "User32.dll" (ByVal hwnd As Long) As Long
Private Declare Function ShowWindow Lib "User32.dll" (ByVal hwnd As Long, ByVal lCmdShow As Long) As Boolean
Private Declare Function GetAncestor Lib "user32" (ByVal hwnd As Long, ByVal flags As Long) As Long
Private Declare Function GetClassName Lib "user32" Alias "GetClassNameA" (ByVal hwnd As Long, ByVal lpClassName As String, ByVal nMaxCount As Long) As Long
Private Declare Function FindWindowEx Lib "user32" Alias "FindWindowExA" (ByVal hWnd1 As Long, ByVal hWnd2 As Long, ByVal lpsz1 As String, ByVal lpsz2 As String) As Long
Private Declare Function GetWindow Lib "user32" (ByVal hwnd As Long, ByVal wCmd As Long) As Long
Private Declare Function GetWindowThreadProcessId Lib "user32" (ByVal hwnd As Long, lpdwProcessId As Long) As Long
Private Declare Function GetNextWindow Lib "user32" Alias "GetWindow" (ByVal hwnd As Long, ByVal wFlag As Long) As Long
Private Declare Function AttachThreadInput Lib "user32" (ByVal idAttach As Long, ByVal idAttachTo As Long, ByVal fAttach As Long) As Long
Private Declare Function GetForegroundWindow Lib "user32"() As Long
Private Declare Function IsIconic Lib "user32" (ByVal hwnd As Long) As Long
Private Const S_OK = &H0
Private Const S_FALSE = &H1
Private Const E_INVALIDARG = &H80070057
Private Const SHGFP_TYPE_CURRENT = 0
Private Const SHGFP_TYPE_DEFAULT = 1
Private Const GW_HWNDNEXT = 2
Private Const GA_PARENT = 1
Private Const SW_SHOW = 5
Private Const SW_RESTORE = 9
Public retainedChromeHwnd As Long, ChildHwnd As Long, ChildFound As Boolean, origChildFound As Boolean
Public NextHandle As Boolean, GotNextParent As Boolean
Private Function BringWindowToFront(ByVal hwnd As Long) As Boolean
'Many thanks to Jaafar Tribak who posted this on MrExcel
'http://www.mrexcel.com/forum/excel-questions/730660-visual-basic-applications-code-maximise-view-activeworksheet-after-having-ie-navigation.html
Dim ThreadID1 As Long
Dim ThreadID2 As Long
Dim nRet As Long
On Error Resume Next
' Nothing to do if already in foreground.
If hwnd = GetForegroundWindow() Then
BringWindowToFront = True
Else
'First need to get the thread responsible for this window,
'and the thread for the foreground window.
ThreadID1 = _
GetWindowThreadProcessId(GetForegroundWindow, ByVal 0&)
ThreadID2 = _
GetWindowThreadProcessId(hwnd, ByVal 0&)
'By sharing input state, threads share their concept of
'the active window.
Call AttachThreadInput(ThreadID1, ThreadID2, True)
nRet = SetForegroundWindow(hwnd)
'Restore and repaint.
If IsIconic(hwnd) Then
Call ShowWindow(hwnd, SW_RESTORE)
Else
Call ShowWindow(hwnd, SW_SHOW)
End If
'BringWindowToFront returns TRUE if success.
BringWindowToFront = CBool(nRet)
End If
End Function
Private Function GetFolder(ByVal lngFolder As Long) As String
' With thanks to Scott Huish who posted this macro on MrExcel
'http://www.mrexcel.com/forum/excel-questions/706627-using-visual-basic-applications-open-links-non-default-browser.html
Dim strBuffer As String * 1000
Dim strPath As String
Dim lngReturn As Long
lngReturn = SHGetFolderPath(0&, lngFolder, 0&, SHGFP_TYPE_CURRENT, strBuffer)
If lngReturn = S_OK Then
strPath = Left$(strBuffer, InStr(strBuffer, Chr$(0)) - 1)
Else
strPath = "(error)"
End If
GetFolder = strPath
End Function
Public Sub Chromelink(hparent As Long, xcount As Long)
Dim ChromeID As Long, strtext As String, ChromeClassName As String, ChromeHwnd As Long
Dim lngret As Long
ChromeHwnd = FindWindowEx(hparent, 0&, vbNullString, vbNullString)
If origChildFound = True Then
ChromeHwnd = retainedChromeHwnd
origChildFound = False
End If
If ChildFound = True And GotNextParent = True Then
Exit Sub
ElseIf ChildFound = True Then
NextHandle = True
ChildFound = False
End If
While ChromeHwnd <> 0
strtext = String$(100, Chr$(0))
lngret = GetClassName(ChromeHwnd, strtext, 100)
ChromeClassName = Left$(strtext, lngret)
If ChromeClassName = "Chrome_RenderWidgetHostHWND" Then
ChildFound = True
ChildHwnd = ChromeHwnd
End If
xcount = xcount + 1
Chromelink ChromeHwnd, xcount 'loop through next level of child windows
If ChildFound = True Then Exit Sub
ChromeHwnd = FindWindowEx(hparent, ChromeHwnd, vbNullString, vbNullString)
If hparent = 0 And NextHandle = True Then
retainedChromeHwnd = ChromeHwnd
ChildFound = True
GotNextParent = True
End If
Wend
End Sub
Sub ChromeSetup()
Dim myURL As String, ChromePath As String, strtext As String, lngret As Long
Dim ChromeOpen As Boolean
Dim W As Object
Dim ProcessQuery As String
Dim processes As Object
Dim process As Object
Set W = GetObject("winmgmts:")
ProcessQuery = "SELECT * FROM win32_process"
Set processes = W.execquery(ProcessQuery)
'helpful process properties - http://msdn.microsoft.com/en-us/library/aa394372(v=vs.85).aspx
For Each process In processes
'check if Chrome is open
If process.Name = "chrome.exe" Then
'Chrome is open, find the Handle for the Chrome Browser
Chromelink 0&, 0
strtext = String$(100, Chr$(0))
lngret = GetClassName(ChildHwnd, strtext, 100)
'loop incase of more siblings
While Not Left$(strtext, lngret) = "Chrome_WidgetWin_1"
ChildHwnd = GetAncestor(ChildHwnd, GA_PARENT)
strtext = String$(100, Chr$(0))
lngret = GetClassName(ChildHwnd, strtext, 100)
'Duplicate of classname but WidgetWin_0
If ChildHwnd = 0 Then
origChildFound = True
Chromelink retainedChromeHwnd, 0
End If
Wend
ChromeOpen = True
Exit For
End If
Next process
myURL = "http://www.google.com/"
If ChromeOpen = False Then 'Chrome needs to be opened so more time required
'which localtion is Chrome at?
ChromePath = "C:\Program Files (x86)\Google\Chrome\Application\chrome.exe"
If Len(Dir(ChromePath)) Then
shell "C:\Program Files (x86)\Google\Chrome\Application\chrome.exe -url " & myURL
Else
ChromePath = GetFolder(&H1C) & "\Google\Chrome\Application\chrome.exe"
If Len(Dir(ChromePath)) Then
shell GetFolder(&H1C) & "\Google\Chrome\Application\chrome.exe -url " & myURL
Else
MsgBox "Chrome could not be found."
Exit Sub
End If
End If
Application.Wait Now() + TimeValue("00:00:10")
Else
BringWindowToFront ChildHwnd
Application.Wait Now() + TimeValue("00:00:01")
End If
End Sub
我可能應該把錯誤處理,並可能找到更多關於'借來的'代碼。其中一些我不明白 - 即使像0這樣的基礎知識也不是0 &。 那一個把我扔了一下。
謝謝! 'Chrome_WidgetWin_1'爲我工作。通過以下函數調用':: FindWindowEx(0,0,「Chrome_WidgetWin_1」,0)' – d34th4ck3r