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[];
POINT Newp; //获取现在对话框的大小
CRect recta;
GetClientRect(&recta); //取客户区大小
Newp.x=recta.right-recta.left;
Newp.y=recta.bottom-recta.top;
fsp[]=(float)Newp.x/old.x;
fsp[]=(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[]);
TLPoint.y = long(OldTLPoint.y*fsp[]);
OldBRPoint = Rect.BottomRight();
BRPoint.x = long(OldBRPoint.x *fsp[]);
BRPoint.y = long(OldBRPoint.y *fsp[]);
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

上一篇:Delphi让控件随着窗口的大小而改变


下一篇:[转] 智能指针(三):unique_ptr使用简介