【发布时间】:2011-01-21 14:26:36
【问题描述】:
从使用 C++ 的本机 Win32 API 是否可以确定与 HWND 关联的窗口是否仍然有效?
【问题讨论】:
-
通常情况下,窗口句柄是否有效与我的特定问题无关。感谢所有的答案。
从使用 C++ 的本机 Win32 API 是否可以确定与 HWND 关联的窗口是否仍然有效?
【问题讨论】:
您可以使用 Win32 API IsWindow。
不建议使用它,原因有两个:
来自 MSDN(与上面相同的链接):
线程不应该使用 IsWindow 它没有创建的窗口,因为 之后窗户可能会被破坏 这个函数被调用了。进一步, 因为窗把手被回收 手柄甚至可以指向 不同的窗口。
可以做什么?
也许您的问题可以重新设计,这样您就无需检查有效句柄。例如,也许您可以建立从客户端到服务器的管道。
您还可以创建一个 windows 挂钩来检测某些消息何时发生,但这对于大多数需求来说可能是多余的。
【讨论】:
这个问题很老,但我自己需要这个功能,在阅读了这些警告后有点失望。但是,在进行了更多挖掘之后,似乎一切都很好。除非您正在处理 16 位程序,否则 IsWindow 似乎是要走的路。句柄重用的问题似乎已经根据这个得到了充分的解决:
http://blogs.msdn.com/b/oldnewthing/archive/2007/07/17/3903614.aspx
因此,由于高 16 位重用计数器,您不太可能遇到窗口重用问题。
【讨论】:
您可以使用IsWindow() 或尝试使用SendMessage(hWnd, WM_NULL) 向窗口发送WM_NULL 消息,看看是否成功。
另外,如果窗口不在您的控制之下,它确实可能随时被破坏。正如其他人所说,当句柄被重用时,句柄可能属于另一个窗口。实际上,我不知道这种可能性有多大。
我所知道的唯一解决方案是创建一个系统范围的hook 来查找指示窗口被破坏的消息(WM_CLOSE、WM_DESTROY)。然后,您会将消息窗口句柄与您持有的消息窗口句柄进行比较,以查看您关心的任何窗口是否受到影响。 See here for more information on system wide hooks.
【讨论】:
也许IsWindow、FindWindow和GetWindowThreadProcessId的组合会更准确
HWND windowHandle = FindWindow(NULL, TEXT("window_title"));
LPDWORD oldpid = 0;
GetWindowThreadProcessId(windowHandle, &oldpid);
//after some time
if (IsWindow(windowHandle))
{
LPDWORD newpid = 0;
GetWindowThreadProcessId(windowHandle, &newpid);
if (newpid == oldpid)
{
//the window is still running
}else
{
//the window exists but has changed
}
}
【讨论】:
如果有问题的窗口的窗口过程在您的控制之下(或者如果您可以对其进行子类化),那么我建议注册一个自定义消息,该窗口以非零结果响应该消息。将该消息发送到任何其他窗口(或无效的 HWND)将导致 0。
当然,这只会告诉您 HWND 是否引用了您控制的窗口之一——但也许上面给出的其他答案甚至可能是有利的。
使用 RegisterWindowMessage 注册消息,使用足够唯一的名称。
【讨论】:
if(IsWindow(FindWindow(NULL , TEXT("Example Window Name")))){
// do stuff
}
将检查窗口是否存在并具有适当的名称
【讨论】: