将子窗口停靠到父窗口
当用户调整主窗口大小(拖动角)时,我需要 6 个控件(主窗口的子窗口)变大。我认为我可以通过使用 MoveWindow 函数更改主窗口的 WM_SIZE 或 WM_SIZING 函数中每个子窗口的比例来实现此目的。这样做会使调试构建变得奇怪(多个窗口、退出后窗口的图像粘连等)。发布版本运行良好,但当我调整主窗口大小时,子窗口没有改变。
我发现 http://msdn.microsoft .com/en-us/library/ms632598%28v=VS.85%29.aspx#creating_enumeating_etc 使用了不同的方法来执行此操作:通过枚举所有子窗口,以及处理窗口大小调整的枚举回调函数通过分配给每个孩子的唯一 ID。我自己尝试过,调整主窗口大小时对控件没有任何影响。
为什么这不起作用?
在主窗口 switch 语句中:
case WM_SIZING:
GetClientRect(hwnd, &hwndRect);
EnumChildWindows(hwnd, EnumChildProc, (LPARAM)&hwndRect);
break;
子枚举器回调函数:
BOOL CALLBACK EnumChildProc(HWND hwndChild, LPARAM lParam)
{
LPRECT hwndRect = (LPRECT)lParam;
switch(GetWindowLong(hwndChild, GWL_ID))
{
case ID_CHILD_LLABEL:
MoveWindow(hwndChild, 0, 0, (hwndRect->right - hwndRect->left) - 30, 20, false);
break;
case ID_CHILD_LDIR:
MoveWindow(hwndChild, 12, 20, (hwndRect->right - hwndRect->left) - 40, 20, false);
break;
case ID_CHILD_LLIST:
MoveWindow(hwndChild, 12, 40, (hwndRect->right - hwndRect->left) - 40, (hwndRect->bottom - hwndRect->top) - 238, false);
break;
}
}
I need my 6 controls (child windows of the main window) to get larger when the main window gets resized by the user (dragging the corners). I thought I could accomplish this by using the MoveWindow function to change the proportions of each child in the main window's WM_SIZE or WM_SIZING function. Doing this made the Debug build go strange (multiple windows, image of the window sticking after exiting, etc). The Release build ran fine but the child windows didn't change when I resized the main window.
I found http://msdn.microsoft.com/en-us/library/ms632598%28v=VS.85%29.aspx#creating_enumerating_etc used a different method of doing this: by enumerating all the child windows, and the enum callback function handling the window resizing through a unique ID assigned to every child. Upon trying this myself, it made no difference to the controls when the main window got resized.
Why isn't this working?
In the main windows switch statement:
case WM_SIZING:
GetClientRect(hwnd, &hwndRect);
EnumChildWindows(hwnd, EnumChildProc, (LPARAM)&hwndRect);
break;
The child enumerator callback function:
BOOL CALLBACK EnumChildProc(HWND hwndChild, LPARAM lParam)
{
LPRECT hwndRect = (LPRECT)lParam;
switch(GetWindowLong(hwndChild, GWL_ID))
{
case ID_CHILD_LLABEL:
MoveWindow(hwndChild, 0, 0, (hwndRect->right - hwndRect->left) - 30, 20, false);
break;
case ID_CHILD_LDIR:
MoveWindow(hwndChild, 12, 20, (hwndRect->right - hwndRect->left) - 40, 20, false);
break;
case ID_CHILD_LLIST:
MoveWindow(hwndChild, 12, 40, (hwndRect->right - hwndRect->left) - 40, (hwndRect->bottom - hwndRect->top) - 238, false);
break;
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
来自 MSDN 有关 WM_SIZE 的文章:“如果由于 WM_SIZE 消息而为子窗口调用 SetScrollPos 或 MoveWindow 函数,则 bRedraw 或 bRepaint 参数应为非零,以便重新绘制窗口。”
我怀疑儿童控件正在移动,它们只是没有被重新绘制。
还可能值得验证您的开关盒是否确实受到撞击。
编辑:
我错过了显而易见的事情。您正在响应 WM_SIZING,这表明窗口的大小即将(但尚未)更改。 WM_SIZE 表示大小已改变。如果要使用WM_SIZING,则需要使用lParam中携带的rect,而不是GetClientRect的结果。不幸的是,WM_SIZING 矩形是窗口的矩形,而不是客户区域,并且位于屏幕坐标中。除非您确实需要在用户仍在执行调整大小时显示调整大小的控件,否则仅处理 WM_SIZE 消息会更容易。
From MSDN's article on WM_SIZE: "If the SetScrollPos or MoveWindow function is called for a child window as a result of the WM_SIZE message, the bRedraw or bRepaint parameter should be nonzero to cause the window to be repainted."
I suspect the child controls are moving, they simply aren't being repainted.
It might also be worth verifying that your switch cases are actually being hit.
Edit:
I missed the obvious. You are responding to WM_SIZING, which indicates that the size of the window is about to (but has not yet) changed. WM_SIZE indicates that the size has changed. If you want to use WM_SIZING, you need to use the rect carried in the lParam, not the results of GetClientRect. Unfortunately the WM_SIZING rect is the rect of the window, not the client area, and is in screen coordinates. Unless you really need to display the resized controls while the user is still performing the resize, it would be much easier to just handle the WM_SIZE message.