轉載: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); //獲取ID爲i的空間的句柄,因爲“確認”ID爲1,“取消”ID爲2
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函數那麼簡單了,實現起來有點複雜。等我掌握了這個複雜的方法,一定會拿來分享的。
二
如果對話框或視類的大小調後,控件的大小和位置沒有變化,界面看起來會很不爽.
控件是從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);
}
方法也是在網上看到的!