对话框内部控件自动缩放类
作者: Lonkil
邮箱:lonkil_AT_Gmail.com
当对话框中控件数量过多,且需要进行缩放的时,需要手工在Onsize中为每个控件位置和大小的计算,实现繁琐。本文的主要思想来自网上的一篇资料,但由于转载已造成数据的不完整,我根据该文章的思想重新实现,且补充完整了该类。效果如下图:


通过上面两幅图,第一幅图是缩放前的,第二幅图是缩放后的。上面的编辑框以及Button1是按对框等比例缩放,”确定”按钮是水平居中对齐,”取消”按钮是垂直居中对齐。”我是静态文本框”是水平等比例平移的。
这个缩放类,主要思想在对话框Onsize进行拦截,统一处理。关于CAutoCtrlSize中的AS_OnSize具体实现可以参看代码。
下面我简述一下类的使用步骤:
1. 在对话框初始化时,将本对话框中所有需要自动调整位置及大小的控件加到类中。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | //如果不想用全局的话,这里用static解决变量过期问题 static AS_CTRLDATA aryCtrls[]= { {IDC_EDIT1, AS_SIZEXY, 100, AS_A_LEFT, false, CSize(0,0)} ,{IDC_BUTTON1,(AS_MOVEX| AS_SIZEX),100, AS_A_LEFT, true, CSize(0,0)} ,{IDC_STATIC_1,AS_MOVEX,100, AS_A_LEFT, false, CSize(0,0)} ,{IDOK,AS_MOVEXY,100, AS_A_H_CENTER, false, CSize(0,0)} ,{IDCANCEL,AS_MOVEXY,100, AS_A_V_CENTER, false, CSize(0,0)} }; m_pAutoSize = new CAutoCtrlSize(); if( m_pAutoSize ) { m_pAutoSize->AS_InitData((PAS_CTRLDATA )aryCtrls, sizeof(aryCtrls)/sizeof(AS_CTRLDATA), m_hWnd ); } |
AS_CTRLDATA这个结构体需要详细描述一下。
1 2 3 4 5 6 7 8 9 | typedef struct { DWORD dwCtrlID;/*控件ID*/ UINT asType;/*缩放或移动类型*/ int nScale;/*缩放或移动比例*/ AS_Align_Type alignType; bool isMiniSize;//是否限定最小尺寸 CSize szMiniSize;//最小尺寸 }AS_CTRLDATA,* PAS_CTRLDATA; |
dwCtrlID:需要进行变化的控件ID
asType:该控件移动属于什么类型以及其组合。AS_MOVEX水平移动,AS_MOVEY垂直移动等,请参见AS_TYPE。
nScale:缩放比例,当对话框尺寸进行一定变化,该类控件按些指定的比例进行同步缩放。范围0到100。
alignType:基于哪种方式进行缩放,如是AS_A_LEFT则基于左边对齐,AS_A_H_CENTER则是基于水平距中对齐,AS_A_V_CENTER则是基于垂直距中对齐。
isMiniSize: 是否限定最小尺寸。如果限定将以对话框初始化的大小作为最小尺寸
szMiniSize:初始值是0,0,如果指定了isMiniSize后,将用于保存最小尺寸。
2. 在对话框中的OnSize中调用CAutoCtrlSize为中的AS_OnSize。
1 2 3 4 5 6 7 8 9 | void CAutoSizeDlg::OnSize(UINT nType, int cx, int cy) { CDialog::OnSize(nType, cx, cy); if( m_pAutoSize ) { m_pAutoSize->AS_OnSize(nType, cx, cy ); } } |
在此将使用我们的类来处理所有缩放。
3. 在GetMinMaxInfo中调用AS_FixSize限定最小尺寸。
1 2 3 4 5 6 7 8 9 | void CAutoSizeDlg::OnGetMinMaxInfo(MINMAXINFO* lpMMI) { // TODO: 在此添加消息处理程序代码和/或调用默认值 if( m_pAutoSize ) { m_pAutoSize->AS_FixSize(lpMMI); } CDialog::OnGetMinMaxInfo(lpMMI); } |
最小尺寸将是对话框的初始大小。
到此已经完成该类的使用,如果您在使用中有什么麻烦或Bug请邮件通知本人,如果您有更好的修改请发一份给我谢谢。Lonkil_AT_Gmail.com或去我小站留言
AutoSize_src.zip (43.8 KiB, 1,041 hits)
12 条评论
楼主,我用你编写的程序在vc 6下试了一下,出现7个以下错误(只列举一个)
error C2440: ‘initializing’ : cannot convert from ‘const int’ to ‘AS_CTRLDATA’;
后来我单独把你定义的数据结构体拿出来调试,问题出现在 {IDC_EDIT1, AS_SIZEXY, 100, AS_A_LEFT, false, CSize(0,0)}中CSize(0,0),这样赋值在vc2010下编译通过,也能运行,但是在vc6下怎么都通不过。不知道是什么原因,没有完全明白Csize的赋值机制。请楼主赐教。我的邮箱是yousheng324@tom.com,谢谢!
请问怎么手动赋值啊。谢谢
To colin:
在进行初始窗口控件集时,使用手动赋值。不要使用我的demo中的那种集体赋值。
博主,小弟在VC6.0中也碰到了如下问题,
error C2440: ‘initializing’ : cannot convert from ‘const int’ to ‘AS_CTRLDATA’
请问是如何解决的?
就要看你那控件,不是继承于CWND,或有单独的句柄了。
按钮这些都有效果,但是对我一个特殊图形化的控件却不起效果,什么原因呢?
谢谢。
对的,指针需要初始化一下.
我看你博客中《对话框内部控件自动缩放类》一文,我觉得很有用!我有一个用VC++6.0编写的基于对话框的小程序,也需要实现动态缩放的功能。按照文章的指引,我在VC++6.0环境中添加语句和函数,出现了一下一个错误:
在对话框的OnInitDialog()中“添加需要自动调整位置及大小的控件加到类中”这里,我按照要求添加我所需要的调整的控件,但是编译时7个类型相同的错误,比如:error C2440: ‘initializing’ : cannot convert from ‘const int’ to ‘AS_CTRLDATA’;
后来我把工程用VS2005打开,编译连接通过,但是一运行就报错了,通过调试,发现是在调用这个函数OnGetMinMaxInfo(MINMAXINFO FAR* lpMMI)时没有传递有限的窗口尺寸参数(相关的窗口尺寸参数全是未知)而导致错误发生。
之后我对比了您给的在VS2005环境下的例程,发现你的例程中一开始的流程是这样的:
程序开始->CAutoSizeDlg::OnSize(UINT nType, int cx, int cy)->CDialog::OnSize(nType, cx, cy)->BOOL CAutoSizeDlg::OnInitDialog()中的m_pAutoSize = new CAutoCtrlSize()->m_pAutoSize->AS_InitData()->CAutoSizeDlg::OnInitDialog()函数结束->出现对话框…改变对话框大小->void CAutoSizeDlg::OnGetMinMaxInfo(MINMAXINFO* lpMMI)对窗口事件处理->新的窗口;
而我的程序一开始的流程是:
程序开始->窗口还没有出现就跳转到::OnGetMinMaxInfo(MINMAXINFO FAR* lpMMI)->lpMMI参数的m_szOriginalWinSize.cx 和m_szOriginalWinSize.cy说是“ cx CXX0030: 错误: 无法计算表达式的值”和“cy CXX0030: 错误: 无法计算表达式的值 ”,然后就出错了!
同时我通过“VS2005的查找和替换”工具查找“OnSize”字段,发现你我的程序中有个差异:
你的函数调用了“\Program Files\Microsoft Visual Studio 8\VC\atlmfc\include\afxwin2.inl(415):_AFXWIN_INLINE void CWnd::OnSize(UINT, int, int)”
而我的程序就是缺少这一项,也不知道是不是问题所在!
—————————————————————————
后来的到作者的赐教,终于把问题解决,先把解决方法贴出来,以供大家参考:
产生这个问题是由于你的m_pAutoSize指针未初始化造成非法访问.
由于在进入OnInitDialog之前,也就是在CreateWindow的时候,系统会调用OnGetMinMaxInfo,造成了非法访问.
如下修改即可.
CComTestDlg::CComTestDlg(CWnd* pParent /*=NULL*/)
: CDialog(CComTestDlg::IDD, pParent),m_pAutoSize(NULL)
遇到问题,请赐教!
QQ:929739889
MSN:iwillbeback008@hotmail.com
哈哈,老大是说我折腾的博客皮肤么?
这几天自己折腾的,不懂什么色彩搭配就搞一点朴素一点的.
中规中矩,喜欢这样的风格。基本功最能体现一个人技术修养!
强大~~