以编程方式关闭对话框 - win32

时间:2012-10-01 14:15:35

标签: c++ windows

我正在开发一个应用程序来检测弹出对话框然后 自动解雇它。我把它写成C ++ / Win32应用程序。该 对话框由IE 7生成,我可以检测到窗口,但是 使OK按钮“点击”的几种方法都失败了。

搜索其他人的解决方案,将这些消息发送给 按钮句柄似乎在很多情况下都有效:

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

虽然我的测试中对按钮状态没有影响。

我可以将制表符发送到主窗口,然后看到OK 按钮获得焦点,但然后发送返回字符什么都不做。

要了解更多相关信息,我使用Spy ++获取有关此内容的信息 窗口层次结构以及手动时传递的消息 单击“确定”按钮。

查看消息日志并阅读有关WM_MOUSEACTIVATE seamed的内容 提供解决方案。日志信息显示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/

2 个答案:

答案 0 :(得分:2)

理想情况下,您应该创建一个导出全局CBT Window Hook的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,类名或父类名时,我们可以调整它。

答案 1 :(得分:2)

在知道窗口类名称和窗口标题

的情况下,连续关闭特定弹出窗口
  #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;
  }

如果一个人不知道或太一般(例如&#34; Dialog&#34;)你可以通过传递空值来省略它

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

当然这将关闭所有具有给定名称的窗口。

相关问题