我正在编写一个 VBA 程序,需要等到特定窗口打开。
我从 user32.dll 中尝试了
FindFindow
FindWindow
.,我都不会得到与 0 不同的结果
Declare Function FindWindow Lib "user32" _
(ByVal lpClassName As String, ByVal lpWindowName As String) As Long
Sub Main
Dim hwnd As Long
hwnd = FindWindow(vbNullString, vbNullString)
If (hwnd = 0) Then MsgBox ("failure")
End Sub
类似问题的解决方案,例如 How to use FindWindow to find a visible or invisible window with a partial name in VBA doesn't seem to work.
问题是
vbNullString
是一个长度为0的字符串,和""
一样。当它被编组到非托管代码时,将传递一个指向以 null 结尾的字符数组的非空指针。因为长度为 0,所以传递了一个指向空终止符的指针。这与空指针 NULL
不同。
我远不是VBA专家,但我认为解决方案是这样的:
Declare Function FindWindow Lib "user32" Alias "FindWindowA" _
(ByRef lpClassName As Any, ByRef lpWindowName As Any) As Long
如果你想为两个参数调用这个传递
NULL
这样做:
window = FindWindow(ByVal 0&, ByVal 0&)
或者,如果你想传递一个字符串值,这样做:
window = FindWindow(ByVal 0&, ByVal "Untitled - Notepad")
我希望找到解决您问题的方法。 要在 VBA 中声明函数所需的 Null 值,请将参数类型更改为整数,并在函数调用中使用 0。像这样
Declare Function FindWindow Lib "user32" Alias "FindWindowA" _
(ByVal a As Integer, ByVal b As Integer) As Long
和
hwnd = FindWindow(0, 0)
我认为这会有所帮助。
将这些声明、子例程和函数添加到模块中
Public Declare Function ShowWindow Lib "user32.dll" (ByVal Hwnd As Long, ByVal nCmdShow As Long) As Long
Public Declare Function GetWindowHandle Lib "user32" (ByVal Hwnd As Long, ByVal wCmd As Long) As Long
Public Declare Function GetWindow Lib "user32" (ByVal Hwnd As Long, ByVal wCmd As Long) As Long
Public Declare Function IsWindowEnabled Lib "user32" (ByVal Hwnd As Long) As Long
Public Declare Function GetParent Lib "user32" (ByVal Hwnd As Long) As Long
Public Declare Function GetWindowText Lib "user32" Alias "GetWindowTextA" (ByVal Hwnd As Long, ByVal lpString As String, ByVal cch As Long) As Long
Public Declare Function EnumWindows Lib "user32" (ByVal lpEnumFunc As Long, ByVal lParam As Long) As Long
Public Declare Function GetClassName Lib "user32" Alias "GetClassNameA" (ByVal Hwnd As Long, ByVal lpClassName As String, ByVal nMaxCount As Long) As Long
Public Const GW_HWNDNEXT As Long = 2
Public Const MAX_PATH = 260
Public Sub GetWindowInfo(Hwnd As Long, Optional sTitle As String, Optional sClass As String)
设置字符串以接收进程类和窗口标题
sTitle = Space$(MAX_PATH)
sClass = Space$(MAX_PATH)
运行 GetClassName api 函数并返回进程类
Call GetClassName(Hwnd, sClass, MAX_PATH)
运行 GetWindowText api 函数并返回进程标题
Call GetWindowText(Hwnd, sTitle, MAX_PATH)
从上面返回的字符串中去除尾随的 chr$(0)
sClass = TrimNull(sClass)
sTitle = TrimNull(sTitle)
运行 IsWindowVisible api 函数来查找可见窗口
If IsWindowVisible(Hwnd) = 1 Then 'window visible is true
'Debug.Print "hwnd value is " & hwnd
'Debug.Print "hwnd Process Class is " & sClass
'Debug.Print "hwnd Process Title is " & sTitle
'Debug.Print "hwnd that is visible " & IsWindowVisible(hwnd)
'Debug.Print ""
End If
End Sub
使用 shell 命令字符串启动 URL 的子程序
Public Sub MS_Edge_Launch(URL)
创建并运行一个 Shell 对象以启动一个单独的窗口,Window Style = 1 可见,等待返回为 True(等待它完成再执行进一步的代码)
Dim WshShell As Object
Dim CommandString As String
Set WshShell = VBA.CreateObject("WScript.Shell")
CommandString = """C:\Program Files (x86)\Microsoft\Edge\Application\msedge.exe"" --start-fullscreen -new-window " & """" & URL & """"
WshShell.Run CommandString, 1, True
End Sub
最大化窗口子程序和函数
Public Sub InitEnumWindowsMaximizeByWindowTitle()
Debug.Print "Maximize by Window Title Initial Subroutine started"
Debug.Print "Looking for '" & WindowTitle & "' in the Window Title."
EnumWindows AddressOf EnumWindowProcMaximizeByWindowTitle, &H0
End Sub
Public Function EnumWindowProcMaximizeByWindowTitle(ByVal Hwnd As Long, ByVal lParam As Long) As Long
Dim sTitle As String
Dim sClass As String
Dim hWndProcessID As Long
GetWindowInfo Hwnd, sTitle, sClass
获取窗口的ThreadProcessID
Call GetWindowThreadProcessId(Hwnd, hWndProcessID)
查找特定窗口标题
If sTitle Like "*" & WindowTitle & "*" Then
Debug.Print "Found '" & WindowTitle & "' In the Window Title. " & "Window hwnd = " & Hwnd & " Window Title = " & sTitle
ShowWindow Hwnd, SW_SHOWMAXIMIZED
Debug.Print "Window Maximized"
End If
'To continue enumeration, return True
'To stop enumeration return False (0).
'When 1 is returned, enumeration continues until there are no more windows left.
EnumWindowProcMaximizeByWindowTitle = 1
End Function
通过运行这个子例程将其全部付诸行动
Public Sub LaunchURL()
Dim URL As String
URL = "https://stackoverflow.com/questions/49189701/how-to-wait-until-a-specific-window-is-open"
'Call the subroutine
Call MS_Edge3.MS_Edge_Launch(URL)
'Maximize the Window
WindowTitle = "vba - How to wait until a specific"
InitEnumWindowsMaximizeByWindowTitle
End Sub