加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

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

发布时间:2020-12-17 07:20:52 所属栏目:百科 来源:网络整理
导读:我有一个visual basic应用程序需要找到Microsoft Access,它有一个消息框,然后Send Enter到消息框. 我跟着这篇文章(FindWindow FindWindowEx). 它找到Access并将其带到前台,但它不想找到消息框并将其带到前面: Public Class Form1 Private Declare Function
我有一个visual basic应用程序需要找到Microsoft Access,它有一个消息框,然后Send 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,"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消息发送实际单击按钮.使用Access表单测试的代码:

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)
        '' 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",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.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读