gpt4 book ai didi

vb.net 使用 FindWindowex 在另一个应用程序中查找消息框

转载 作者:行者123 更新时间:2023-12-04 18:02:52 38 4
gpt4 key购买 nike

我有一个可视化基本应用程序,它需要找到具有消息框的 Microsoft Access,然后将 Enter 发送到消息框。

我关注了这篇文章( FindWindow FindWindowEx )。

它找到 Access 并将其置于前台,但它不想找到消息框并将其置于前台:

enter image description here

Public Class Form1

Private Declare Function SetForegroundWindow Lib "user32" (ByVal hwnd As IntPtr) As Long

Private Declare Auto Function FindWindow Lib "user32.dll" ( _
ByVal lpClassName As String, _
ByVal lpWindowName As String _
) As IntPtr

Private Declare Auto Function FindWindowEx Lib "user32.dll" ( _
ByVal hwndParent As IntPtr, _
ByVal hwndChildAfter As IntPtr, _
ByVal lpszClass As String, _
ByVal lpszWindow As String _
) As IntPtr

Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Dim hWnd As IntPtr
hWnd = FindWindow("OMain", Nothing)

MsgBox(hWnd) 'FINDS 1640402

Dim hWndChild1 As IntPtr = _
FindWindowEx(hWnd, IntPtr.Zero, "#32770 (Dialog)", "Microsoft Access")

MsgBox(hWndChild1) 'FIRST PROBLEM IT FINDS ZERO HERE

Dim hWndChild1Button As IntPtr = _
FindWindowEx(hWndChild1, IntPtr.Zero, "Button", "OK")

MsgBox(hWndChild1Button) 'ALSO FINDS ZERO HERE

If hWndChild1Button <> IntPtr.Zero Then
SetForegroundWindow(hWndChild1Button)
SendKeys.SendWait("{Enter}")
End If

End Sub
End Class

enter image description here
enter image description here

enter image description here
enter image description here

最佳答案

该代码未使用正确的 winapi 函数。 FindWindowEx() 可以找到子窗口,但 MsgBox() 显示的窗口不是子窗口。它是一个顶级窗口,您可以使用 FindWindow() 找到的那种。

但该功能不足以定位您要关闭的特定消息框。需要一种更好的方法,您可以使用的方法是使用 EnumThreadWindows() 枚举由同一线程拥有的窗口。 MsgBox() 的好处是只有一个这样的窗口,因为对话框是模态的。

SendKeys() 也不够好,它只有在消息框在前台时才能正常工作。更好的方法是通过向按钮发送 BM_CLICK 消息来实际单击按钮。测试代码,使用访问表单:

Imports System.Runtime.InteropServices
Imports System.ComponentModel
Imports System.Text

Module Module1
Sub Main()
'' Find the MS-Access host window
Dim access = FindWindow("OMain", Nothing)
If access = IntPtr.Zero Then Throw New Win32Exception()
'' Enumerate the windows owned by the same thread
Dim pid As Integer
Dim tid = GetWindowThreadProcessId(access, pid)
If tid = 0 Then Throw New Win32Exception()
EnumThreadWindows(tid, AddressOf ClickOkButton, Nothing)
End Sub

Private Function ClickOkButton(hWnd As IntPtr, lp As IntPtr) As Boolean
'' Verify the class name is #32770
Dim buf As New StringBuilder(256)
GetClassName(hWnd, buf, 256)
If buf.ToString <> "#32770" Then Return True
'' Find the OK button (control ID 2)
Dim okbutton = GetDlgItem(hWnd, 2)
If okbutton = IntPtr.Zero Then Return True
'' Activate the dialog, just in case
SetActiveWindow(hWnd)
'' Click the button
SendMessage(okbutton, BM_CLICK, IntPtr.Zero, IntPtr.Zero)
'' Done, no need to continue enumerating windows
Return False
End Function
End Module

Friend Module NativeMethods
<DllImport("user32.dll", SetLastError:=True, CharSet:=CharSet.Auto)>
Friend Function FindWindow(ByVal lpClassName As String, ByVal lpWindowName As String) As IntPtr
End Function

<DllImport("user32.dll", SetLastError:=True)>
Friend Function GetWindowThreadProcessId(ByVal hwnd As IntPtr, ByRef lpdwProcessId As Integer) As Integer
End Function

Friend Delegate Function EnumThreadDelegate(hWnd As IntPtr, lParam As IntPtr) As Boolean

<DllImport("user32.dll", SetLastError:=True)>
Friend Function EnumThreadWindows(dwThreadId As Int32, lpfn As EnumThreadDelegate, lParam As IntPtr) As Boolean
End Function

<DllImport("user32.dll", CharSet:=CharSet.Auto)>
Friend Function GetClassName(ByVal hWnd As System.IntPtr, ByVal lpClassName As System.Text.StringBuilder, ByVal nMaxCount As Integer) As Integer
End Function

<DllImport("user32.dll", SetLastError:=True, CharSet:=CharSet.Auto)>
Friend Function GetDlgItem(ByVal hDlg As IntPtr, id As Integer) As IntPtr
End Function

<DllImport("user32.dll", SetLastError:=True)>
Friend Function SetActiveWindow(ByVal hWnd As IntPtr) As IntPtr
End Function

<DllImport("user32.dll")>
Friend Function SendMessage(ByVal hWnd As IntPtr, ByVal msg As Integer, ByVal wp As IntPtr, ByVal lp As IntPtr) As IntPtr
End Function

Friend Const BM_CLICK As Integer = &HF5
End Module

通常的建议是到 favor UI Automation .

关于vb.net 使用 FindWindowex 在另一个应用程序中查找消息框,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40607191/

38 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com