簡體   English   中英

以編程方式關閉對話框 - win32

[英]Programmatically closing a dialog box - win32

我正在開發一個應用程序來檢測彈出對話框,然后自動關閉它。 我把它寫成C ++ / Win32應用程序。 該對話框由IE 7生成,我可以檢測到窗口,但有幾種方法可以使OK按鈕“點擊”失敗。

搜索其他人的解決方案,將這些消息發送到按鈕句柄似乎在很多情況下都有效:

PostMessage( handle, WM_LBUTTONDOWN, 0, 0 );
PostMessage( handle, WM_LBUTTONUP, 0, 0 );
PostMessage( handle, BM_SETSTATE, 1, 0 );

但它在我的測試中對按鈕狀態沒有影響。

我可以將制表符發送到主窗口,看到確定按鈕獲得焦點,但是發送返回字符什么都不做。

要了解更多相關信息,我使用Spy ++獲取有關窗口層次結構的信息以及手動單擊“確定”按鈕時所傳遞的消息。

查看消息日志並閱讀有關WM_MOUSEACTIVATE聯合提供解決方案的信息。 日志信息顯示0002166C是按鈕窗口。 所以在我的代碼中我嘗試了這個:

GetClassNameA( handle, str, str_size );

if( strcmp( str, "Internet Explorer_Server" ) != 0 )
    return TRUE; // Not the window we're interested in.

// Send a message to activate the button window and have it process a mouse click.
PostMessage( handle, WM_MOUSEACTIVATE, (WPARAM) dialog_handle, MAKELPARAM( HTCLIENT, WM_LBUTTONDOWN );

根據窗口層次結構和消息日志,我認為類名為“Internet Explorer_Server”的窗口是按鈕。 也許我錯了,因為它看起來像按鈕的奇怪的類名...

下面是窗口層次結構圖像的鏈接,當我手動單擊“確定”按鈕時的消息日志。 最后是在1秒計時器票證上執行的代碼,查找窗口。

任何見解和幫助表示贊賞!

此處提供了窗口層次結構,源,窗口消息和測試對話框源的圖像:

https://sites.google.com/site/matthewmillersmiscellanea/Home/

理想情況下,您應該創建一個導出全局CBT窗口掛鈎的DLL。 這將允許您在創建對話框時獲得早期通知。 這將避免通過不斷輪詢來消耗資源的需要。

一旦檢測到即將創建對話框,您有兩個選擇:

1)防止創建對話框。

我不建議這樣做,它會導致各種問題,而這些代碼完全期望CreateDialog()返回有效的HWND;

2)異步控制對話框。

我們通過使用帶有注冊用戶消息的PostMessage並通過掛鈎WNDPROC來獲取它來實現這一點。 收到此消息后,您必須決定如何終止您所在的對話框。

退出對話框有多種方法:

a)使用WM_COMMAND(BN_CLICKED)模擬按OK,取消,中止,無按鈕(作為Chris評論)。 您可以使用GetDlgItem(),查找WindowText並做出選擇。 但是,這不適用於非美國英語。 盡管如此,在利用Accessibility API可能還有一段距離。

b)使用PostMessage(WM_CLOSE,m_hWnd)模擬關閉對話框。 這並不總是按預期工作 - 某些對話框沒有[X]關閉按鈕,並且他們的客戶端代碼期望按下特定按鈕。

c)使用SendInput()API模擬用戶輸入。 這解決了在其中有反彈出殺手代碼的對話框:)

我們的最終解決方案是基於規則+啟發式的方法,該方法具有配置文件,當app / IE對話框更改其ID,類名或父類名時,我們可以調整該配置文件。

在知道窗口類名稱和窗口標題的情況下,連續關閉特定彈出窗口

  #define UNICODE

  #include <windows.h>

  #pragma comment(lib, "user32")

  int main (int nn, char ** aa)
  {
     while (true) {
        HWND iHandle = FindWindow (L"theWindowClassName", L"theWindowCaption");
        if (iHandle > 0) SendMessage(iHandle, WM_SYSCOMMAND, SC_CLOSE, 0);
        Sleep (200); // check 5 times per second
     }
     return 0;
  }

如果一個未知或太一般(例如“Dialog”),您可以通過傳遞null來省略它

 HWND iHandle = FindWindow (L"theWindowClassName", 0);
 or
 HWND iHandle = FindWindow (0, L"theWindowCaption");

當然,這將關閉所有給定名稱的窗口。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM