1. 程式人生 > >MFC 設定控制元件位置和大小

MFC 設定控制元件位置和大小

初始化對話方塊大小: ::SetWindowPos(this->m_hWnd, HWND_BOTTOM, 0, 0, 100, 500, SWP_NOZORDER);

最近經常要用到改變控制元件在對話方塊上的位置和大小,一直找不到有效的方法,查看了很多資料。這篇博文還算靠譜,轉載到這裡了。

  1. void CmyqeDlg::OnSize(UINT nType, int cx, int cy)  
  2. {  
  3.     CDialog::OnSize(nType, cx, cy);  
  4.     if(nType!=SIZE_MINIMIZED)  
  5.     {  
  6.          if (me) 
    // 判斷是否為空,因為對話方塊建立時會呼叫此函式,而當時控制元件還未建立 
  7.     {  
  8.             CRect rt;  
  9.             me.GetWindowRect(&rt);  
  10.          ScreenToClient(&rt);  
  11.             me.MoveWindow(rt.left,rt.top,cx-rt.left*2,cy-rt.top-rt.left);  
  12.     }  
  13. }  
  14. CWnd *pWnd;  
  15. pWnd = GetDlgItem( IDC_BUTTON1 );    //獲取控制元件指標,IDC_BUTTON1為控制元件ID號

用CWnd類的函式MoveWindow()或SetWindowPos()可以改變控制元件的大小和位置。
  1. void MoveWindow(int x,int y,int nWidth,int nHeight);  
  2. void MoveWindow(LPCRECT lpRect);  

SetWindowPos()函式使用更靈活,多用於只修改控制元件位置而大小不變或只修改大小而位置不變的情況:
BOOL SetWindowPos(const CWnd* pWndInsertAfter,int x,int y,int cx,int cy,UINT nFlags);
第一個引數我不會用,一般設為NULL;

x、y控制元件位置;cx、cy控制元件寬度和高度;
nFlags常用取值:
SWP_NOZORDER:忽略第一個引數;
SWP_NOMOVE:忽略x、y,維持位置不變;
SWP_NOSIZE:忽略cx、cy,維持大小不變;
例:
  1. CWnd *pWnd;  
  2. pWnd = GetDlgItem( IDC_BUTTON1 );    //獲取控制元件指標,IDC_BUTTON1為控制元件ID號
  3. pWnd->SetWindowPos( NULL,50,80,0,0,SWP_NOZORDER | SWP_NOSIZE );    //把按鈕移到視窗的(50,80)處
  4. pWnd = GetDlgItem( IDC_EDIT1 );  
  5. pWnd->SetWindowPos( NULL,0,0,100,80,SWP_NOZORDER | SWP_NOMOVE );    //把編輯控制元件的大小設為(100,80),位置不變
  6. pWnd = GetDlgItem( IDC_EDIT1 );  
  7. pWnd->SetWindowPos( NULL,0,0,100,80,SWP_NOZORDER );    //編輯控制元件的大小和位置都改變

以上方法也適用於各種視窗。


如果對話方塊或視類的大小調後,控制元件的大小和位置沒有變化,介面看起來會很不爽
控制元件是從CWnd派生的,但不能使用SetWindowPos()或OnSize()或OnSizing()來改變其大小,應在父視窗的WM_SIZE訊息中使用MoveWindow()來進行調整。


VC++之根據對話方塊大小調整控制元件大小
1、在對話方塊類中加入成員變數CRect m_rect;用於儲存對話方塊大小變化前的大小;
2、在對話方塊的OnInitDialog()函式中獲取對話方塊建立時的大小:GetClientRect(&m_rect);
3、在WM_SIZE的響應函式OnSize()中加入以下程式碼:
  1. CWnd * pWnd;  
  2. pWnd = GetDlgItem(IDC_LIST);      // 獲取控制元件控制代碼 
  3. if (pWnd) // 判斷是否為空,因為對話方塊建立時會呼叫此函式,而當時控制元件還未建立 
  4. {  
  5.           CRect rect;    // 獲取控制元件變化前大小 
  6.           pWnd -> GetWindowRect( & rect);  
  7.           ScreenToClient( & rect); // 將控制元件大小轉換為在對話方塊中的區域座標
  8.           //  cx/m_rect.Width()為對話方塊在橫向的變化比例 
  9.           rect.left = rect.left * cx / m_rect.Width(); /**//// //調整控制元件大小 
  10.          rect.right = rect.right * cx / m_rect.Width();  
  11.          rect.top = rect.top * cy / m_rect.Height();  
  12.          rect.bottom = rect.bottom * cy / m_rect.Height();  
  13.          pWnd -> MoveWindow(rect); // 設定控制元件大小 
  14. }   
  15. GetClientRect( & m_rect); // 將變化後的對話方塊大小設為舊大小

解決一個BUG: 
加上 if(nType!=1){} 
或者 if(nType!=SIZE_MINIMIZED ){} 
不然視窗最小化後再恢復就產生BUG(整數除以0).

貼一下對我自己實際問題的程式碼:

首先在標頭檔案中定義幾個變數:

  1. CRect rectPointList,rectCmdResponse;  
  2. CWnd *pWnd;  

然後在對話方塊初始化函式中儲存好需要獲取的控制元件的大小和位置

系統首先獲取的螢幕座標,獲取後要將螢幕座標轉換成使用者座標系:

  1.        pWnd = (CWnd *)GetDlgItem(IDC_STATIC_GROUPBOX_POINT_LIST);  
  2. pWnd->GetWindowRect(rectPointList);  
  3. ScreenToClient(rectPointList);  
  4. pWnd = (CWnd *)GetDlgItem(IDC_EDIT_RESPONSE);  
  5. pWnd->GetWindowRect(rectCmdResponse);  
  6. ScreenToClient(rectCmdResponse);  

在響應改變大小的函式中調整控制元件大小:
  1. pWnd = GetDlgItem(IDC_EDIT_RESPONSE);  
  2. pWnd->MoveWindow(rectCmdResponse.left,rectCmdResponse.top,rectCmdResponse.right-rectCmdResponse.left,rectCmdResponse.bottom-rectCmdResponse.top);  
  3. //pWnd->SetWindowPos(NULL,rectCmdResponse.left,rectCmdResponse.top,rectCmdResponse.right-rectCmdResponse.left,rectCmdResponse.bottom-rectCmdResponse.top,SWP_NOZORDER);
MoveWindow和SetWindowPos的功能是一樣,引數不一樣。然後四個點的座標,前兩個一個是控制元件左邊位置,一個是控制元件上邊位置,第三個是控制元件的寬度,要用右邊減去左邊,第四個高度,要用下邊減去上邊。

這樣就可以完美實現功能!

注意!!MFC中的Edit Control控制元件,如果往控制元件中寫入時換行使用的是\n,那麼在改變大小後,框裡面的文字在新的位置不是換行的!而是全部排成一行。

所以在向Edit Control中輸入文字時,最好!最好的換行使用 \r\n !!!!