书到用时方恨少!
一直没有用VC做过什么开发,眼下遇上任何一件小事都得从头来过。下面就是一个例子,记下来留作参考。
【要求】
1. 窗体大小可调的特殊要求:不允许比原始窗体更小,而且宽度不允许拉伸,即只允许高度拉伸;
2. 窗体中有一个文本框还有两个按钮,高度变化后所属控件要进行相应的位置调整。
【实现手法】
1. 窗体设计。新建对话框的Border默认为Dialog Frame,需要修改为Resizing;
2. 在窗体类的头文件中增加两个私有变量;
CSize m_OldSize; //保存上一次窗体大小 CRect m_rectOrigi; //窗体的原始位置及大小
3. 变量初始化(构架函数中);
//init m_rectOrigi = CRect(0, 0, 0, 0);
4. 获取窗体的初始大小(OnInitDialog中);
GetWindowRect(&m_rectOrigi);
5. 指定窗体的WM_SIZE消息事件的处理属性为OnSize;
6. OnSize方法代码;
void CTestDlg::OnSize(UINT nType, int cx, int cy) { CDialog::OnSize(nType, cx, cy); if(nType == SIZE_MINIMIZED) return; // 原本窗体大小尚没有初始化,则直接退出 if (m_rectOrigi.Width() != 0 && m_rectOrigi.Height()!= 0 ){ CRect rectNew; GetWindowRect(&rectNew); // 如果新的窗体宽度与原本的窗体宽度不同或是高度小于原本宽度,则恢复原本的窗体大小; // 即:只允许用户拉伸窗体高度。 if( (rectNew.Width() != m_rectOrigi.Width())) { MoveWindow(rectNew.left, rectNew.top, m_rectOrigi.Width(), rectNew.Height()); return; } if( (rectNew.Height() < m_rectOrigi.Height())) { MoveWindow(rectNew.left, rectNew.top, rectNew.Width(), m_rectOrigi.Height()); return; } } // 与上一次窗体高度或是宽度的相差 CSize SizeOff(cx - m_OldSize.cx, cy-m_OldSize.cy); // 改变窗体内控件的位置,参数即为offset值 ::EnumChildWindows(GetSafeHwnd(), EnumProc, (LPARAM)&SizeOff); if(GetDlgItem(IDD_TEST_DIALOG)->GetSafeHwnd()) { if(nType == SIZE_MAXIMIZED) GetDlgItem(IDD_TEST_DIALOG)->ShowWindow(SW_HIDE); else GetDlgItem(IDD_TEST_DIALOG)->ShowWindow(SW_SHOW); } // 更新窗体旧大小,用于下一次做比较。 m_OldSize =CSize(cx,cy); Invalidate(); }
7. OnSize中用到一个回调函数EnumProc,定义如下:
//////////全局函数 BOOL CALLBACK EnumProc(HWND hwnd, LPARAM lParam) { CWnd* pWnd = CWnd::FromHandle(hwnd); CSize* pSizeOff =(CSize*)lParam; CTestDlg* pDlg = (CTestDlg*)pWnd->GetParent(); if(!pDlg) return FALSE; CRect rect; pWnd->GetWindowRect(rect); pDlg->ScreenToClient(rect); if( hwnd == pDlg->m_btnCancel.GetSafeHwnd() || hwnd == pDlg->m_btnOK.GetSafeHwnd()) { pWnd->MoveWindow( rect.left+pSizeOff->cx, //改变左上坐标 rect.top+pSizeOff->cy, //改变左上坐标 rect.Width(), //宽度不变 rect.Height(), //高度不变 FALSE); } if( hwnd == pDlg->m_edit.GetSafeHwnd()) { pWnd->MoveWindow( rect.left, //左上坐标不变 rect.top, //左上坐标不变 rect.Width()+pSizeOff->cx, //改变宽度(由于别处的控制,此处也一定不会变更) rect.Height()+pSizeOff->cy, //改变高度 FALSE); } return TRUE; }
【参考资料】(第二个资料由于原始链接已经失效,给出的是百度快照。具体参见“0345 限制窗体的大小”)
1. http://hi.baidu.com/sysnapmfc/blog/item/763ae617ae184c1e972b43c4.html
【相关代码下载】