[英]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.