MFC控件随窗口大小变化原理及实现
本文主要针对MFC的dialog,实现控件随窗口大小变化。
原理:首先获取dialog的初始大小,当窗口发送变动时,调用OnSize事件和方法,计算缩放比例,然后对界面中的所有控件进行缩放和布局。
实现:
创建一个CMFCDemoDlg的dialog对话框;
// CMFCDemoDlg 对话框 class CMFCDemoDlg : public CDialogEx { // 构造 public: CMFCDemoDlg(CWnd* pParent = NULL); // 标准构造函数 // 对话框数据 enum { IDD = IDD_MFCDEMO_DIALOG }; protected: virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV 支持 protected: CRect m_rect; void ChangeSize(UINT nID,int x,int y); void ReSize(void); POINT old; protected: // 生成的消息映射函数 virtual BOOL OnInitDialog(); afx_msg void OnSize(UINT nType, int cx, int cy); DECLARE_MESSAGE_MAP() };
在OnInitDialog方法中获取dialog的初始大小,记录到old变量中;
注册OnSize事件处理方法(ON_WM_SIZE(), OnSize()函数),设置控件大小
CMFCDemoDlg::CMFCDemoDlg(CWnd* pParent /*=NULL*/) : CDialogEx(CMFCDemoDlg::IDD, pParent) { m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME); } void CMFCDemoDlg::DoDataExchange(CDataExchange* pDX) { CDialogEx::DoDataExchange(pDX); } BEGIN_MESSAGE_MAP(CMFCDemoDlg, CDialogEx) ON_WM_SIZE() END_MESSAGE_MAP() // CMFCDemoDlg 消息处理程序 BOOL CMFCDemoDlg::OnInitDialog() { CDialogEx::OnInitDialog(); // 获取对话框初始大小 GetClientRect(&m_rect); //获取对话框的大小 old.x=m_rect.right-m_rect.left; old.y=m_rect.bottom-m_rect.top; return TRUE; } void CMFCDemoDlg::ReSize(void) { float fsp[2]; POINT Newp; //获取现在对话框的大小 CRect recta; GetClientRect(&recta); //取客户区大小 Newp.x=recta.right-recta.left; Newp.y=recta.bottom-recta.top; fsp[0]=(float)Newp.x/old.x; fsp[1]=(float)Newp.y/old.y; CRect Rect; int woc; CPoint OldTLPoint,TLPoint; //左上角 CPoint OldBRPoint,BRPoint; //右下角 HWND hwndChild=::GetWindow(m_hWnd,GW_CHILD); //列出所有控件 while(hwndChild){ woc=::GetDlgCtrlID(hwndChild);//取得ID GetDlgItem(woc)->GetWindowRect(Rect); ScreenToClient(Rect); OldTLPoint = Rect.TopLeft(); TLPoint.x = long(OldTLPoint.x*fsp[0]); TLPoint.y = long(OldTLPoint.y*fsp[1]); OldBRPoint = Rect.BottomRight(); BRPoint.x = long(OldBRPoint.x *fsp[0]); BRPoint.y = long(OldBRPoint.y *fsp[1]); Rect.SetRect(TLPoint,BRPoint); GetDlgItem(woc)->MoveWindow(Rect,TRUE); hwndChild=::GetWindow(hwndChild, GW_HWNDNEXT); } old=Newp; } void CMFCDemoDlg::OnSize(UINT nType, int cx, int cy) { CDialogEx::OnSize(nType,cx,cy); if(nType!=SIZE_MINIMIZED ) //判断窗口是不是最小化了,因为窗口最小化之后 ,窗口的长和宽会变成0,当前一次变化的时就会出现除以0的错误操作 { ReSize(); } }
通过hwndChild=::GetWindow(m_hWnd,GW_CHILD);和::GetWindow(hwndChild, GW_HWNDNEXT); 列出所有控件
也可针对特定控件设置其大小,如:
//change control size void CMFCDemoDlg::ChangeSize(UINT nID,int x,int y) { CWnd *pWnd = GetDlgItem(nID); if(pWnd!=NULL) { CRect rec; pWnd->GetWindowRect(&rec);//获取控件变化前的大小 ScreenToClient(rec); //将控件大小装换位在对话框中的区域坐标 // x / m_rect.Width(); 伸缩rate rec.left = rec.left * x / m_rect.Width(); rec.top = rec.top * y / m_rect.Height(); rec.bottom = rec.bottom * y / m_rect.Height(); rec.right = rec.right * x / m_rect.Width(); pWnd->MoveWindow(rec);//伸缩控件 } }
参考:http://blog.csdn.net/lujianfeiccie2009/article/details/5485602