网上查阅有多种方法,选学一种笔记如步骤下。
1 搭建完成控件随对话框变化比例变化的框架
1.1 在对话框类中的消息映射宏中添加对话框尺寸改变时的消息宏
- BEGIN_MESSAGE_MAP( theClass, baseClass )
- ON_WM_SIZE()
- END_MESSAGE_MAP()
ON_VM_SIZE消息,此消息(VC定义的宏)表示只要窗口大小发生变化时就系统就自动调用此消息对应的函数OnSize(UINT nType, intcx, int cy)。
VM_SIZE消息宏对应的消息如下表所列举:
SIZE_MAXHIDE 4 | Message is sent to all pop-up windows when some other window is maximized.当有窗口最大化时,此消息发送给所有在上层的窗口,告之隐藏。 |
SIZE_MAXIMIZED2 | The window has been maximized.当窗口已经被最大化后。 |
SIZE_MAXSHOW3 | Message is sent to all pop-up windows when some other window has been restored(恢复) to its former size. |
SIZE_MINIMIZED1 | The window has been minimized. |
SIZE_RESTORED0 | The window has been resized, but neither the SIZE_MINIMIZED norSIZE_MAXIMIZED value applies. |
1.2 因为此消息宏对应的唯一函数为OnSize,所以在添加此消息后需要到.cpp文件中编写此函数,实现目标功能的代码
1.3 在编写此函数时(前 | 后 )需要到对话框继承类中声明此函数
2 实现目标功能
2.1 首先在对话框的OnInitDialog函数中获取对话框客户区的大小
- CRect rect;
- GetClientRect(&rect);
- oSize.x = rect.right - rect.left;
- oSize.y = rect.bottom - rect.top;
此处GetClientRect函数的原型为:
void GetClientRect(
LPRECT lpRect
) const;
函数功能:将CWnd类窗口的客户区域的坐标赋值到lpRect所指的结构体中。
参数含义:指向RECT类型的结构体或者CRect对象接受客户区域的坐标。此参数的left和top成员的值将会是0,right和bottom成员的值包含了窗口客户区域的宽度和高度。
oSize是在继承对话框类中的数据成员,类型为POINT。根据lpRect参数含义,后面的两行语句就记住了窗体客户区域的宽度和高度。
2.2 重载OnSize函数
- //-------------------------------------------------
- //对话框尺寸变化时,对话框内的控件随之改变大小函数
- //--------------------------------------------------
- void CDMarriageMatchDlg::OnSize(UINT nType, int cx, int cy)
- {
- CDialogEx::OnSize(nType, cx, cy);
- if (nType==SIZE_RESTORED || nType==SIZE_MAXIMIZED)
- {
- float ratio[2];
- POINT newDialogSize;
- CRect newRect;
- //获取新的客户区的大小
- GetClientRect(&newRect);
- newDialogSize.x = newRect.right - newRect.left;
- newDialogSize.y = newRect.bottom - newRect.top;
- //得现在的对话框与以往对话框的大小比例
- ratio[0] = (float)newDialogSize.x / oSize.x;
- ratio[1] = (float)newDialogSize.y / oSize.y;
- CRect Rect;
- int woc;
- //左右上角的数据
- CPoint OldTLPoint, NewTLPint;
- CPoint OldBRPoint, NewBRPint;
- //列出所有控件
- HWND hwndChild = ::GetWindow(m_hWnd,GW_CHILD);
- while(hwndChild)
- {
- //取得ID
- woc = ::GetDlgCtrlID(hwndChild);
- GetDlgItem(woc)->GetWindowRect(Rect);
- ScreenToClient(Rect);
- OldTLPoint = Rect.TopLeft();
- NewTLPint.x = long(OldTLPoint.x*ratio[0]);
- NewTLPint.y = long(OldTLPoint.y*ratio[1]);
- OldBRPoint = Rect.BottomRight();
- NewBRPint.x = long(OldBRPoint.x*ratio[0]);
- NewBRPint.y = long(OldBRPoint.y*ratio[1]);
- Rect.SetRect(NewTLPint,NewBRPint);
- GetDlgItem(woc)->MoveWindow(Rect,TRUE);
- hwndChild=::GetWindow(hwndChild, GW_HWNDNEXT);
- }
- //获取视频窗口父窗口的大小
- ::GetClientRect(hWnd, &grc);
- oSize = newDialogSize;
- }
- }
(1) 在此函数中的GetClientRect表示在窗口有变动时就会在窗口改变尺寸( 以非SIZE_MINIMIZED norSIZE_MAXIMIZED 时)或者窗口已经最大化的情况下重新获取窗口的尺寸并获得窗口的宽度和高度。
(2) 获取对话框中的所有控件
实现这一个功能利用window函数,函数原型为:
HWND WINAPI GetWindow(
_In_ HWND hWnd,
_In_ UINT uCmd
);
函数功能:检索hWnd所指向的窗口与特殊窗口cCmd之间的关系。
参数:hWnd索要检测的父窗口。
uCmd父窗口中的所属控件类型( 与hWnd窗口的关系,具体参数含义在VS2010中 按F1查询 )。
程序中的m_hWnd表示对话框(当对话框是所有的窗口最上面那个的时候 ),GW_CHILD表示当前最上面窗口的子窗口( 如对话框内的控件 )。
(3) 在用GetWindow获取hWnd(对话框 )内子窗口( 控件 )成功时,就进入while中进行下一步操作。
第一步是用GetDlgCtrlID函数获取此控件的标识符,此函数有唯一的参数,就是此控件的句柄( 由GetWindow函数返回 如hwndChild)。
第二步是利用GetDlgItem(F1)函数返回指向控件或子窗口的指针,并用此指针访问GetWindowRect方法,目的是获取到指针所指向控件( 猜:此指针已属此控件定义的一种指针对象 )的尺寸大小,并返回给GetWindowRect中的参数Rect。
第三步是利用ScreenToClient函数将获取的尺寸转换成客户区的尺寸。ScreenToClient函数的参数可为POINT或者CRect类型。此程序为CRect类型。
第四步是计算对话框尺寸改变后控件在客户区的新坐标。由对话框整个客户区改变的比例(新坐标比上旧坐标 )来确定对话框中的控件的坐标应该怎么变化:控件的新坐标与整个对话框成比例变化。所以就得到了控件的新坐标:
- OldTLPoint = Rect.TopLeft();
- NewTLPint.x = long(OldTLPoint.x*ratio[0]);
- NewTLPint.y = long(OldTLPoint.y*ratio[1]);
- OldBRPoint = Rect.BottomRight();
- NewBRPint.x = long(OldBRPoint.x*ratio[0]);
- NewBRPint.y = long(OldBRPoint.y*ratio[1]);
第五步是用CRect::SetRect方法设定CRect特定的坐标。
第六步是利用将当前控件的MoveWindow方法将控件的位置移到新设定的坐标之上。
void MoveWindow(
LPCRECT lpRect,
BOOL bRepaint = TRUE
);
第一个参数即是CRect对象或者RECT结构体指定的新坐标。
第六步就hwndChild=::GetWindow(hwndChild,GW_HWNDNEXT);可单纯的认为是获取对话框内下一个子控件。
如此循环,就将对话框内的所有的控件都按照对话框尺寸变化给变化完成了。
第7步:等对话框中所有的控件都变化完毕之后,对话框的大小要更新为当前对话框的大小,这个理念,做过程序设计的都懂。下次对话框尺寸再发生变化时,就在oSize的基础之上在执行此函数中的代码,对话框内控件随对话框成比例变化功能完成。
此次笔记记录完毕。