窗口的继承,子类窗口可以拥有父类窗口的一些属性、风格和方法等,将极大的简化代码量,本例将完成一个mfc窗口继承的实例:
1.新建一个基于对话框的dialog,作为父类窗口,本例名称TemplateDlg
TemplateDlg.h:
// TemplateDlg.h : 头文件
//
#pragma once
// CTemplateDlg 对话框
class CTemplateDlg : public CDialog
{
// 构造
public:
//CTemplateDlg(CWnd* pParent = NULL); // 标准构造函数
CTemplateDlg(UINT nIDTemplate,CWnd* pParent = NULL);
//enum { IDD = IDD_TEMPLATE_DIALOG };
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV 支持
// 生成的消息映射函数
DECLARE_MESSAGE_MAP()
public:
//afx_msg void OnPaint(); //原版OnPaint
virtual afx_msg void OnPaint(); //virtual虚方法,留待method dialog重写
void HelloWorld();
};
TemplateDlg.cpp:
// TemplateDlg.cpp : 实现文件
//
#include "stdafx.h"
#include "Template.h"
#include "TemplateDlg.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
// CTemplateDlg 对话框
/*
标准构造函数
IDD_TEMPLATE_DIALOG:template dialog的控件资源id
*/
//CTemplateDlg::CTemplateDlg(CWnd* pParent /*=NULL*/)
// : CDialog(IDD_TEMPLATE_DIALOG,pParent)
//{
//
//}
/*
方便继承的构造函数
nIDTemplate:子窗口的控件资源id
*/
CTemplateDlg::CTemplateDlg(UINT nIDTemplate,CWnd* pParent /*=NULL*/)
: CDialog(nIDTemplate,pParent)
{
}
void CTemplateDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
}
BEGIN_MESSAGE_MAP(CTemplateDlg, CDialog)
//}}AFX_MSG_MAP
ON_WM_PAINT()
END_MESSAGE_MAP()
// CTemplateDlg 消息处理程序
void CTemplateDlg::OnPaint()
{
CRect rect;
CPaintDC dc(this);
GetClientRect(rect);
dc.FillSolidRect(rect,RGB(0,255,0)); //设置为绿色背景
CDialog::OnPaint();
}
void CTemplateDlg::HelloWorld()
{
AfxMessageBox(L"Hello world!");
}
2.新建一个基于TemplateDlg的对话框,名称MethodDlg:
MethodDlg.h:
#pragma once
#include "TemplateDlg.h" //引用模板窗口
// CMethodDlg 对话框
//class CMethodDlg : public CDialog
class CMethodDlg : public CTemplateDlg //继承template
{
DECLARE_DYNAMIC(CMethodDlg)
public:
CMethodDlg(CWnd* pParent = NULL); // 标准构造函数
// 对话框数据
enum { IDD = IDD_METHODDLG };
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV 支持
DECLARE_MESSAGE_MAP()
public:
//没有在method dialog的消息映射中出现,但是可以重写template dialog的消息处理
afx_msg void OnPaint();
//添加一个属于method dialog自己的消息处理
afx_msg void OnBnClickedButton1();
};
MethodDlg.cpp:
// MethodDlg.cpp : 实现文件
//
#include "stdafx.h"
#include "Template.h"
#include "MethodDlg.h"
// CMethodDlg 对话框
IMPLEMENT_DYNAMIC(CMethodDlg, CDialog)
//: CDialog(CMethodDlg::IDD, pParent)
CMethodDlg::CMethodDlg(CWnd* pParent /*=NULL*/)
: CTemplateDlg(CMethodDlg::IDD,pParent) //继承template
{
}
void CMethodDlg::DoDataExchange(CDataExchange* pDX)
{
//CDialog::DoDataExchange(pDX); //原继承CDialog
CTemplateDlg::DoDataExchange(pDX); //继承template
}
//BEGIN_MESSAGE_MAP(CMethodDlg, CDialog) //原只处理method自己的消息映射
BEGIN_MESSAGE_MAP(CMethodDlg, CTemplateDlg) //继承template dialog的所有消息映射
ON_BN_CLICKED(IDC_BUTTON1, &CMethodDlg::OnBnClickedButton1) //method dialog自己的消息映射处理
END_MESSAGE_MAP()
// CMethodDlg 消息处理程序
void CMethodDlg::OnPaint()
{
CRect rect;
CPaintDC dc(this);
GetClientRect(rect);
dc.FillSolidRect(rect,RGB(0,0,255)); //设置为蓝色背景
CDialog::OnPaint();
}
void CMethodDlg::OnBnClickedButton1()
{
//调用父窗口中的方法
CTemplateDlg::HelloWorld();//this->HelloWorld();
}
3.修改一下Template.cpp(本例项目名Template)
修改为启动我们的子类窗口MethodDlg:
BOOL CTemplateApp::InitInstance()
{
// 如果一个运行在 Windows XP 上的应用程序清单指定要
// 使用 ComCtl32.dll 版本 6 或更高版本来启用可视化方式,
//则需要 InitCommonControlsEx()。否则,将无法创建窗口。
INITCOMMONCONTROLSEX InitCtrls;
InitCtrls.dwSize = sizeof(InitCtrls);
// 将它设置为包括所有要在应用程序中使用的
// 公共控件类。
InitCtrls.dwICC = ICC_WIN95_CLASSES;
InitCommonControlsEx(&InitCtrls);
CWinApp::InitInstance();
AfxEnableControlContainer();
// 标准初始化
// 如果未使用这些功能并希望减小
// 最终可执行文件的大小,则应移除下列
// 不需要的特定初始化例程
// 更改用于存储设置的注册表项
// TODO: 应适当修改该字符串,
// 例如修改为公司或组织名
SetRegistryKey(_T("应用程序向导生成的本地应用程序"));
//CTemplateDlg dlg;
CMethodDlg dlg; //启动method dialog
m_pMainWnd = &dlg;
INT_PTR nResponse = dlg.DoModal();
if (nResponse == IDOK)
{
// TODO: 在此放置处理何时用
// “确定”来关闭对话框的代码
}
else if (nResponse == IDCANCEL)
{
// TODO: 在此放置处理何时用
// “取消”来关闭对话框的代码
}
// 由于对话框已关闭,所以将返回 FALSE 以便退出应用程序,
// 而不是启动应用程序的消息泵。
return FALSE;
}
4.编译运行,效果如下:
本例启动的是子类窗口MethodDlg,但是他具有父类窗口TemplateDlg的风格(蓝色底色,无控件),因为加载自己的控件资源,所有显示了属于自己的控件(Button1),点击Button1,调用了属于父类窗口的方法。