0

我创建了一个有 2 个按钮的表单。一个按钮弹出一个 msgbox,另一个从下面列出的 frmAPI(代码在下面列出)中运行。如果我打开 msgbox 并将其保持打开状态,然后运行 ​​frmAPI,它将列出 msgbox 及其文本,然后将其关闭。这是我期望它做的。如果我打开另一个应用程序并在该应用程序中生成一个 msgbox,而我的 frmAPI 仍在运行,它实际上会列出其他应用程序 msgbox 和文本,但它不会从其他应用程序关闭 msgbox。如果我从另一个应用程序运行 frmAPI 并执行相同的测试,结果将相反。所以简而言之,它只会从同一个应用程序中关闭对话框。

我希望能够从任何应用程序中关闭一个对话框,因为它是一个对话框并且具有符合我标准的文本。对我做错了什么有帮助吗?

谢谢

Imports System.Runtime.InteropServices
Imports System.Text

Partial Public Class TestMSgBoxStuff
    Inherits Form
    Public Sub New()
        InitializeComponent()
    End Sub

    <DllImport("user32.dll", SetLastError:=True)> _
    Private Shared Function FindWindow(lpClassName As String, lpWindowName As String) As IntPtr
    End Function

    <DllImport("user32.dll", SetLastError:=True)> _
    Private Shared Function FindWindowEx(hwndParent As IntPtr, hwndChildAfter As IntPtr, lpszClass As String, lpszWindow As String) As IntPtr
    End Function

    <DllImport("user32.dll", CharSet:=CharSet.Auto, SetLastError:=True)> _
    Private Shared Function GetWindowText(hWnd As IntPtr, lpString As StringBuilder, nMaxCount As Integer) As Integer
    End Function

    <DllImport("user32.dll", SetLastError:=True, CharSet:=CharSet.Auto)> _
    Private Shared Function GetWindowTextLength(hWnd As IntPtr) As Integer
    End Function

    <DllImport("user32.dll", SetLastError:=True)> _
    Private Shared Function SendMessage(hWnd As HandleRef, Msg As UInteger, wParam As IntPtr, lParam As IntPtr) As IntPtr
    End Function
    <DllImport("user32", CharSet:=Runtime.InteropServices.CharSet.Auto, SetLastError:=True, ExactSpelling:=True)>
    Private Shared Function SetForegroundWindow(ByVal hwnd As IntPtr) As IntPtr
    End Function


    Private Const WM_IME_NOTIFY As Integer = &H282
    Private Const WM_DESTROY As Integer = &H2
    Private Const WM_NCDESTROY As Integer = &H82
    Private Const WM_CLOSE As Integer = &H10
    Private Const IMN_CLOSESTATUSWINDOW As Integer = &H1
    Private Const WM_KILLFOCUS As Integer = &H8
    Private Const WM_COMMAND As Integer = &H11



    Private Sub TestMSgBoxStuff_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
        Dim timer As New Timer()
        Timer1.Interval = 10000
        'detect the MessageBox every seconds
        'Timer1.Tick += New EventHandler(Timer1_Tick)
        Timer1.Start()
    End Sub

    Private Sub Timer1_Tick(sender As System.Object, e As System.EventArgs) Handles Timer1.Tick
        'Get the MessageBox handle
        Dim handle As IntPtr = FindWindow("#32770", Nothing)
        Me.RichTextBox1.AppendText("Handle: " + handle.ToString() + vbLf)

        'Get the Text window handle
        Dim txtHandle As IntPtr = FindWindowEx(handle, IntPtr.Zero, "Static", Nothing)
        Me.RichTextBox1.AppendText(vbTab & "text handle: " + txtHandle.ToString() + vbLf)
        Dim len As Integer = GetWindowTextLength(txtHandle)
        Dim sb As New StringBuilder()

        'Get the text
        GetWindowText(txtHandle, sb, len + 1)
        Me.RichTextBox1.AppendText(vbTab & "text: " + sb.ToString() + vbLf & vbLf)
        Me.RichTextBox1.ScrollToCaret()

        SetForegroundWindow(handle)

        'close the messagebox WM_CLOSE
        Dim lResults As Integer = SendMessage(New HandleRef(Nothing, handle), WM_NCDESTROY, IntPtr.Zero, IntPtr.Zero)

    End Sub
End Class
4

1 回答 1

1

您可能遇到了User Interface Privilege Isolation。这将阻止您的消息进入更高权限的进程。也可以看看ChangeWindowsMessageFilter()

我建议尝试发送 aWM_COMMAND而不是 a WM_CLOSE; WM_COMMAND通常被系统更温和地对待并且可能通过。使用 BN_CLICKED 作为 WPARAM 的高位字,IDOK 作为低位字(假设它有一个 OK 按钮),以及 LPARAM 中 OK 按钮的句柄。其他按钮消息在这里

于 2013-02-14T22:34:19.053 回答