一、问题描述
对话框所有控件Controls可随对话框Dialog大小比例的变化而变化位置和大小。
二、解决方法
1 声明一对double值存储原始对话框大小m_OriginX & m_OriginY
2 声明一个CRect的向量 m_RectVector存储每个控件Control的Rect大小
3 对话框初始化时,初始化CRect 向量
4 对话框响应OnSize时,处理控件变化。先获取当前对话框大小cx & cy,分别求X轴、Y轴的大小变化比例ratio[2],
自m_RectVector中获取每个控件的左上角、右下角的点,两点的x、y值分别乘以ratio[0]、ratio[1],再MoveWindow
到新的位置。
5 比较好的一次性处理所有控件的方法:Windows的API函数 GetWindow()
6 为了Resize不出问题,最好通过OnGetMinMaxInfo消息设置对话框的最小尺寸
三、源代码
// .h文件
double m_nOriginX;
double m_nOriginY;
std::vector<CRect> m_RectVector;
void InitRectVector();
void ReSize();
// .cpp文件
// OnInitDialog()初始化中添加如下代码
CRect rect;
GetClientRect(&rect); //取客户区大小
m_nOriginX = double(rect.right - rect.left);
m_nOriginY = double(rect.bottom - rect.top);
// .cpp文件
void CTempChamberDlg::InitPtVector()
{
int id;
CRect rt;
HWND hChild = ::GetWindow(m_hWnd, GW_CHILD);
while(hChild)
{
id = ::GetDlgCtrlID(hChild);
GetDlgItem(id)->GetWindowRect(rt);
ScreenToClient(rt);
m_PtVector.push_back(rt);
hChild = ::GetWindow(hChild, GW_HWNDNEXT);
}
}
void CTempChamberDlg::ReSize()
{
double ratio[2];
CRect rt;
GetClientRect(&rt); //取客户区大小
double cx = rt.right - rt.left;
double cy = rt.bottom - rt.top;
ratio[0] = (double)cx / m_nOriginX;
ratio[1] = (double)cy / m_nOriginY;
int id;
CRect Rect;
CPoint OldTLPoint, TLPoint; //左上角
CPoint OldBRPoint, BRPoint; //右下角
std::vector<CRect>::iterator iter = m_PtVector.begin();
HWND hChild = ::GetWindow(m_hWnd, GW_CHILD); //列出所有控件
while(hChild)
{
id = ::GetDlgCtrlID(hChild);//取得ID
OldTLPoint = (*iter).TopLeft();
TLPoint.x = long(OldTLPoint.x * ratio[0]);
TLPoint.y = long(OldTLPoint.y * ratio[1]);
OldBRPoint = (*iter).BottomRight();
BRPoint.x = long(OldBRPoint.x * ratio[0]);
BRPoint.y = long(OldBRPoint.y * ratio[1]);
Rect.SetRect(TLPoint,BRPoint);
GetDlgItem(id)->MoveWindow(Rect,TRUE);
++iter;
hChild = ::GetWindow(hChild, GW_HWNDNEXT);
}
}
// .cpp文件
// OnSize消息 & OnGetMinMaxInfo消息
BEGIN_MESSAGE_MAP(CTempChamberDlg, CDialog)
//}}AFX_MSG_MAP
ON_WM_SIZE()
ON_WM_GETMINMAXINFO()
END_MESSAGE_MAP()
void CTempChamberDlg::OnSize(UINT nType, int cx, int cy)
{
CDialog::OnSize(nType, cx, cy);
if (nType==SIZE_RESTORED||nType==SIZE_MAXIMIZED)
{
ReSize();
}
}
void CTempChamberDlg::OnGetMinMaxInfo(MINMAXINFO* lpMMI)
{
lpMMI->ptMinTrackSize = m_ptMinTrackSize;
CDialog::OnGetMinMaxInfo(lpMMI);
}
四、参考尝试过的相关资源链接整理
1、界面布局动态调整
4、WTL CDialogResize extension (CodeProject)
5、CResizableDialog (CodeProject)
6、EasySize - Dialog resizing in no time
7、EASY_SIZE:控件随窗口变化自由调整大小
8、Easysize的使用