在用VC开发应用程序时,经常会要做一些可以改变大小的对话框,而这个时候就要求对话框上的控件会随着对话框大小的改变而改变自己的位置和大小。如果控件比较少,那可以在对话框的OnSize()事件里面添加代码,通过计算来调整各个控件的位置和大小;但是,如果对话框上的控件比较多的话,那这将是一件非常痛苦的事情!要是程序中又有很多可以改变大小的对话框,那一个一个的OnSize()写下来,那会使程序员崩溃的!
为了解决这个问题,我写了一个自动改变控件位置和大小的对话框类ClxDialog。从这个类继承的对话框类,只要在OnInitDialog()里对控件做一些简单的设置,对话框上的控件就会随着对话框大小的改变而改变自己的位置和大小(当然,别忘了把对话框的Border属性改为Resizing)。
为了保存控件信息,我定义了一个结构:
typedef
struct
_dlgControlTag
{
int
iId;
//
控件ID
int
iFlag;
//
标志,表示怎样改变控件的位置或者大小
int
iPercent;
//
改变值占对话框改变值的百分比
} DLGCTLINFO,
*
PDLGCTLINFO;
这里要对结构中的iFlag和iPercent进行一些解释。其中iFlag是下面的枚举值:
enum
{
MOVEX
=
0
,
//
控件在X方向(左右)移动
MOVEY,
//
控件在Y方向(上下)移动
MOVEXY,
//
控件在X方向和Y方向同时移动
ELASTICX,
//
控件在X方向(宽度)改变大小
ELASTICY,
//
控件在Y方向改(高度)改变大小
ELASTICXY
//
控件在X方向和Y方向同时改变大小
};
iPercent表示改变值占对话框改变值的百分比。例如,一个控件的iPercent值为100,iFlag值为MOVEX,那么当对话框的宽度改变100个单位的时候,这个控件就在X方向移动100个单位;又如,一个控件的iPercent值为100,iFlag值为ELASTICXY,那么当对话框的宽度和高度分别改变100个单位的时候,控件的高度和宽度也相应的改变100个单位。
下面是设置控件信息的函数:
BOOL SetControlProperty(PDLGCTLINFO lp,
int
nElements);
使用起来非常简单,在对话框的OnInitDialog()函数里面添加类似下面的代码就行了:
//
控件信息数组
static
DLGCTLINFO dcMenuGroup[]
=
{
{IDOK, MOVEX,
100
},
{IDCANCEL, MOVEX,
100
},
{IDC_BUTTON1, MOVEX,
50
},
{IDC_BUTTON1, MOVEY,
100
},
{IDC_EDIT1, ELASTICX,
100
},
{IDC_EDIT2, ELASTICX,
50
},
{IDC_EDIT3, ELASTICX,
50
},
{IDC_EDIT3, MOVEX,
50
},
{IDC_EDIT4, ELASTICY,
100
},
{IDC_EDIT5, ELASTICX,
100
},
{IDC_EDIT5, ELASTICY,
50
},
{IDC_EDIT6, ELASTICX,
100
},
{IDC_EDIT6, ELASTICY,
50
},
{IDC_EDIT6, MOVEY,
50
},
};
//
设置控件信息
SetControlProperty(dcMenuGroup,
sizeof
(dcMenuGroup)
/
sizeof
(DLGCTLINFO));
下面就是使用上面这段代码的对话框改变大小前后的效果图:
对两张截图的比较我们可以很容易的理解上面那段代码。
我还提供了一个函数:
void
ShowSizeIcon(BOOL bShow
=
TRUE);
来设置是否显示对话框右下角表示可以改变大小的图标。这个图标是从系统中读取的,我上面的截图是Windows2000下的,在WindowsXP中就会自动变成XP风格的。
好了,闲话不多说了,下面贴出该对话框类ClxDialog的源代码,里面有详细的注释:
lxDialog.h文件:
//
//
自动改变控件位置和大小的对话框类
//
文件名:lxDialog.h
//
作者:StarLee([email protected])
//
class
ClxDialog :
public
CDialog
{
public
:
ClxDialog(UINT nID, CWnd
*
pParent
=
NULL);
typedef
struct
_dlgControlTag
{
int
iId;
int
iFlag;
int
iPercent;
} DLGCTLINFO,
*
PDLGCTLINFO;
enum
{
MOVEX
=
0
,
MOVEY,
MOVEXY,
ELASTICX,
ELASTICY,
ELASTICXY
};
//
设置控件信息
BOOL SetControlProperty(PDLGCTLINFO lp,
int
nElements);
//
是否在对话框右下角显示表示可改变大小的图标
void
ShowSizeIcon(BOOL bShow
=
TRUE);
protected
:
virtual
BOOL OnInitDialog();
afx_msg
void
OnSize(UINT nType,
int
cx,
int
cy);
afx_msg
void
OnSizing(UINT nSide, LPRECT lpRect);
DECLARE_MESSAGE_MAP()
private
:
int
m_iClientWidth;
//
对话框client区域的宽度
int
m_iClientHeight;
//
对话框client区域的高度
int
m_iMinWidth;
//
对话框的最小宽度
int
m_iMinHeight;
//
对话框的最小高度
PDLGCTLINFO m_pControlArray;
//
控件信息数组指针
int
m_iControlNumber;
//
设置控件信息的控件个数
BOOL m_bShowSizeIcon;
//
是否显示表示可改变大小的图标
CStatic m_wndSizeIcon;
//
放图标的静态控件
//
保存图标的bitmap
CBitmap m_bmpSizeIcon;
BITMAP m_bitmap;
};
lxDialog.cpp文件:
//
//
自动改变控件位置和大小的对话框类
//
文件名:lxDialog.cpp
//
作者:StarLee([email protected])
//
#include
"
stdafx.h
"
#include
"
lxDialog.h
"
//
表示可改变大小的图标ID
#ifndef OBM_SIZE
#define
OBM_SIZE 32766
#endif
ClxDialog::ClxDialog(UINT nID, CWnd
*
pParent
/*
=NULL
*/
)
: CDialog(nID, pParent)
, m_iClientWidth(
0
)
, m_iClientHeight(
0
)
, m_iMinWidth(
0
)
, m_iMinHeight(
0
)
, m_pControlArray(NULL)
, m_iControlNumber(
0
)
, m_bShowSizeIcon(TRUE)
{}
BEGIN_MESSAGE_MAP(ClxDialog, CDialog)
ON_WM_SIZE()
ON_WM_SIZING()
END_MESSAGE_MAP()
BOOL ClxDialog::OnInitDialog()
{
CDialog::OnInitDialog();
//
设置对话框为可变大小的
ModifyStyle(
0
, WS_SIZEBOX);
//
以对话框的初始大小作为对话框的宽度和高度的最小值
CRect rectDlg;
GetWindowRect(rectDlg);
m_iMinWidth
=
rectDlg.Width();
m_iMinHeight
=
rectDlg.Height();
//
得到对话框client区域的大小
CRect rectClient;
GetClientRect(rectClient);
m_iClientWidth
=
rectClient.Width();
m_iClientHeight
=
rectClient.Height();
//
Load图标
m_bmpSizeIcon.LoadOEMBitmap(OBM_SIZE);
m_bmpSizeIcon.GetBitmap(
&
m_bitmap);
//
创建显示图标的静态控件并放在对话框右下角
m_wndSizeIcon.Create(NULL, WS_CHILD
|
WS_VISIBLE
|
SS_BITMAP, CRect(
0
,
0
, m_bitmap.bmWidth, m_bitmap.bmHeight),
this
,
0
);
m_wndSizeIcon.SetBitmap(m_bmpSizeIcon);
m_wndSizeIcon.MoveWindow(m_iClientWidth
-
m_bitmap.bmWidth, m_iClientHeight
-
m_bitmap.bmHeight, m_bitmap.bmWidth, m_bitmap.bmHeight);
//
显示图标
m_wndSizeIcon.ShowWindow(m_bShowSizeIcon);
return
TRUE;
}
void
ClxDialog::OnSize(UINT nType,
int
cx,
int
cy)
{
CDialog::OnSize(nType, cx, cy);
//
对话框宽度和高度的增量
int
iIncrementX
=
cx
-
m_iClientWidth;
int
iIncrementY
=
cy
-
m_iClientHeight;
//
最小化时增量为0
if
(nType
==
SIZE_MINIMIZED)
{
iIncrementX
=
iIncrementY
=
0
;
}
for
(
int
i
=
0
; i
<
m_iControlNumber; i
++
)
{
CWnd
*
pWndCtrl
=
NULL;
int
iId
=
m_pControlArray[i].iId;
int
iFlag
=
m_pControlArray[i].iFlag;
int
iPercent
=
m_pControlArray[i].iPercent;
//
无效值
if
((iPercent
<
0
)
||
(iPercent
>
100
))
continue
;
//
得到控件指针
pWndCtrl
=
GetDlgItem(iId);
if
((NULL
!=
pWndCtrl)
&&
IsWindow(pWndCtrl
->
GetSafeHwnd()))
{
CRect rectCtrl;
pWndCtrl
->
GetWindowRect(rectCtrl);
ScreenToClient(rectCtrl);
int
iLeft
=
rectCtrl.left;
int
iTop
=
rectCtrl.top;
int
iWidth
=
rectCtrl.Width();
int
iHeight
=
rectCtrl.Height();
switch
(iFlag)
{
case
MOVEX:
//
X方向移动
iLeft
+=
(iIncrementX
*
iPercent
/
100
);
break
;
case
MOVEY:
//
Y方向移动
iTop
+=
(iIncrementY
*
iPercent
/
100
);
break
;
case
MOVEXY:
//
X方向和Y方向同时移动
iLeft
+=
(iIncrementX
*
iPercent
/
100
);
iTop
+=
(iIncrementY
*
iPercent
/
100
);
break
;
case
ELASTICX:
//
X方向改变大小
iWidth
+=
(iIncrementX
*
iPercent
/
100
);
break
;
case
ELASTICY:
//
Y方向改变大小
iHeight
+=
(iIncrementY
*
iPercent
/
100
);
break
;
case
ELASTICXY:
//
X方向和Y方向同时改变大小
iWidth
+=
(iIncrementX
*
iPercent
/
100
);
iHeight
+=
(iIncrementY
*
iPercent
/
100
);
break
;
default
:
;
}
//
把控件移动到新位置
pWndCtrl
->
MoveWindow(iLeft, iTop, iWidth, iHeight);
}
}
//
把图标移动到对话框右下角
if
(IsWindow(m_wndSizeIcon.GetSafeHwnd()))
{
m_wndSizeIcon.MoveWindow(cx
-
m_bitmap.bmWidth, cy
-
m_bitmap.bmHeight, m_bitmap.bmWidth, m_bitmap.bmHeight);
if
(nType
==
SIZE_MAXIMIZED)
m_wndSizeIcon.ShowWindow(FALSE);
else
m_wndSizeIcon.ShowWindow(TRUE);
}
Invalidate();
//
记录对话框client区域的大小
if
(nType
!=
SIZE_MINIMIZED)
{
m_iClientWidth
=
cx;
m_iClientHeight
=
cy;
}
}
void
ClxDialog::OnSizing(UINT nSide, LPRECT lpRect)
{
CDialog::OnSizing(nSide, lpRect);
//
对话框不能小于初始大小
int
iWidth
=
lpRect
->
right
-
lpRect
->
left;
int
iHeight
=
lpRect
->
bottom
-
lpRect
->
top;
if
(iWidth
<=
m_iMinWidth)
lpRect
->
right
=
lpRect
->
left
+
m_iMinWidth;
if
(iHeight
<=
m_iMinHeight)
lpRect
->
bottom
=
lpRect
->
top
+
m_iMinHeight;
}
BOOL ClxDialog::SetControlProperty(PDLGCTLINFO lp,
int
nElements)
{
//
设置控件数组信息
if
(NULL
==
lp)
return
FALSE;
if
(nElements
<=
0
)
return
FALSE;
m_pControlArray
=
lp;
m_iControlNumber
=
nElements;
return
TRUE;
}
void
ClxDialog::ShowSizeIcon(BOOL bShow
/*
=TRUE
*/
)
{
m_bShowSizeIcon
=
bShow;
}
示例代码下载:http://download.csdn.net/download/starlee/4009546