MFC 控件大小隨窗體改變而改變大小-OnSize

轉載:https://blog.csdn.net/zhoxier/article/details/7776128

一個基於對話框的MFC界面,怎麼樣才能讓對話框裏的控件能和對話框同比例變小變大?今天我一直想解決這個問題,這是師姐留給我的任務。經過在網上的大量搜素,終於找到了解決方法,其實比較簡單。

   一般情況下,我們新建的對話框,裏面的確定和:取消按鈕,在對話框最大化得時候,不會一起變大的,而是保持原來的大小。

   最簡單的情況:

 

   當我們點擊最大化按鈕的時候,對話框會最大化,但是控件確定取消不會跟着變大。如果我們在對話框上面有多少控件,那麼會很醜,而且很不實用,最大化本來就是想看的更清楚嘛。

   我們可以採取下面的措施:對話框也是窗口,最大化是對窗口大小的改變,而在windows messagehandle中有個WM_SIZE的消息,該消息在窗口大小發生變化的時候會產生。那麼我們可以根據這個消息,在窗口大小發生變化的時候,利用MoveWindow()函數來重新設置各個控件的大小。

   還是以上面最簡單的情況爲例子:

 1  首先要知道對話框大小是否改變,改變了多少,我們應該記錄當前對話框的大小。

    在對話框類中添加成員變量 CRect m_rect  他是用來記錄當前對話框的大小。我們在OnInitDialog()函數中獲取對話框創建時的大小:GetClientRect(&m_rect);

 2 增加消息WM_SIZE的消息響應函數 OnSize():只要對話框大小發生變化,就會調用該函數。

 3 OnSize()函數中增加如下代碼:(最簡單的爲例子,就一個確定按鈕和取消按鈕)

來源:(http://blog.sina.com.cn/s/blog_4b5039210100dzkd.html)- MFC:如何讓對話框中的控件和對話框一起變小變大_蕭蕭_新浪博客

 

  voidCTestDlg::OnSize(UINT nType, int cx, int cy)
{
 CDialog::OnSize(nType, cx, cy);
 
 // TODO: Add your message handler code here
  for (int i=1;i<=2;i++)     
//因爲是兩個控件,所以這裏用了循環
  {

  CWnd*pWnd; 
  pWnd = GetDlgItem(i);    
//獲取IDi的空間的句柄,因爲確認”ID1取消”ID2
 if(pWnd)  //判斷是否爲空,因爲對話框創建時會調用此函數,而當時控件還未創建

  {
   CRect rect;  
//獲取控件變化前的大小  

  pWnd->GetWindowRect(&rect);
   ScreenToClient(&rect
//將控件大小轉換爲在對話框中的區域座標
  //cx/m_rect.Width()
爲對話框在橫向的變化比例

  rect.left=rect.left*cx/m_rect.Width();//調整控件大小
   rect.right=rect.right*cx/m_rect.Width();
   rect.top=rect.top*cy/m_rect.Height();
   rect.bottom=rect.bottom*cy/m_rect.Height();
   pWnd->MoveWindow(rect);//
設置控件大小
  }

  }
  GetClientRect(&m_rect);//
將變化後的對話框大小設爲舊大小

 
 }

 

  然後運行,當對話框最大化的時候,兩個按鈕也變大了。

 

               (因爲全屏圖太大,我只截取了右上角的部分)

 
PS:其實這種方法實現起來簡單,但是是存在問題的,如果界面有很多控件,那個當你拖拽窗口的角的時候,經過幾次變大變小,你會發現其實裏面的控件已經失真了,就不是原來的長寬比例了。那麼要實現不管窗口怎麼變,裏面的控件不但大小跟着變,而且大小比例也跟着變,那就不是這個OnSize函數那麼簡單了,實現起來有點複雜。等我掌握了這個複雜的方法,一定會拿來分享的。

 

mfc 控件大小隨窗體改變而改變

  如果對話框或視類的大小調後,控件的大小和位置沒有變化,界面看起來會很不爽.

  控件是從CWnd派生的,但不能使用SetWindowPos()或OnSize()或OnSizing()來改變其大小,應在父窗口的WM_SIZE消息中使用MoveWindow()來進行調整。

  VC++之根據對話框大小調整控件大小

  1、在對話框類中加入成員變量CRect m_rect;用於保存對話框大小變化前的大小;

  2、在對話框的OnInitDialog()函數中獲取對話框創建時的大小:

  GetClientRect(&m_rect);

  3、在WM_SIZE的響應函數OnSize()中加入以下代碼:

  CWnd *pWnd;

  pWnd = GetDlgItem(IDC_LIST);   //獲取控件句柄

  if(pWnd)//判斷是否爲空,因爲對話框創建時會調用此函數,而當時控件還未創建

  {
  CRect rect;  //獲取控件變化前大小
  pWnd->GetWindowRect(&rect);
  ScreenToClient(&rect);//將控件大小轉換爲在對話框中的區域座標
  // cx/m_rect.Width()爲對話框在橫向的變化比例
  rect.left=rect.left*cx/m_rect.Width();/////調整控件大小
  rect.right=rect.right*cx/m_rect.Width();
  rect.top=rect.top*cy/m_rect.Height();
  rect.bottom=rect.bottom*cy/m_rect.Height();
  pWnd->MoveWindow(rect);//設置控件大小
  }
  GetClientRect(&m_rect);//將變化後的對話框大小設爲舊大小

 

 如果是裏面只有一兩個控件倒好辦,但控件太多的話這樣做是不是重複勞動太多了?
有沒有更好的辦法啊?

視類中加成員函數和成員變量:
        void   SetControlInfo(WORD   CtrlId);
protected:
        int   m_old_cx,m_old_cy;
        CDWordArray   m_control_info;
 
構造函數中初始化:
        m_old_cx   =   m_old_cy   =  0;
 
加控件信息的函數定義:
void   CTestFormView::SetControlInfo(WORD   CtrlId)
{
        m_control_info.Add(CtrlId);
 
}
 


修改OnSize函數:
void   CTestFormView::OnSize(UINT   nType,   int   cx,  int   cy)
{
        if(cx==0   ||   cy==0)
        {
                cx=800;
                cy=600;
        }
        CFormView::OnSize(nType,   cx,   cy);
        float   dx_percent   =   (m_old_cx  ==0)?   1   :   (float)((float)cx/(float)m_old_cx);
        float   dy_percent   =   (m_old_cy  ==0)?   1   :     (float)((float)cy/(float)m_old_cy);
 
        if(m_old_cx)
        {
                CRect   WndRect;
                CWnd   *pWnd;
                for(int   i  =   0;   i   <   m_control_info.GetSize();   i++)
                {
                       pWnd   =   GetDlgItem(m_control_info[i]);
                       if(!pWnd)
                       {
                               TRACE( “Control   ID   -  %d   NOT   FOUND!!\n “,m_control_info[i]);


                               continue;
                       }
 
                       pWnd-> GetWindowRect(&WndRect);
                       ScreenToClient(&WndRect);
 
                       WndRect.left   =   (int)(WndRect.left*dx_percent);
                       WndRect.right   =   (int)(WndRect.right*   dx_percent);
                       WndRect.bottom   =   (int)(WndRect.bottom*dy_percent);
                       WndRect.top   =   (int)(WndRect.top*dy_percent);
 
                       pWnd-> MoveWindow(&WndRect);
                }
 
        }
        m_old_cx   =   cx;
        m_old_cy   =   cy;
}
 
在OnInitialUpdate函數中加入控件ID:
        SetControlInfo(IDC_BUTTON1);
            。。。。。。。。。。。。。。。。


  運行,搞定!
Dialog也一樣!

 


上面是轉載的內容,補充一些,就是,當在運行上面的程序後,當dlg爲僅剩下標題欄時,再放大,就不會顯示內部的控件,那麼自己設置了窗體的最小值:

void CDataBaseConfigDlg::OnGetMinMaxInfo(MINMAXINFO* lpMMI)
{
// TODO: 在此添加消息處理程序代碼和/或調用默認值
if(lpMMI->ptMinTrackSize.x <= 800)
lpMMI->ptMinTrackSize.x = 800;
if(lpMMI->ptMinTrackSize.y <= 500)
lpMMI->ptMinTrackSize.y = 500;
CDialogEx::OnGetMinMaxInfo(lpMMI);
}

方法也是在網上看到的!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章