【问题标题】:Validate HWND using Win32 API使用 Win32 API 验证 HWND
【发布时间】:2011-01-21 14:26:36
【问题描述】:

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

【问题讨论】:

  • 通常情况下,窗口句柄是否有效与我的特定问题无关。感谢所有的答案。

标签: c++ winapi


【解决方案1】:

您可以使用 Win32 API IsWindow

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

  1. 一旦窗口被销毁,窗口句柄就可以重新使用,所以你不知道你是否有一个完全不同的窗口的句柄。
  2. 此调用后状态可能会直接更改,您会认为它有效,但实际上可能无效。

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

线程不应该使用 IsWindow 它没有创建的窗口,因为 之后窗户可能会被破坏 这个函数被调用了。进一步, 因为窗把手被回收 手柄甚至可以指向 不同的窗口。

可以做什么?

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

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

【讨论】:

  • 那会有什么解决方案?
  • @Vlad:这取决于你想要完成什么。
  • @Brian: 判断一个HWND关联的窗口是否仍然有效?
  • @Vlad:我得到了这么多,但我的意思是在那之后你想做什么。这也是我的观点,一旦你知道并进入下一行代码,这个假设就会被打破,因为它可能已经关闭,甚至可以打开一个新的。
  • 值得一试,但另一个进程拥有的窗口在 IsWindow 调用后仍然会失效并导致问题。我会寻找其他解决方案。
【解决方案2】:

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

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

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

【讨论】:

  • 你真的应该引用那篇文章中重申的观点。 “此处描述的行为属于“实施细节”类别,随时可能更改”
  • 好点。谢谢。我将自己运行测试以查看此实现是否已更改。但是,我会说,这是一个没有意义的修复。除非有充分的理由重新占用那些高 16 位,否则我无法想象 MS 开发人员会想要让自己比修复之前更头痛。
  • “不太可能”与“不可能”不同。高位中的标记是为了减轻编程错误。这不是你应该刻意依赖的东西。
【解决方案3】:

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

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

我所知道的唯一解决方案是创建一个系统范围的hook 来查找指示窗口被破坏的消息(WM_CLOSE、WM_DESTROY)。然后,您会将消息窗口句柄与您持有的消息窗口句柄进行比较,以查看您关心的任何窗口是否受到影响。 See here for more information on system wide hooks.

【讨论】:

  • 发送 WM_NULL 消息可能不是一个好主意。一些应用程序实际上执行操作以响应 WM_NULL 消息。
【解决方案4】:

也许IsWindowFindWindowGetWindowThreadProcessId的组合会更准确

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
    }
}

【讨论】:

    【解决方案5】:

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

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

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

    【讨论】:

      【解决方案6】:
      if(IsWindow(FindWindow(NULL , TEXT("Example Window Name")))){
           // do stuff
       }
      

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

      【讨论】:

        猜你喜欢
        • 2021-08-09
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2010-12-04
        相关资源
        最近更新 更多