我正在开发一个仅限WinAPI的应用程序。我想创建一个静态子窗口,它将用作子控件的“容器”。在我到目前为止找到的示例中,“容器”窗口是在主窗口过程中捕获WM_CREATE创建的。我认为创建子窗口的子控件的最佳位置是捕获子窗口的WM_CREATE。为此,我首先需要对子窗口进行子类化,以指向新的窗口过程。问题是窗口是在它被子类化之前创建的,因此WM_CREATE被发送到原始过程,而不是我的用户创建的过程。当然,我可以在主窗口过程中创建子静态窗口之后创建子控件,但我不认为这是最好的方法。最好的选择是什么?
工作样例代码:
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_CREATE:
{
HWND hContainer = CreateWindow(WC_STATIC, L"Container", WS_CHILD, 0, 0, 100, 50, hWnd, (HMENU)ID_CONTAINER, NULL, NULL);
WNDPROC wpOldProc = (WNDPROC)SetWindowLongPtr(hContainer, GWLP_WNDPROC, (LONG_PTR)ChildWindowProc);
HWND hButton = CreateWindow(WC_BUTTON, L"Button", WS_CHILD | BS_PUSHBUTTON, 0, 0, 20, 10, hContainer, (HMENU)ID_BUTTON, NULL, NULL); // This works well
}
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
INT_PTR CALLBACK ChildWindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_CREATE:
{
// HWND hButton = CreateWindow(WC_BUTTON, L"Button", WS_CHILD | BS_PUSHBUTTON, 0, 0, 20, 10, hContainer, (HMENU)ID_BUTTON, NULL, NULL);
// This point is never reached because the WM_CREATE message is sent before subclassing of the window
}
break;
default:
break;
}
return CallWindowProc(gsHdl.wpTE, hWnd, message, wParam, lParam);
}发布于 2019-05-10 13:30:02
这里的主要原则是分离关注点:窗口通常会创建其子窗口来响应其WM_CREATE消息,如下所示:
这确保了窗口“拥有”其子窗口的创建。它还保证了当父窗口直接由classname创建时,所有的子窗口都会自动创建。最后,因为WM_CREATE是在窗口可见/绘制之前发送的,所以它可以确保在第一次绘制窗口时创建所有的子窗口。
当使用子窗口来组织子窗口时,这些注意事项中的许多都被忽略了:-如果你正在制作一个适当的抽象控件窗口,这是一回事,但如果你只是排列一些相对标准的窗口控件,你希望主窗口能够与之交互,那么深层的层次结构导航起来就很烦人,在鼠标和绘画发生的地方,你可能想要将容器和它的孩子按照“错误”的z顺序排列,如果严格地将它们安排为孩子/父母,你就无法实现。
也就是说,创建一个静态窗口并将返回的HWND用作后续行的父窗口并没有错--特别是如果这样做可以减少窗口类、代码行/创建卷积的数量,并简化父窗口与其控件的关系。
发布于 2019-05-10 16:59:34
在WM_CREATE消息下创建子窗口/控件可确保在成功创建窗口后创建子窗口/控件,并确保在创建主窗口时自动创建所有子窗口/子控件。
但我不认为它和下面的有太大的不同:
HWND hContainer = CreateWindow (WC_STATIC, L "Container", WS_CHILD, 0, 0, 100, 50, hWnd, (HMENU) ID_CONTAINER, NULL, NULL);
if(hContainer)
{
HWND hButton = CreateWindow (WC_BUTTON, L "Button", WS_CHILD | BS_PUSHBUTTON, 0, 0, 20, 10, hContainer, (HMENU) ID_BUTTON, NULL, NULL);
}它还保证了创建顺序和前提条件。
如果您确实需要修改WinProc并在标准窗口控件中捕获WM_CREATE消息,SetWindowsLongPtr不能满足您的要求。请先使用SetClassLongPtr,然后再创建容器。
https://stackoverflow.com/questions/56070609
复制相似问题