应用程序使用 Enum* 例程检索窗口句柄。
碰巧在应用程序管理枚举/创建窗口的句柄(获取类名,窗口统计信息......)时,句柄不再有效。管理窗口句柄的代码使用 try/catch 块进行保护,但窗口句柄被存储并随后用于管理所表示的窗口。
如何处理窗口句柄生命周期?是否可以检测到句柄无效?
每次应用程序使用窗口句柄时,我都想避免 try/catch 块。
应用程序使用 Enum* 例程检索窗口句柄。
碰巧在应用程序管理枚举/创建窗口的句柄(获取类名,窗口统计信息......)时,句柄不再有效。管理窗口句柄的代码使用 try/catch 块进行保护,但窗口句柄被存储并随后用于管理所表示的窗口。
如何处理窗口句柄生命周期?是否可以检测到句柄无效?
每次应用程序使用窗口句柄时,我都想避免 try/catch 块。
窗口句柄只有在创建窗口的线程中使用时才是安全的。从任何其他线程中,您所能知道的关于窗口句柄的所有信息都是,它在过去的某个时间是有效的。现在,它可能是也可能不是,如果是,它可能指的是与完全预期不同的窗口。
我已经有了实际的解决方案……但直到现在我才知道!
感谢大家对窗口句柄生命周期的澄清,但实际上有一种检测窗口句柄生命周期的方法:CbtProc。
如果钩子安装在系统范围内,则可以通知特定应用程序(这完全取决于 CBT 钩子的实际实现)有关窗口销毁,这表明特定句柄在通知后将无效。
从文档中:
HCBT_DESTROYWND 指定要销毁的窗口的句柄。
当然,使用 WINAPI 例程访问句柄必须与通知系统同步,这似乎没有很好的可行性(CBT 挂钩实际上阻止了窗口销毁,因为它与应用程序逻辑同步)。
您可以将其传递给以IsWindow()
进行验证。
有一些警告,但是两者都适用于几乎任何方法:
线程不应将 IsWindow 用于它没有创建的窗口,因为在调用此函数后窗口可能会被销毁。此外,由于窗口句柄被回收,句柄甚至可以指向不同的窗口。
如果您对自己的外部应用程序中的一个窗口执行此操作,则可以通过 Set/GetProp()'ing 某种唯一标识符添加第二层验证。
您可以使用该GetWindowInfo
功能。如果句柄无效,则返回 0。