在调试应用程序以尝试提高性能时,我发现它在处理大于0xC000的消息时会浪费时间.这显然是RegisterWindowMessageAPI 创建的消息.但是,该应用程序使用了超过两百个这样的消息; 有没有办法通过数值找到邮件的原始名称?
该GetAtomName和GlobalGetAtomName失败,
ERROR_INVALID_HANDLE
错误.
话虽如此,RegisterWindowMessage()并且RegisterClipboardFormat()碰巧当前共享一个原子表(以及一些其他API函数),因此在当前版本的Windows中,您可以使用GetClipboardFormatName()获取已注册窗口消息的名称.
这在Raymond Chen的MSDN博客上有所描述:
如何调查大量泄露窗口类(RegisterClass)的可能性?
碰巧在当前版本的Windows中,注册的类名,注册的剪贴板格式名和注册的窗口消息名都来自同一个原子表.我想重申,这是一个可以随时更改的实现细节,因此不要对此有任何依赖.我提供此信息用于诊断目的,这就是我们在这里所拥有的.
客户遇到问题后即可执行此操作:
Run Code Online (Sandbox Code Playgroud)Foreach atom in (0xC000 .. 0xFFFF) If (GetClipboardFormatName(atom, buffer, bufferSize)) Print buffer这将打印出所有类,剪贴板格式和已注册窗口消息的名称.原子表中有16,384个原子的空间,实际上不超过一百个,所以如果你看到超过15,000个条目,这是一个非常好的迹象表明你正在泄漏类.
我将从注册窗口消息开始,由RegisterWindowMessage函数创建.这些不是正式的原子 ; 它们只是位于0xC000到0xFFFF范围内的整数,就像原子一样.但是,在内部,他们是原子.当然,你不应该依赖它,因为它不是契约性的.把它想象成一个奇妙的巧合.
由RegisterClipboardFormat消息创建的注册剪贴板格式也不是正式原子 ; 他们只是UINT.甚至没有指定注册剪贴板格式的数字范围; 它们在0xC000范围内挂起只是一个实现细节.有一天,注册的剪贴板格式可能有像0x1234这样的值,谁知道.
因此,正如我所说,目前没有官方API来获取已注册的窗口消息的名称,但是您现在可以通过将注册的窗口消息与注册的剪贴板格式相同来解决这个问题.但是如果实施永远改变,那么GetClipboardFormatName()以这种方式使用可能会在将来中断RegisterWindowMessage().