2013-02-14 33 views
0

我創建了一個具有2個按鈕的窗體。一個按鈕彈出一個msgbox,另一個按照下面列出的frmAPI(代碼如下)運行。如果我打開msgbox並將其保持打開狀態,然後運行frmAPI,它將列出msgbox及其文本,然後關閉它。這是我期望它做的。如果我打開另一個應用程序並在該應用程序中生成msgbox,並且我的frmAPI仍在運行,它實際上會列出其他應用程序msgbox和文本,但它不會從另一個應用程序關閉msgbox。如果Irun來自其他應用程序的frmAPI並執行相同的測試,則結果會相反。簡而言之,它只會關閉同一個應用程序中的對話框。API SendMessage()不適用於外部應用程序對話框

我希望能夠從任何應用程序關閉對話框,基於它是一個對話框,並具有符合我的標準的文本。任何幫助我做錯了什麼?

感謝

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 
+2

發送WM_NCDESTROY不會破壞窗口。 [它只是惡作劇 - 稱之爲窗口](http://blogs.msdn.com/b/oldnewthing/archive/2011/09/26/10216420.aspx)。如果你的目標是自動化關閉按鈕,那麼使用'System.Windows.Automation'命名空間。閱讀'Name'屬性以獲取消息框的文本,並使用'InvokePattern.Invoke()'推動OK按鈕。 – 2013-02-14 22:25:37

+0

我正在使用WM_Close選項,然後嘗試使用基於我閱讀的另一篇文章的WM_Destroy。感謝這是一件好事。至於使用system.windows.automation命名空間,這將適用於所有對話框,而不管它來自何處?這是否意味着我將不再使用Windows API方法? – 2013-02-15 17:41:33

+0

自動化名稱空間可以控制任何具有UI(並且通過可訪問性公開自己的東西,大多數應用程序至少在基本級別執行操作,因爲Windows自動提供基本級別)。不確定第二個問題的含義。您正在使用自動化方法(包裝相應的Windows API方法)。 – 2013-02-15 18:29:58

回答

1

您可能正在運行到User Interface Privilege Isolation。這會阻止您的消息進入更高的權限流程。另請參見ChangeWindowsMessageFilter()

我建議嘗試發送一個WM_COMMAND而不是WM_CLOSE;系統通常會更輕鬆地對待WM_COMMAND,並且可能會通過。使用BN_CLICKED作爲WPARAM和IDOK的高位字作爲低位字(假設它具有OK按鈕)以及LPARAM中的OK按鈕的句柄。其他按鈕消息是here

+0

你不認爲發送錯誤信息是一個更嚴重的問題。沒有任何UIPI緩解措施可以解決這個問題。 – 2013-02-14 22:51:24

+0

今天早上我開始啓動我的應用程序,並試圖在SQL對話框上使用WM_COMMAND代碼,詢問我是否希望將更改保存在查詢中。有3個選項。我的應用打破了這一行:GetWindowText(txtHandle,sb,len + 1)帶有字符串生成器錯誤。如果我跳過這條線,那麼它就起作用了。然後我將其更改回WM_Close,現在它也可以工作。這對我來說有點困惑。 WM_COMMAND能否改變權利? – 2013-02-15 17:46:10

相關問題