1.前言
我们在做窗口程序时,难免有时候会软件添加一些背景颜色或者图片,来对其进行美化,如果只有一个窗口,可能这还比较好办.如果窗口很多,而且我们又想让它们的界面风格保持一致,那么我们应该怎么去做呢?或许有朋友会讲,对每个对话框窗口进行美化不就行了吗?如果要求它们的界面保持一致的话,使用相同的代码对各自的对话框进行美化,这不就能达到风格统一的效果吗?
是的,的确,这样确实也能达到我们的要求,但不知道各位有没有想过,当我们的对话框足够多,就意味着我们需要将同一份代码复制足够多份到足够多的对话框程序中,如果那天我们对风格不满意了,需要对它们进行修改,而且风格依然要求统一起来,如果遇到这样的情况,我们再使用前面 的方法去做,或许这会儿我们就会感到该方法的的弊端,因为我们需要去修改每一个对话框程序中的代码.那么究竟用什么方法才能避免这种事情呢?
答案是:充分利用面向对象的思想,采用继承机制来帮我们完成这一工作.
2.设计思想:
平常情况下, 我们创建一个对话框,那么我们会从CDialog类中派生一个类来与之相关联,如果 我们需要更改对话框的风格,我们就需要在该派生类中来完成对该对话框风格的更改.
当需要定义多个对话框时,我们可以先从CDialog类中派生一个自己的类CMyDialog,然后再为对话框创建关联类时,我们只需要把对话框关联类的基类修改成CMyDialog,那么在CMyDialog中定义的所有方法都会被所有继承它的子类所享有,当我们需要对对话框的界面风格进行统一制定时,我们只需要在CMyDialog里对风格进行设置,其它的对话框所风格则会自己继承.当需要对风格进行更改时,我们只需要修改CMyDialog中定义风格的代码即可完成对所有对话框的界面风格的更改.
3.举例说明
1.首先我们创建一个基于对话框的MFC应用程序.工程名字为phpoo.
2.然后我们新建一个类,该类从CDialog中派生,类名为CMyDig.(注意:当我们点击确定时,这里会出现一个提示信息,提示说"没有为该类创建一个资源对话框,希望我们先创建资源对话框后再创建该类,否则将会为其关联一个不合法的资源ID,是否断续",我们选择是).
3.修改CPhpooDlg类的基类为CMyDig,同时修改CPhpooDlg构造函数的初始化列表为 CMyDlg(CPhpooDlg::IDD, pParent)(因为现在CPhpooDlg已经不再从CDialog派生,而是从CMyDlg类派生而来,所以这时我们需要向它的基类CMyDlg传递资源相关的参数.
代码如下:
class CPhpooDlg : public CMyDlg//将CPhpooDlg基类修改为CMyDlg
CPhpooDlg::CPhpooDlg(CWnd* pParent /*=NULL*/) : CMyDlg(CPhpooDlg::IDD, pParent)//修改CPhpooDlg构造函数的初始化列表
4.将CMyDlg类头文件MyDlg.h加入到CPhpooDlg类的头文件中.
5.将CMyDlg中enum { IDD = _UNKNOWN_RESOURCE_ID_ };去掉。并重载一个构造函数,将设置和先前默认构造函数相同的初始化列表,用来接受派生类传递过来的ID。同时将默认构造函数的初始化列表去掉。因为这里只使用我们所重载的构造函数。向基类的构造函数的初始化由现在的重载构造函数来完成。
代码如下:
/** * 重载构造函数,用来接收派生类所传递的资源ID等参数, */ CMyDlg::CMyDlg(UINT nIDTemplate, CWnd *pParentWnd) : CDialog(nIDTemplate, pParentWnd)//设置初始化列表对CDialog函数进行初始化 { }
//去掉初始化列表 CMyDlg::CMyDlg(CWnd* pParent /*=NULL*/)
6.接下来为CMyDlg定义背景,这里我们将设置一张图片作为该对话框的背景。
首先找一张图片,拷入到资源文件夹下,并将其导入到资源列表中。
接下来在CMyDlg类中添类型为CBrush的成员变量,用来保存我们的背景。
CBrush m_brush;//定义画刷句柄
在构造函数中创建位图画刷.
/**
* 重载构造函数,用来接收派生类所传递的资源ID等参数,
*/
CMyDlg::CMyDlg(UINT nIDTemplate, CWnd *pParentWnd)
: CDialog(nIDTemplate, pParentWnd)//设置初始化列表对CDialog函数进行初始化
{
CBitmap bmp;
bmp.LoadBitmap(IDB_BITMAP1);//load pic
m_brush.CreatePatternBrush(&bmp);//使用指定的位图来创建一把画刷
bmp.DeleteObject();
}
添加ON_WM_CTLCOLOR事件响应函数,将返回值改为m_brush.
HBRUSH CMyDlg::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor) { HBRUSH hbr = CDialog::OnCtlColor(pDC, pWnd, nCtlColor); // TODO: Change any attributes of the DC here // TODO: Return a different brush if the default is not desired return m_brush;//返回我们定义的画刷 }
由于在子类中CMyDlg的OnCtlColor不会自动被调用,所以我们需要在子类中显示的调用该函数。
创建CPhpooDlg的ON_WM_CTLCOLOR事件响应函数。并将返回CMyDlg所拥有的画刷。代码如下:
HBRUSH CPhpooDlg::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor) { HBRUSH hbr = CMyDlg::OnCtlColor(pDC, pWnd, nCtlColor);//返回CMyDlg而不是CDialog的画刷 // TODO: Change any attributes of the DC here // TODO: Return a different brush if the default is not desired return hbr; }
我们这里编译运行,就会发现,这里的对话框背景已经变成了我们所指定的背景了。
上面我们只创建了一个对话框,如果我们需要创建更多的对话框,我们只需要简简单单的修改几处,就能很方便的将这些对话框的风格进行统一进来。这几处是:对话框的基类,修改对话框构造函数的初始化列表,为ON_WM_CTLCOLOR添加响应函数,并返回CMyDlg的画刷。