刚看完MFC的文档/视图编程,特总结SDI框架代码解析如下:
SDI程序包含四个主要类:CMainFrame、CSDITestApp、CSDITestDoc和CSDITestView,其中,CMainFrame是程序框架类,主要包括框架的创建、工具栏和状态栏的创建等;CSDITestApp是应用程序类,主要包括一些应用程序的初始化工作等;CSDITestDoc是文档类,主要包括各种对文档数据的操作函数;CSDITestView是视图类,主要包括对各种视图控件的操作。详细代码解析如下:
// MainFrm.h : CMainFrame 类的接口
//
#pragma once
class CMainFrame : public CFrameWnd
{
protected: // 仅从序列化创建
CMainFrame();
DECLARE_DYNCREATE(CMainFrame)
// 属性
public:
// 操作
public:
// 重写
public:
virtual BOOL PreCreateWindow(CREATESTRUCT& cs);
// 实现
public:
virtual ~CMainFrame();
#ifdef _DEBUG
virtual void AssertValid() const;
virtual void Dump(CDumpContext& dc) const;
#endif
protected: // 控件条嵌入成员
CStatusBar m_wndStatusBar;
CToolBar m_wndToolBar;
// 生成的消息映射函数
protected:
afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
DECLARE_MESSAGE_MAP()
};
// MainFrm.cpp : CMainFrame 类的实现
//
#include "stdafx.h"
#include "SDITest.h"
#include "MainFrm.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
// CMainFrame
IMPLEMENT_DYNCREATE(CMainFrame, CFrameWnd)
BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd)
ON_WM_CREATE()
END_MESSAGE_MAP()
static UINT indicators[] =
{
ID_SEPARATOR, // 状态行指示器
ID_INDICATOR_CAPS,
ID_INDICATOR_NUM,
ID_INDICATOR_SCRL,
};
// CMainFrame 构造/析构
CMainFrame::CMainFrame()
{
// TODO: 在此添加成员初始化代码
}
CMainFrame::~CMainFrame()
{
}
int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CFrameWnd::OnCreate(lpCreateStruct) == -1)
return -1;
// 创建工具栏
if (!m_wndToolBar.CreateEx(this, TBSTYLE_FLAT, WS_CHILD | WS_VISIBLE | CBRS_TOP
| CBRS_GRIPPER | CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC) ||
!m_wndToolBar.LoadToolBar(IDR_MAINFRAME))
{
TRACE0("未能创建工具栏/n");
return -1; // 未能创建
}
// 创建状态栏
if (!m_wndStatusBar.Create(this) ||
!m_wndStatusBar.SetIndicators(indicators,
sizeof(indicators)/sizeof(UINT)))
{
TRACE0("未能创建状态栏/n");
return -1; // 未能创建
}
// TODO: 如果不需要工具栏可停靠,则删除这三行
m_wndToolBar.EnableDocking(CBRS_ALIGN_ANY);
EnableDocking(CBRS_ALIGN_ANY);
DockControlBar(&m_wndToolBar);
return 0;
}
BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs)
{
if( !CFrameWnd::PreCreateWindow(cs) )
return FALSE;
// TODO: 在此处通过修改
// CREATESTRUCT cs 来修改窗口类或样式
return TRUE;
}
// CMainFrame 诊断
#ifdef _DEBUG
void CMainFrame::AssertValid() const
{
CFrameWnd::AssertValid(); // 提供对对象内部状态的运行时检查
}
void CMainFrame::Dump(CDumpContext& dc) const
{
CFrameWnd::Dump(dc); // 将对象的成员变量的文本化表示形式写入转储上下文(CDumpContext)
}
#endif //_DEBUG
// CMainFrame 消息处理程序
// ...
// SDITest.h : SDITest 应用程序的主头文件
//
#pragma once
#ifndef __AFXWIN_H__
#error "在包含此文件之前包含“stdafx.h”以生成PCH 文件"
#endif
#include "resource.h" // 主符号
// CSDITestApp:
// 有关此类的实现,请参阅SDITest.cpp
//
class CSDITestApp : public CWinApp
{
public:
CSDITestApp();
// 重写
public:
virtual BOOL InitInstance();
// 实现
afx_msg void OnAppAbout();
DECLARE_MESSAGE_MAP()
};
extern CSDITestApp theApp;
// SDITest.cpp : 定义应用程序的类行为。
//
#include "stdafx.h"
#include "SDITest.h"
#include "MainFrm.h"
#include "SDITestDoc.h"
#include "SDITestView.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
// CSDITestApp
BEGIN_MESSAGE_MAP(CSDITestApp, CWinApp)
ON_COMMAND(ID_APP_ABOUT, &CSDITestApp::OnAppAbout)
// 基于文件的标准文档命令
ON_COMMAND(ID_FILE_NEW, &CWinApp::OnFileNew)
ON_COMMAND(ID_FILE_OPEN, &CWinApp::OnFileOpen)
// 标准打印设置命令
ON_COMMAND(ID_FILE_PRINT_SETUP, &CWinApp::OnFilePrintSetup)
END_MESSAGE_MAP()
// CSDITestApp 构造
CSDITestApp::CSDITestApp()
{
// TODO: 在此处添加构造代码,
// 将所有重要的初始化放置在InitInstance 中
}
// 唯一的一个CSDITestApp 对象
CSDITestApp theApp;
// CSDITestApp 初始化
BOOL CSDITestApp::InitInstance()
{
// 如果一个运行在Windows XP 上的应用程序清单指定要
// 使用ComCtl32.dll 版本6 或更高版本来启用可视化方式,
//则需要InitCommonControlsEx()。否则,将无法创建窗口。
INITCOMMONCONTROLSEX InitCtrls;
InitCtrls.dwSize = sizeof(InitCtrls);
// 将它设置为包括所有要在应用程序中使用的
// 公共控件类。
InitCtrls.dwICC = ICC_WIN95_CLASSES;
InitCommonControlsEx(&InitCtrls);
CWinApp::InitInstance();
// 初始化OLE 库
if (!AfxOleInit())
{
AfxMessageBox(IDP_OLE_INIT_FAILED);
return FALSE;
}
AfxEnableControlContainer();
// 标准初始化
// 如果未使用这些功能并希望减小
// 最终可执行文件的大小,则应移除下列
// 不需要的特定初始化例程
// 更改用于存储设置的注册表项
// TODO: 应适当修改该字符串,
// 例如修改为公司或组织名
SetRegistryKey(_T("应用程序向导生成的本地应用程序"));
LoadStdProfileSettings(4); // 加载标准INI 文件选项(包括MRU)
// 注册应用程序的文档模板。文档模板
// 将用作文档、框架窗口和视图之间的连接
CSingleDocTemplate* pDocTemplate;
pDocTemplate = new CSingleDocTemplate(
IDR_MAINFRAME,
RUNTIME_CLASS(CSDITestDoc),
RUNTIME_CLASS(CMainFrame), // 主SDI 框架窗口
RUNTIME_CLASS(CSDITestView));
if (!pDocTemplate)
return FALSE;
AddDocTemplate(pDocTemplate);
// 分析标准外壳命令、DDE、打开文件操作的命令行
CCommandLineInfo cmdInfo;
ParseCommandLine(cmdInfo);
// 调度在命令行中指定的命令。如果
// 用/RegServer、/Register、/Unregserver 或/Unregister 启动应用程序,则返回FALSE。
if (!ProcessShellCommand(cmdInfo))
return FALSE;
// 唯一的一个窗口已初始化,因此显示它并对其进行更新
m_pMainWnd->ShowWindow(SW_SHOW);
m_pMainWnd->UpdateWindow();
// 仅当具有后缀时才调用DragAcceptFiles
// 在SDI 应用程序中,这应在ProcessShellCommand 之后发生
return TRUE;
}
// 用于应用程序“关于”菜单项的CAboutDlg 对话框
class CAboutDlg : public CDialog
{
public:
CAboutDlg();
// 对话框数据
enum { IDD = IDD_ABOUTBOX };
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV 支持
// 实现
protected:
DECLARE_MESSAGE_MAP()
};
CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
{
}
void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
}
BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
END_MESSAGE_MAP()
// 用于运行对话框的应用程序命令
void CSDITestApp::OnAppAbout()
{
CAboutDlg aboutDlg;
aboutDlg.DoModal();
}
// CSDITestApp 消息处理程序
// ...
// SDITestDoc.h : CSDITestDoc 类的接口
//
#pragma once
class CSDITestDoc : public CDocument
{
protected: // 仅从序列化创建
CSDITestDoc();
DECLARE_DYNCREATE(CSDITestDoc)
// 属性
public:
// 操作
public:
// 重写
public:
virtual BOOL OnNewDocument();
virtual void Serialize(CArchive& ar);
// 实现
public:
virtual ~CSDITestDoc();
#ifdef _DEBUG
virtual void AssertValid() const;
virtual void Dump(CDumpContext& dc) const;
#endif
protected:
// 生成的消息映射函数
protected:
DECLARE_MESSAGE_MAP()
};
// SDITestDoc.cpp : CSDITestDoc 类的实现
//
#include "stdafx.h"
#include "SDITest.h"
#include "SDITestDoc.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
// CSDITestDoc
IMPLEMENT_DYNCREATE(CSDITestDoc, CDocument)
BEGIN_MESSAGE_MAP(CSDITestDoc, CDocument)
END_MESSAGE_MAP()
// CSDITestDoc 构造/析构
CSDITestDoc::CSDITestDoc()
{
// TODO: 在此添加一次性构造代码
}
CSDITestDoc::~CSDITestDoc()
{
}
BOOL CSDITestDoc::OnNewDocument()
{
if (!CDocument::OnNewDocument())
return FALSE;
// TODO: 在此添加重新初始化代码
// (SDI 文档将重用该文档)
return TRUE;
}
// CSDITestDoc 序列化
void CSDITestDoc::Serialize(CArchive& ar)
{
if (ar.IsStoring())
{
// TODO: 在此添加存储代码
}
else
{
// TODO: 在此添加加载代码
}
}
// CSDITestDoc 诊断
#ifdef _DEBUG
void CSDITestDoc::AssertValid() const
{
CDocument::AssertValid();
}
void CSDITestDoc::Dump(CDumpContext& dc) const
{
CDocument::Dump(dc);
}
#endif //_DEBUG
// CSDITestDoc 命令
// ...
// SDITestView.h : CSDITestView 类的接口
//
#pragma once
class CSDITestView : public CView
{
protected: // 仅从序列化创建
CSDITestView();
DECLARE_DYNCREATE(CSDITestView)
// 属性
public:
CSDITestDoc* GetDocument() const;
// 操作
public:
// 重写
public:
virtual void OnDraw(CDC* pDC); // 重写以绘制该视图
virtual BOOL PreCreateWindow(CREATESTRUCT& cs);
protected:
virtual BOOL OnPreparePrinting(CPrintInfo* pInfo);
virtual void OnBeginPrinting(CDC* pDC, CPrintInfo* pInfo);
virtual void OnEndPrinting(CDC* pDC, CPrintInfo* pInfo);
// 实现
public:
virtual ~CSDITestView();
#ifdef _DEBUG
virtual void AssertValid() const;
virtual void Dump(CDumpContext& dc) const;
#endif
protected:
// 生成的消息映射函数
protected:
DECLARE_MESSAGE_MAP()
};
#ifndef _DEBUG // SDITestView.cpp 中的调试版本
inline CSDITestDoc* CSDITestView::GetDocument() const
{ return reinterpret_cast<CSDITestDoc*>(m_pDocument); }
#endif
// SDITestView.cpp : CSDITestView 类的实现
//
#include "stdafx.h"
#include "SDITest.h"
#include "SDITestDoc.h"
#include "SDITestView.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
// CSDITestView
IMPLEMENT_DYNCREATE(CSDITestView, CView)
BEGIN_MESSAGE_MAP(CSDITestView, CView)
// 标准打印命令
ON_COMMAND(ID_FILE_PRINT, &CView::OnFilePrint)
ON_COMMAND(ID_FILE_PRINT_DIRECT, &CView::OnFilePrint)
ON_COMMAND(ID_FILE_PRINT_PREVIEW, &CView::OnFilePrintPreview)
END_MESSAGE_MAP()
// CSDITestView 构造/析构
CSDITestView::CSDITestView()
{
// TODO: 在此处添加构造代码
}
CSDITestView::~CSDITestView()
{
}
BOOL CSDITestView::PreCreateWindow(CREATESTRUCT& cs)
{
// TODO: 在此处通过修改
// CREATESTRUCT cs 来修改窗口类或样式
return CView::PreCreateWindow(cs);
}
// CSDITestView 绘制
void CSDITestView::OnDraw(CDC* /*pDC*/)
{
CSDITestDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
if (!pDoc)
return;
// TODO: 在此处为本机数据添加绘制代码
}
// CSDITestView 打印
BOOL CSDITestView::OnPreparePrinting(CPrintInfo* pInfo)
{
// 默认准备
return DoPreparePrinting(pInfo);
}
void CSDITestView::OnBeginPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
{
// TODO: 添加额外的打印前进行的初始化过程
}
void CSDITestView::OnEndPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
{
// TODO: 添加打印后进行的清除过程
}
// CSDITestView 诊断
#ifdef _DEBUG
void CSDITestView::AssertValid() const
{
CView::AssertValid();
}
void CSDITestView::Dump(CDumpContext& dc) const
{
CView::Dump(dc);
}
CSDITestDoc* CSDITestView::GetDocument() const // 非调试版本是内联的
{
ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CSDITestDoc)));
return (CSDITestDoc*)m_pDocument;
}
#endif //_DEBUG
// CSDITestView 消息处理程序
// ...
以上是单文档程序向导创建的代码,其中注释已经清楚的告诉我们各个函数的作用,我们只需在向导的基础上添加我们自己的代码即可。