11

我一直认为 WM_CREATE 是窗口收到的第一条消息。然而,在顶层窗口上测试这个假设时,结果证明是错误的。在我的测试中,WM_MINMAXINFO 作为第一条消息出现。

那么,一个窗口保证接收的第一条消息是什么?

4

4 回答 4

17

WM_NCCREATE实际上是您的窗口将收到的第一条消息,它会在之前到达WM_CREATE。它与创建非客户区(例如标题栏、系统菜单等)有关,因此是NC前缀。

WM_GETMINMAXINFO在窗口大小/位置改变之前发送,并且可能在之前到达WM_CREATE(更多信息见下文)。

WM_CREATE消息在返回之前发送,CreateWindow()因此您可以保证每个窗口的初始化已在该点执行。您的窗口 proc 将WM_CREATE在窗口创建后但在窗口变为可见之前(WM_SHOWWINDOW)接收。

实际上,MSDN 文档中有一个有趣的不一致之处——创建消息似乎取决于您是否调用CreateWindow()CreateWindowEx(),但它并未指定消息必须按调度顺序列出。

  • CreateWindow():和WM_CREATE_WM_GETMINMAXINFOWM_NCCREATE
  • CreateWindowEx(): WM_NCCREATE,WM_NCCALCSIZEWM_CREATE

我强烈怀疑中描述的消息顺序CreateWindow()应该有WM_NCCREATE第一个,常规的WM_CREATE最后一个,这与通知文档和CreateWindowEx()参考一致(也与您描述的一致)。

Raymond Chen 也有一些关于窗口创建/销毁的有趣信息

它只是表明,即使是看似简单的事情,你越看越复杂。

于 2009-11-16T10:38:10.370 回答
8

你是在自问自答。我也在 Windows XP SP3 上看到 WM_GETMINMAXINFO,然后是 WM_NCCREATE、WM_NCCALCSIZE,最后是 WM_CREATE,然后 CreateWindowEx() 甚至还返回了正在创建的窗口的句柄。什么垃圾'

一般的答案是微软在有序地创建和销毁对象方面是无能的。他们在 windows、COM 和设备驱动程序上都搞错了。总是有一些 catch-22 对象是半创建或半破坏的,这需要一些迂回复杂的解决方案来生产可靠的产品。

于 2009-12-19T23:37:23.323 回答
4

通过实验得出的结果比仅仅相信源代码要好,尤其是因为源代码是由大量程序员组成的,而且没有人知道所有的代码。那说:

我收到的第一条消息是 0x24 (WM_GETMINMAXINFO)。

我可以假设它永远是第一条消息吗?不,因为 Windows 版本之间的代码更改,并且 Microsoft 没有记录保证是第一个收到的消息。

底线:不要假设 WM_CREATE 在另一条消息之前被调用。

于 2011-03-06T16:00:45.803 回答
2

您可以使用 Visual Studio 附带的 spy++ 来查看启动应用程序或窗口时生成的消息。

于 2009-11-20T12:04:44.437 回答