如何等到特定窗口打开?

问题描述 投票:0回答:3

我正在编写一个 VBA 程序,需要等到特定窗口打开。

我从 user32.dll 中尝试了

FindFindow

即使我将函数的两个参数设置为 Null,我也会得到负回报,尽管在那种情况下所有窗口都应该匹配。
基本上,无论我如何调用
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.

windows vba winapi user32
3个回答
1
投票

问题是

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")

-1
投票

我希望找到解决您问题的方法。 要在 VBA 中声明函数所需的 Null 值,请将参数类型更改为整数,并在函数调用中使用 0。像这样

Declare Function FindWindow Lib "user32" Alias "FindWindowA" _

  (ByVal a As Integer, ByVal b As Integer) As Long

hwnd = FindWindow(0, 0)

我认为这会有所帮助。


-1
投票

将这些声明、子例程和函数添加到模块中

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
© www.soinside.com 2019 - 2024. All rights reserved.