我找到了一些代码来将浏览器放到最前面,即使它被最小化了。 但是,我不知道如何获得浏览器的hwnd。
我看过FindWindow API函数,但你需要classname和windowname。 我发现我需要的类名是“Chrome_WidgetWin_1” 然而,windowname将根据浏览器中打开的内容不断变化。
我认为这个窗口的一个'孩子'的类名为“WrapperNativeWindowClass” 我不确定我是否可以用它来找到原来的父母。
有人可以建议如何找到Chrome浏览器的窗口句柄(使用VBA)吗?
答案 0 :(得分:2)
NirSoft优秀的WinExplorer工具(在众多其他工具中)
Chrome_WidgetWin_1
和Chrome_RenderWidgetHostHWND
答案 1 :(得分:1)
FindWindow function are optional中的参数。如果只提供lpClassName
,它将找到该类的句柄第一个窗口。如果仅提供lpWindowName
,则具有该名称的句柄第一个窗口。如果同时提供两者,则只能返回与两个条件匹配的窗口句柄。我(不幸的是)有Internet Explorer,所以我会按照以下方式做你想要的,假设只有一个窗口:
Declare Function FindWindow Lib "User32.dll" Alias "FindWindowA" (ByVal lpClassName As Any, ByVal lpWindowName As Any) As Long
Declare Function BringWindowToTop Lib "user32" (ByVal hwnd As Long) As Long
Public Sub Test()
Dim ClassName As String
Dim WindowName As String
Dim hwnd As Long
Dim Ret As Long
ClassName = "IEFrame" 'You would use "Chrome_WidgetWin_1"
WindowName = vbNullString
hwnd = FindWindow(ClassName, WindowName)
Ret BringWindowToTop(hwnd)
End Sub
如果您有多个Chrome窗口,则必须使用EnumWindows
功能。
答案 2 :(得分:1)
感谢史蒂夫 - 我很感谢你花时间看这个。它证实我的路线正确。
在浏览器打开且只显示一个默认标签的情况下,有4个“Chrome_WidgetWin_1”实例。
我还发现,如果浏览器是打开的而不是gmail,那么类名“WrapperNativeWindowClass”是不合适的。我最终使用了类名“Chrome_RenderWidgetHostHWND”(下一个兄弟) - 但是还有不止一个这样的实例。所以我必须确定父母的姓名(Chrome_WidgetWin_1),其中一个孩子有类名(RenderWidgetHostHWND)。
我想我已经设法了。
另一件事是,Windows8并不是一直将Chrome应用程序存储在同一个地方。有些版本在Programs(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&amp;也不一样。 那个人扔了我一点。