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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM