【问题标题】:Handling invalid window handle处理无效的窗口句柄
【发布时间】:2011-03-24 03:28:37
【问题描述】:
应用程序使用 Enum* 例程检索窗口句柄。
在应用程序管理枚举/创建窗口的句柄(获取类名、窗口统计信息...)时,该句柄不再有效。管理窗口句柄的代码使用 try/catch 块进行保护,但窗口句柄会被存储并依次用于管理所表示的窗口。
如何处理窗口句柄生命周期?是否可以检测到句柄无效?
我想避免每次应用程序使用窗口句柄时出现 try/catch 块。
【问题讨论】:
标签:
c#
windows
winapi
window-handles
【解决方案1】:
【讨论】:
-
-1 IsWindow 是您正在寻找的功能。此外,OP 需要通知句柄销毁,而不是验证句柄。
【解决方案2】:
您可以将其传递给IsWindow() 进行验证。
有几个注意事项,但两者都适用于几乎任何解决此问题的方法:
线程不应该使用 IsWindow
它没有创建的窗口,因为
之后窗户可能会被破坏
这个函数被调用了。进一步,
因为窗把手被回收
手柄甚至可以指向
不同的窗口。
如果您对自己的外部应用程序中的一个窗口执行此操作,则可以通过 Set/GetProp() 添加某种唯一标识符来添加第二层验证。
【解决方案3】:
窗口句柄只有在创建窗口的线程中使用时才是安全的。从任何其他线程中,您所能知道的关于窗口句柄的所有信息都是,它在过去的某个时间是有效的。现在,它可能是也可能不是,如果是,它可能指的是与预期完全不同的窗口。
【解决方案4】:
我已经有了实际的解决方案……但直到现在我才知道!
感谢大家对窗口句柄生命周期的澄清,其实窗口句柄生命周期有一种检测方法:CbtProc。
如果钩子安装在系统范围内,则可以通知特定应用程序(这完全取决于 CBT 钩子的实际实现)有关窗口销毁,这表明特定句柄在通知。
来自文档:
HCBT_DESTROYWND 指定要销毁的窗口句柄。
当然,使用 WINAPI 例程访问句柄必须与通知系统同步,这似乎没有很好的可行性(CBT 挂钩实际上阻止了窗口销毁,因为它与应用程序逻辑同步)。