您的位置:首页 > 其它

判断一个窗口是否被挂起【小记】?

2012-02-26 20:45 369 查看
判断一个窗口是否被挂起了(就是没有响应了),在多窗口编程了经常会用到,在给别的窗口发消息前,为了目的窗口能确定收到消息,常常在之前先检测窗口是否被挂起了,我们以前常用的方式的是使用下面的方法:

// 判断一个窗口是否已经停止响应了(超时0.5秒)
DWORD_PTR dwResult = 0;
LRESULT lr = ::SendMessageTimeout(g_hWin, WM_NULL, 0, 0, SMTO_ABORTIFHUNG | SMTO_BLOCK, 500, &dwResult);
if (lr)
{
	// 还可以响应
}
else
{
	// 已经停止响应了(俗话说的窗口挂死了)
}
后来在(http://blog.csdn.net/wingeek/article/details/3875903)看到一种使用IsHungAppWindow这个API来直接判断窗口是否挂起的的方法,从MSDN上面看(http://msdn.microsoft.com/en-us/library/ms633526.aspx),这个API从windows2000就已经开始提供了,但是直到windowsxp_sp1和windows2003开始才提供了SDK。开始猜测是不是内部就是使用SendMessageTimeout实现,实时跟踪了下,发现不是。下面就是IsHungAppWindow的实现代码:

77D69C61 > 8BFF MOV EDI,EDI

77D69C63 55 PUSH EBP

77D69C64 8BEC MOV EBP,ESP

77D69C66 6A 04 PUSH 4

77D69C68 FF75 08 PUSH DWORD PTR SS:[EBP+8]

77D69C6B E8 6BEAFAFF CALL USER32.77D186DB

77D69C70 F7D8 NEG EAX

77D69C72 1BC0 SBB EAX,EAX

77D69C74 F7D8 NEG EAX

77D69C76 5D POP EBP

77D69C77 C2 0400 RETN 4

77D186DB B8 E3110000 MOV EAX,11E3

77D186E0 BA 0003FE7F MOV EDX,7FFE0300

77D186E5 FF12 CALL DWORD PTR DS:[EDX] ; ntdll.KiFastSystemCall

77D186E7 C2 0800 RETN 8

在IsHungAppWindow内部其实很简单,调用了USER32.77D186DB这个函数,这个函数其实就是NtUserQueryWindow(从后面可以看出77D186DB内部直接就调往内核了调用了,功能号EAX是11E3),其中7FFE0300既是KiFastSystemCall的地址,在看调用NtUserQueryWindow的地方,Push了两个参数,也就是NtUserQueryWindow(hwnd, 4),第一个参数是目的窗口的句柄,第二个参数是查询ID,也就是标明想查这个窗口的什么信息,4代表是查这个窗口是否挂起了,直接由ring0来实现了……
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: