繁体   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