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

posted @ 2016-10-31 22:01  小小鸟的大梦想  阅读(17002)  评论(1编辑  收藏  举报