C++ 使用 Win32 API 验证 HWND

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2344233/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-27 23:08:32  来源:igfitidea点击:

Validate HWND using Win32 API

c++winapi

提问by Doug Ferguson

From the native Win32 API using C++ is there a way to determine whether the window associated with an HWND is still valid?

从使用 C++ 的本机 Win32 API 有没有办法确定与 HWND 关联的窗口是否仍然有效?

回答by Brian R. Bondy

You could use the Win32 API IsWindow.

您可以使用 Win32 API IsWindow

It is not recommendedto use it though for 2 reasons:

不建议使用它,但有两个原因:

  1. Windows handles can be re-used once the window is destroyed, so you don't know if you have a handle to an entirely different window or not.
  2. The state could change directly after this call and you will think it is valid, but it may really not be valid.
  1. 一旦窗口被销毁,窗口句柄就可以重新使用,所以你不知道你是否有一个完全不同的窗口的句柄。
  2. 在这个调用之后状态可能会直接改变,你会认为它是有效的,但它可能真的无效。

From MSDN (same link as above):

来自 MSDN(与上面相同的链接):

A thread should not use IsWindow for a window that it did not create because the window could be destroyed after this function was called. Further, because window handles are recycled the handle could even point to a different window.

线程不应将 IsWindow 用于它未创建的窗口,因为在调用此函数后该窗口可能会被销毁。此外,因为窗口句柄被回收,句柄甚至可以指向不同的窗口。

What can be done?

可以做什么?

Perhaps your problem can be re-architected so that you do not have the need to check for a valid handle. Maybe for example you can establish a pipe from the client to the server.

也许您的问题可以重新设计,这样您就无需检查有效句​​柄。例如,您可以建立从客户端到服务器的管道。

You could also create a windows hook to detect when certain messages occur, but this is probably overkill for most needs.

您还可以创建一个 windows 钩子来检测某些消息何时发生,但这对于大多数需求来说可能是过度的。

回答by Yap Dog

This question is old, but I needed this functionality myself and was a bit disappointed after reading about the caveats. However, after doing a bit more digging it seems that all is well. Unless you're dealing with 16bit programs, IsWindow appears to be the way to go. The problem of handle re-use appears to have been sufficiently addressed according to this:

这个问题很老,但我自己需要这个功能,在阅读了警告后有点失望。然而,在做更多的挖掘之后,似乎一切都很好。除非您正在处理 16 位程序,否则 IsWindow 似乎是要走的路。手柄重用的问题似乎已经根据这个得到了充分的解决:

http://blogs.msdn.com/b/oldnewthing/archive/2007/07/17/3903614.aspx

http://blogs.msdn.com/b/oldnewthing/archive/2007/07/17/3903614.aspx

So, because of the upper 16bit reuse counter, it is highly unlikely that you'll run into a window reuse problem.

因此,由于较高的 16 位重用计数器,您不太可能遇到窗口重用问题。

回答by Dana Holt

You can use IsWindow()or also try to send the window a WM_NULL message with SendMessage(hWnd, WM_NULL) and see if it is successful.

您可以使用IsWindow()或尝试使用SendMessage(hWnd, WM_NULL)向窗口发送 WM_NULL 消息并查看它是否成功。

Also, it is true that the window could be destroyed at any time if it isn't under your control. As others have stated the handle could potentially belong to another window as the handles are reused. In reality I don't know how likely that is.

此外,如果窗口不在您的控制之下,它确实可以随时销毁。正如其他人所说,当句柄被重用时,句柄可能属于另一个窗口。实际上,我不知道这有多大可能。

The only solution that I know of the to create a system wide hookthat looks for messages indicating a window is destroyed (WM_CLOSE, WM_DESTROY). Then you would compare the message window handle to ones you are holding to see if any of the windows you care about are affected. See here for more information on system wide hooks.

我所知道的唯一解决方案是创建一个系统范围的挂钩,该挂钩查找指示窗口已销毁的消息(WM_CLOSE、WM_DESTROY)。然后您将消息窗口句柄与您持有的窗口句柄进行比较,以查看您关心的任何窗口是否受到影响。有关系统范围钩子的更多信息,请参见此处。

回答by IdontCareAboutReputationPoints

Maybe a combination of IsWindow, FindWindowand GetWindowThreadProcessIdwill be more accurate

也许的组合IsWindowFindWindow并且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
    }
}

回答by Nemanja Trifunovic

回答by Chip Camden

If the window procedure for the window in question is under your control (or if you can subclass it), then I would suggest registering a custom message that the window responds to with a non-zero result. Sending that message to any other window (or an invalid HWND) will result in 0.

如果有问题的窗口的窗口过程在您的控制之下(或者您可以将其子类化),那么我建议注册一个自定义消息,该窗口以非零结果响应该消息。将该消息发送到任何其他窗口(或无效的 HWND)将导致 0。

Of course, that only tells you if the HWND refers to one of the windows that you control -- but perhaps given other answers above that might even be advantageous.

当然,这只会告诉您 HWND 是否指的是您控制的窗口之一——但也许上面给出的其他答案甚至可能是有利的。

Use RegisterWindowMessage to register the message, using a sufficiently unique name.

使用 RegisterWindowMessage 注册消息,并使用足够唯一的名称。

回答by Anthony Bachler

if(IsWindow(FindWindow(NULL , TEXT("Example Window Name")))){
     // do stuff
 }

will check if the window exists and has the appropriate name

将检查窗口是否存在并具有适当的名称