将子窗口停靠到父窗口
Posted
技术标签:
【中文标题】将子窗口停靠到父窗口【英文标题】:Docking a child window to the parent window 【发布时间】:2011-02-21 16:59:05 【问题描述】:当用户调整主窗口的大小(拖动角)时,我需要我的 6 个控件(主窗口的子窗口)变大。我想我可以通过使用 MoveWindow 函数来更改主窗口的 WM_SIZE 或 WM_SIZING 函数中每个子项的比例来实现这一点。这样做会使 Debug 构建变得奇怪(多个窗口、退出后窗口的图像等)。发布版本运行良好,但当我调整主窗口大小时子窗口没有改变。
我发现http://msdn.microsoft.com/en-us/library/ms632598%28v=VS.85%29.aspx#creating_enumerating_etc 使用了不同的方法:枚举所有子窗口,枚举回调函数通过分配给每个子窗口的唯一 ID 来处理窗口大小调整。亲自尝试后,调整主窗口大小时对控件没有影响。
为什么这不起作用?
在主窗口切换语句中:
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;
【问题讨论】:
你有什么理由不使用为你做这类事情的众多框架之一? 【参考方案1】:来自MSDN's article on WM_SIZE:“如果由于 WM_SIZE 消息而为子窗口调用 SetScrollPos 或 MoveWindow 函数,则 bRedraw 或 bRepaint 参数应为非零,以导致重新绘制窗口。” 我怀疑子控件正在移动,它们根本没有被重新绘制。
还可能值得验证您的 switch case 是否真的被击中。
编辑: 我错过了明显的。您正在响应 WM_SIZING,这表明窗口的大小即将(但尚未)更改。 WM_SIZE 表示大小发生了变化。如果要使用WM_SIZING,需要使用lParam中携带的rect,而不是GetClientRect的结果。不幸的是,WM_SIZING 矩形是窗口的矩形,而不是客户区,并且位于屏幕坐标中。除非您确实需要在用户仍在执行调整大小时显示调整大小的控件,否则只处理 WM_SIZE 消息会容易得多。
【讨论】:
我用InvalidateRect()函数重绘了窗口,什么也没发生。我尝试使用 EnumChildWindows() 移动我的 MoveWindow() widhout,这一次所有子窗口都在调整大小时闪烁。我仍然有控件没有变大的问题,但至少我知道它没有达到枚举器回调代码。将 BRedraw/paint 参数的 false 更改为 true 不会影响它。重绘与重绘有什么不同吗?如果它们相同,则无法解决问题。 @Greg 更新了我的答案。您在计算新控件大小时使用了错误的矩形。以上是关于将子窗口停靠到父窗口的主要内容,如果未能解决你的问题,请参考以下文章