【发布时间】:2013-01-05 21:26:32
【问题描述】:
我正在 Win32 上创建一个简单的框架,但我似乎无法捕获任何 WM_COMMAND 消息。我将通过 WndProc 的所有消息打印到输出控制台,但没有 WM_COMMAND 消息。我的程序由一个窗口和一个编辑框(带有“EDIT”类)组成。
这是我的临时消息循环(仅用于测试):
MSG msg;
BOOL ret;
while( ( ret = ::GetMessage( &msg, NULL, 0, 0 ) ) > 0 )
{
if(msg.hwnd == NULL)
continue;
else if(ret == -1)
break;
else {
::TranslateMessage( &msg );
::DispatchMessage( &msg );
}
}
这是 WndProc:
LRESULT CALLBACK Win32Base::GlobalWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
Win32Base *pWindow;
pWindow = reinterpret_cast<Win32Base*>( GetWindowLong( hWnd, GWL_USERDATA ) );
if( pWindow ) {
MSG msgdata;
msgdata.hwnd = hWnd;
msgdata.message = msg;
msgdata.wParam = wParam;
msgdata.lParam = lParam;
return pWindow->OnMessage( msgdata );
}
return DefWindowProc(hWnd, msg, wParam, lParam);
}
我也在子类化编辑框。我可以捕捉到它的 WM_CHAR 消息等,但没有 WM_COMMAND 消息(但是,我认为它们不应该存在)。
我觉得问题可能出在我处理育儿的方式上。我添加了 Windows 父级的动态更改,当创建控件时,它可能还没有父级。所以如果我用WS_CHILD创建一个控件,会因为没有父控件而报错。因此,当我分配父级时,我还附加了 WS_CHILD 样式(或删除它,如果我要删除父级)。这是一个好习惯吗?也许它可能阻止主窗口接收编辑框的 WM_COMMAND 消息?
另外,当我输入时,编辑框不会自己重新绘制,我必须强制它重新绘制,这非常慢......
【问题讨论】:
-
如果在您键入时编辑框没有自行重新绘制,那么您的代码存在严重错误...您是否在
OnMessage上转发您不处理的消息? -
无关,但如果您希望您的代码在 64 位 Windows 上运行,则需要使用
GetWindowLongPtr和SetWindowLongPtr(注意Ptr后缀)而不是Get/SetWindowLong。否则,指向Win32Base对象的指针将被截断。 -
您的
else if(ret == -1)永远不会是真的。您可以安全地删除它。除此之外,EDIT 控件将永远不会收到WM_COMMAND消息。WM_COMMAND消息在单击按钮时发送到 BUTTON 控件的 父级,或者在选择命令时发送到 MENU 的所有者。 -
当编辑控件中的文本发生更改时,它会向其父级发送
EN_CHANGE通知。这是Edit Control Notifications的完整列表。 -
还有一件事,与您的问题无关:使用
GWLP_USERDATA相当不可靠,因为每个人都可以读写它。一个更健壮的解决方案是通过cbWndExtra在WNDCLASSstructure中分配额外的空间并将指针存储在那里。
标签: c++ winapi frameworks