windows 如何等待特定窗口打开?

x8diyxa7  于 2023-03-19  发布在  Windows
关注(0)|答案(3)|浏览(139)

我正在编写一个VBA程序,它需要等待特定窗口打开。
我从user32.dll尝试了FindFindow
即使将函数的两个参数设置为Null,也会得到负的返回值,尽管在这种情况下所有窗口都应该匹配。
基本上,对于hwnd,不管我如何调用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这样的问题的解决方案似乎不起作用。

b4qexyjb

b4qexyjb1#

问题是vbNullString是一个长度为0的字符串,和""一样。当它被封送到非托管代码时,传递了一个指向以空结尾的字符数组的非空指针。因为长度为0,所以传递了一个指向空终止符的指针。这与NULL不同,NULL是一个空指针。
我远非VBAMaven,但我认为解决方案是这样的:

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

tv6aics12#

‘Add these declarations, subroutines and functions to a Module 
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)
'set up the strings to receive the Process Class and Window Title
sTitle = Space$(MAX_PATH)
sClass = Space$(MAX_PATH)
'Run GetClassName api function and return the Process Class
Call GetClassName(Hwnd, sClass, MAX_PATH)
'Run GetWindowText api function and return the Process Title
Call GetWindowText(Hwnd, sTitle, MAX_PATH)
'strip the trailing chr$(0)'s from the strings returned above
sClass = TrimNull(sClass)
sTitle = TrimNull(sTitle)
'Run IsWindowVisible api function to find visible windows
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


'*********************************************************
'Subroutine to Launch a URL using a shell command string
Public Sub MS_Edge_Launch(URL)
'Create and run a Shell object to launch a separate window, Window Style = 1 for visible, Wait for return is True (wait for it to finish before executing further code)
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
'*********************************************************

'*********************************************************
'Maximize Window Subroutine and Function
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
'get the ThreadProcessID of the window
Call GetWindowThreadProcessId(Hwnd, hWndProcessID)
'Find a specific window title
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
'*********************************************************


'*********************************************************
'Put it all in to action by running this subroutine
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
'*********************************************************
doinxwow

doinxwow3#

我希望你能找到解决问题的方法。在VBA中声明函数所需的空值,将参数类型改为整型,并在函数调用中使用0。如下所示
声明函数查找窗口库“user32”别名“查找窗口A”_
(ByVal a为整数,ByVal b为整数)为长整型
'及
hwnd =查找窗口(0,0)
我想会有帮助的。

相关问题