MFC 单文档视图架构
目录
单文档视图架构
只能管理一个文档,但可以有多个视图窗口。
参与架构的类:CFrameWnd ,? CWinApp , CView , CDocument
需要用到的类:CDocTemplate(文档模板类)的一个子类CSingleDocTemplate(单文档模板类),以及CDocManger(文档管理类)
代码书写:参与架构的四个类除了应用程序类,其余三个类均支持动态创建机制。
模仿单文档视图结构
创建一个Win32桌面程序
代码如下:
#include <afxwin.h>
#include "resource1.h"
class CMyDoc : public CDocument {
DECLARE_DYNCREATE(CMyDoc)
};
IMPLEMENT_DYNCREATE(CMyDoc, CDocument)
class CMyView : public CView {
DECLARE_DYNCREATE(CMyView)
public:
virtual void OnDraw(CDC* pDC);
};
IMPLEMENT_DYNCREATE(CMyView, CView)
void CMyView::OnDraw(CDC* pDC) {
pDC->TextOut(100, 100, "我是视图窗口");
}
class CMyFrameWnd : public CFrameWnd {
DECLARE_DYNCREATE(CMyFrameWnd)
};
IMPLEMENT_DYNCREATE(CMyFrameWnd, CFrameWnd)
class CMyWinApp : public CWinApp {
public:
virtual BOOL InitInstance();
};
BOOL CMyWinApp::InitInstance() {
CSingleDocTemplate* pTemplate = new CSingleDocTemplate(IDR_MENU1,
RUNTIME_CLASS(CMyDoc),
RUNTIME_CLASS(CMyFrameWnd),
RUNTIME_CLASS(CMyView));
AddDocTemplate(pTemplate);
OnFileNew();
m_pMainWnd->ShowWindow(SW_SHOW);
m_pMainWnd->UpdateWindow();
return TRUE;
}
CMyWinApp theApp;
- 文档类,视图类,框架窗口类需要实现动态创建机制,交给程序实现
- 视图类需要重写虚函数OnDraw()
- 应用程序类需要重写虚函数InitInstance()
遇见报错
点击重试,跳转至代码报错位置
这里需要一个字符串,作为窗口的标题,添加一个字符串资源即可,值必须是61443
InitInstance()函数执行分析
InitInstance()函数中,首先创建了一个CSingleDocTemplate对象,接下来进入构造函数中看看
首先创建了一个CSingleDocTemplate对象,接下来进入构造函数中看看,this指针是CSingleDocTemplate对象
先进入父类的构造函数,函数内部this指针是CSingleDocTemplate对象
给CSingleDocTemplate对象的诸多成员变量赋值
构造函数执行完毕
进入函数??AddDocTemplate(pTemplate);? ?this指针是thsApp
进入函数AddDocTemplate函数,this指针是theApp的成员变量m_pDocManager,参数是CSingleDocTemplate对象
进入函数LoadTemplate(),this指针是CSingleDocTemplate对象
theApp还有一个成员变量m_templateList是一个链表结构,m_templateList.AddTail(pTemplate);? 这句代码应该是把CSingleDocTemplate对象放到链表结构的尾部。
到此,大概就构成下面的数据关系
进入函数OnFileNew();? 函数内部this指针是theApp
?theApp的成员变量m_pDocMannager调用函数OnFileNew(),函数内部this为文档管理类对象地址
拿到刚刚放到链表尾部的CSingleDocTemplate对象地址
函数OpenDocumentFile内部this为单文档模板类对象地址
进入函数看看
调用函数CreateNewDocument(),函数内部this为单文档模板类对象地址
动态创建文档类对象,并返回对象地址;并调用AddDocument(pDocument);
?函数内部this为单文档模板类对象地址,并且把pDocument赋值给单文档模板类对象的成员变量m_pOnly
调用函数CreateNewFrame(pDocument, NULL);??函数内部this为单文档模板类对象地址
动态创建框架类对象,并返回对象地址
之后就是pFrame->LoadFrame,创建框架窗口
函数OnFileNew的逻辑如下:
框架生成单文档视图项目
单文档视图项目的类信息
?
框架窗口类
MainFrm.h
// MainFrm.h : interface of the CMainFrame class
//
#pragma once
class CMainFrame : public CFrameWnd // 框架窗口类
{
protected: // create from serialization only
CMainFrame(); // 构造函数
DECLARE_DYNCREATE(CMainFrame) // 消息映射
// Attributes
public:
// Operations
public:
// Overrides
public:
virtual BOOL PreCreateWindow(CREATESTRUCT& cs); // (1)注册窗口,(2)把为NULL的成员赋值
// Implementation
public:
virtual ~CMainFrame(); // 析构函数
#ifdef _DEBUG // 和调试程序相关不需要管
virtual void AssertValid() const;
virtual void Dump(CDumpContext& dc) const;
#endif
// Generated message map functions
protected:
DECLARE_MESSAGE_MAP()
};
MainFrm.cpp
// MainFrm.cpp : implementation of the CMainFrame class
//
#include "stdafx.h"
#include "MFCSdiWizard.h"
#include "MainFrm.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
// CMainFrame
IMPLEMENT_DYNCREATE(CMainFrame, CFrameWnd) // 动态创建
BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd) // 消息映射
END_MESSAGE_MAP()
// CMainFrame construction/destruction
CMainFrame::CMainFrame() // 构造函数
{
// TODO: add member initialization code here
}
CMainFrame::~CMainFrame() // 析构函数
{
}
BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs) //(1)注册窗口 (2)更改为NULL,并给窗口标题
{
if( !CFrameWnd::PreCreateWindow(cs) ) // 调用父类的
return FALSE;
// TODO: Modify the Window class or styles here by modifying
// the CREATESTRUCT cs
return TRUE;
}
// CMainFrame diagnostics
#ifdef _DEBUG // 调试程序相关
void CMainFrame::AssertValid() const
{
CFrameWnd::AssertValid();
}
void CMainFrame::Dump(CDumpContext& dc) const
{
CFrameWnd::Dump(dc);
}
#endif //_DEBUG
// CMainFrame message handlers
应用程序类
MFCSdiWizard.h
// MFCSdiWizard.h : main header file for the MFCSdiWizard application
//
#pragma once
#ifndef __AFXWIN_H__
#error "include 'stdafx.h' before including this file for PCH"
#endif
#include "resource.h" // main symbols
// CMFCSdiWizardApp:
// See MFCSdiWizard.cpp for the implementation of this class
//
class CMFCSdiWizardApp : public CWinApp // 应用程序类
{
public:
CMFCSdiWizardApp(); // 构造函数
// Overrides
public:
virtual BOOL InitInstance(); // 初始化函数
virtual int ExitInstance(); // 反初始化函数
// Implementation
afx_msg void OnAppAbout(); // 处理WM_COMMAND消息
DECLARE_MESSAGE_MAP() // 消息映射
};
extern CMFCSdiWizardApp theApp;
MFCSdiWizard.cpp
// MFCSdiWizard.cpp : Defines the class behaviors for the application.
//
#include "stdafx.h"
#include "afxwinappex.h"
#include "afxdialogex.h"
#include "MFCSdiWizard.h"
#include "MainFrm.h"
#include "MFCSdiWizardDoc.h"
#include "MFCSdiWizardView.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
// CMFCSdiWizardApp
BEGIN_MESSAGE_MAP(CMFCSdiWizardApp, CWinApp) // 消息映射
ON_COMMAND(ID_APP_ABOUT, &CMFCSdiWizardApp::OnAppAbout)
// Standard file based document commands
ON_COMMAND(ID_FILE_NEW, &CWinApp::OnFileNew)
ON_COMMAND(ID_FILE_OPEN, &CWinApp::OnFileOpen)
// Standard print setup command
ON_COMMAND(ID_FILE_PRINT_SETUP, &CWinApp::OnFilePrintSetup)
END_MESSAGE_MAP()
// CMFCSdiWizardApp construction
CMFCSdiWizardApp::CMFCSdiWizardApp() // 构造函数
{
// support Restart Manager
m_dwRestartManagerSupportFlags = AFX_RESTART_MANAGER_SUPPORT_ALL_ASPECTS;
#ifdef _MANAGED
// If the application is built using Common Language Runtime support (/clr):
// 1) This additional setting is needed for Restart Manager support to work properly.
// 2) In your project, you must add a reference to System.Windows.Forms in order to build.
System::Windows::Forms::Application::SetUnhandledExceptionMode(System::Windows::Forms::UnhandledExceptionMode::ThrowException);
#endif
// TODO: replace application ID string below with unique ID string; recommended
// format for string is CompanyName.ProductName.SubProduct.VersionInformation
SetAppID(_T("MFCSdiWizard.AppID.NoVersion"));
// TODO: add construction code here,
// Place all significant initialization in InitInstance
}
// The one and only CMFCSdiWizardApp object
CMFCSdiWizardApp theApp; // 爆破点,程序由次开始
// CMFCSdiWizardApp initialization
BOOL CMFCSdiWizardApp::InitInstance() // 初始化函数,前面是初始化一些组件,和架构关系不大
{
// InitCommonControlsEx() is required on Windows XP if an application
// manifest specifies use of ComCtl32.dll version 6 or later to enable
// visual styles. Otherwise, any window creation will fail.
INITCOMMONCONTROLSEX InitCtrls;
InitCtrls.dwSize = sizeof(InitCtrls);
// Set this to include all the common control classes you want to use
// in your application.
InitCtrls.dwICC = ICC_WIN95_CLASSES;
InitCommonControlsEx(&InitCtrls);
CWinApp::InitInstance();
// Initialize OLE libraries
if (!AfxOleInit())
{
AfxMessageBox(IDP_OLE_INIT_FAILED);
return FALSE;
}
AfxEnableControlContainer();
EnableTaskbarInteraction(FALSE);
// AfxInitRichEdit2() is required to use RichEdit control
// AfxInitRichEdit2();
// Standard initialization
// If you are not using these features and wish to reduce the size
// of your final executable, you should remove from the following
// the specific initialization routines you do not need
// Change the registry key under which our settings are stored
// TODO: You should modify this string to be something appropriate
// such as the name of your company or organization
SetRegistryKey(_T("Local AppWizard-Generated Applications"));
LoadStdProfileSettings(4); // Load standard INI file options (including MRU)
// Register the application's document templates. Document templates
// serve as the connection between documents, frame windows and views
CSingleDocTemplate* pDocTemplate; // 单文档类对象
pDocTemplate = new CSingleDocTemplate(
IDR_MAINFRAME,
RUNTIME_CLASS(CMFCSdiWizardDoc),
RUNTIME_CLASS(CMainFrame), // main SDI frame window
RUNTIME_CLASS(CMFCSdiWizardView));
if (!pDocTemplate)
return FALSE;
AddDocTemplate(pDocTemplate);
// Parse command line for standard shell commands, DDE, file open
CCommandLineInfo cmdInfo;
ParseCommandLine(cmdInfo);
// Dispatch commands specified on the command line. Will return FALSE if
// app was launched with /RegServer, /Register, /Unregserver or /Unregister.
if (!ProcessShellCommand(cmdInfo)) //这个函数里面就会调用OnFileNew函数
return FALSE;
// The one and only window has been initialized, so show and update it
m_pMainWnd->ShowWindow(SW_SHOW);
m_pMainWnd->UpdateWindow();
// call DragAcceptFiles only if there's a suffix
// In an SDI app, this should occur after ProcessShellCommand
return TRUE;
}
int CMFCSdiWizardApp::ExitInstance() // 反初始化函数
{
//TODO: handle additional resources you may have added
AfxOleTerm(FALSE); // 处理前面的初始化的组件
return CWinApp::ExitInstance();
}
// CMFCSdiWizardApp message handlers
// CAboutDlg dialog used for App About
class CAboutDlg : public CDialogEx // 管理点击Help的对话框类
{
public:
CAboutDlg();
// Dialog Data
enum { IDD = IDD_ABOUTBOX };
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
// Implementation
protected:
DECLARE_MESSAGE_MAP()
};
CAboutDlg::CAboutDlg() : CDialogEx(CAboutDlg::IDD)
{
}
void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
CDialogEx::DoDataExchange(pDX);
}
BEGIN_MESSAGE_MAP(CAboutDlg, CDialogEx)
END_MESSAGE_MAP()
// App command to run the dialog
void CMFCSdiWizardApp::OnAppAbout()
{
CAboutDlg aboutDlg;
aboutDlg.DoModal();
}
// CMFCSdiWizardApp message handlers
文档类
MFCSdiWizardDoc.h
// MFCSdiWizardDoc.h : interface of the CMFCSdiWizardDoc class
//
#pragma once
class CMFCSdiWizardDoc : public CDocument // 文档类
{
protected: // create from serialization only
CMFCSdiWizardDoc(); // 构造函数
DECLARE_DYNCREATE(CMFCSdiWizardDoc) // 动态创建
// Attributes
public:
// Operations
public:
// Overrides
public:// 和管理数据有关的两个函数
virtual BOOL OnNewDocument();
virtual void Serialize(CArchive& ar);
#ifdef SHARED_HANDLERS // 不需要管
virtual void InitializeSearchContent();
virtual void OnDrawThumbnail(CDC& dc, LPRECT lprcBounds);
#endif // SHARED_HANDLERS
// Implementation
public:
virtual ~CMFCSdiWizardDoc(); //析构函数
#ifdef _DEBUG // 调试程序相关
virtual void AssertValid() const;
virtual void Dump(CDumpContext& dc) const;
#endif
protected:
// Generated message map functions
protected:
DECLARE_MESSAGE_MAP() // 消息映射
#ifdef SHARED_HANDLERS
// Helper function that sets search content for a Search Handler
void SetSearchContent(const CString& value);
#endif // SHARED_HANDLERS
};
MFCSdiWizardDoc.cpp
// MFCSdiWizardDoc.cpp : implementation of the CMFCSdiWizardDoc class
//
#include "stdafx.h"
// SHARED_HANDLERS can be defined in an ATL project implementing preview, thumbnail
// and search filter handlers and allows sharing of document code with that project.
#ifndef SHARED_HANDLERS
#include "MFCSdiWizard.h"
#endif
#include "MFCSdiWizardDoc.h"
#include <propkey.h>
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
// CMFCSdiWizardDoc
IMPLEMENT_DYNCREATE(CMFCSdiWizardDoc, CDocument) // 动态创建
BEGIN_MESSAGE_MAP(CMFCSdiWizardDoc, CDocument) // 消息映射
END_MESSAGE_MAP()
// CMFCSdiWizardDoc construction/destruction
CMFCSdiWizardDoc::CMFCSdiWizardDoc() // 构造
{
// TODO: add one-time construction code here
}
CMFCSdiWizardDoc::~CMFCSdiWizardDoc() //析构
{
}
// 下面两个函数与管理数据有关
BOOL CMFCSdiWizardDoc::OnNewDocument()
{
if (!CDocument::OnNewDocument())
return FALSE;
// TODO: add reinitialization code here
// (SDI documents will reuse this document)
return TRUE;
}
// CMFCSdiWizardDoc serialization
void CMFCSdiWizardDoc::Serialize(CArchive& ar)
{
if (ar.IsStoring())
{
// TODO: add storing code here
}
else
{
// TODO: add loading code here
}
}
#ifdef SHARED_HANDLERS
// Support for thumbnails
void CMFCSdiWizardDoc::OnDrawThumbnail(CDC& dc, LPRECT lprcBounds)
{
// Modify this code to draw the document's data
dc.FillSolidRect(lprcBounds, RGB(255, 255, 255));
CString strText = _T("TODO: implement thumbnail drawing here");
LOGFONT lf;
CFont* pDefaultGUIFont = CFont::FromHandle((HFONT) GetStockObject(DEFAULT_GUI_FONT));
pDefaultGUIFont->GetLogFont(&lf);
lf.lfHeight = 36;
CFont fontDraw;
fontDraw.CreateFontIndirect(&lf);
CFont* pOldFont = dc.SelectObject(&fontDraw);
dc.DrawText(strText, lprcBounds, DT_CENTER | DT_WORDBREAK);
dc.SelectObject(pOldFont);
}
// Support for Search Handlers
void CMFCSdiWizardDoc::InitializeSearchContent()
{
CString strSearchContent;
// Set search contents from document's data.
// The content parts should be separated by ";"
// For example: strSearchContent = _T("point;rectangle;circle;ole object;");
SetSearchContent(strSearchContent);
}
void CMFCSdiWizardDoc::SetSearchContent(const CString& value)
{
if (value.IsEmpty())
{
RemoveChunk(PKEY_Search_Contents.fmtid, PKEY_Search_Contents.pid);
}
else
{
CMFCFilterChunkValueImpl *pChunk = NULL;
ATLTRY(pChunk = new CMFCFilterChunkValueImpl);
if (pChunk != NULL)
{
pChunk->SetTextValue(PKEY_Search_Contents, value, CHUNK_TEXT);
SetChunkValue(pChunk);
}
}
}
#endif // SHARED_HANDLERS
// CMFCSdiWizardDoc diagnostics
#ifdef _DEBUG // 调试程序相关
void CMFCSdiWizardDoc::AssertValid() const
{
CDocument::AssertValid();
}
void CMFCSdiWizardDoc::Dump(CDumpContext& dc) const
{
CDocument::Dump(dc);
}
#endif //_DEBUG
// CMFCSdiWizardDoc commands
视图类
MFCSdiWizardView.h
// MFCSdiWizardView.h : interface of the CMFCSdiWizardView class
//
#pragma once
class CMFCSdiWizardView : public CView // 视图类
{
protected: // create from serialization only
CMFCSdiWizardView(); // 构造
DECLARE_DYNCREATE(CMFCSdiWizardView) //动态创建
// Attributes
public:
CMFCSdiWizardDoc* GetDocument() const; // 可以拿到视图类对应的文档类对象
// Operations
public:
// Overrides
public:
virtual void OnDraw(CDC* pDC); // overridden to draw this view // 绘制
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);
// Implementation
public:
virtual ~CMFCSdiWizardView(); //析构
#ifdef _DEBUG // 调试程序相关
virtual void AssertValid() const;
virtual void Dump(CDumpContext& dc) const;
#endif
protected:
// Generated message map functions
protected:
DECLARE_MESSAGE_MAP() // 消息映射
public:
afx_msg void OnLButtonDown(UINT nFlags, CPoint point);
afx_msg void OnTest();
};
#ifndef _DEBUG // debug version in MFCSdiWizardView.cpp
inline CMFCSdiWizardDoc* CMFCSdiWizardView::GetDocument() const
{ return reinterpret_cast<CMFCSdiWizardDoc*>(m_pDocument); }
#endif
MFCSdiWizardView.cpp
// MFCSdiWizardView.cpp : implementation of the CMFCSdiWizardView class
//
#include "stdafx.h"
// SHARED_HANDLERS can be defined in an ATL project implementing preview, thumbnail
// and search filter handlers and allows sharing of document code with that project.
#ifndef SHARED_HANDLERS
#include "MFCSdiWizard.h"
#endif
#include "MFCSdiWizardDoc.h"
#include "MFCSdiWizardView.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
// CMFCSdiWizardView
IMPLEMENT_DYNCREATE(CMFCSdiWizardView, CView) // 动态创建
BEGIN_MESSAGE_MAP(CMFCSdiWizardView, CView) // 消息映射
// Standard printing commands
ON_COMMAND(ID_FILE_PRINT, &CView::OnFilePrint)
ON_COMMAND(ID_FILE_PRINT_DIRECT, &CView::OnFilePrint)
ON_COMMAND(ID_FILE_PRINT_PREVIEW, &CView::OnFilePrintPreview)
ON_WM_LBUTTONDOWN()
ON_COMMAND(ID_TEST_TT, &CMFCSdiWizardView::OnTest)
END_MESSAGE_MAP()
// CMFCSdiWizardView construction/destruction
CMFCSdiWizardView::CMFCSdiWizardView() //构造
{
// TODO: add construction code here
}
CMFCSdiWizardView::~CMFCSdiWizardView() //析构
{
}
BOOL CMFCSdiWizardView::PreCreateWindow(CREATESTRUCT& cs) // (1)注册窗口 (2)窗口标题赋值
{
// TODO: Modify the Window class or styles here by modifying
// the CREATESTRUCT cs
return CView::PreCreateWindow(cs); // 调用父类的
}
// CMFCSdiWizardView drawing
void CMFCSdiWizardView::OnDraw(CDC* /*pDC*/)
{
CMFCSdiWizardDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
if (!pDoc)
return;
// TODO: add draw code for native data here
}
// CMFCSdiWizardView printing
BOOL CMFCSdiWizardView::OnPreparePrinting(CPrintInfo* pInfo)
{
// default preparation
return DoPreparePrinting(pInfo);
}
void CMFCSdiWizardView::OnBeginPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
{
// TODO: add extra initialization before printing
}
void CMFCSdiWizardView::OnEndPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
{
// TODO: add cleanup after printing
}
// CMFCSdiWizardView diagnostics
#ifdef _DEBUG
void CMFCSdiWizardView::AssertValid() const
{
CView::AssertValid();
}
void CMFCSdiWizardView::Dump(CDumpContext& dc) const
{
CView::Dump(dc);
}
CMFCSdiWizardDoc* CMFCSdiWizardView::GetDocument() const // non-debug version is inline
{
ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CMFCSdiWizardDoc)));
return (CMFCSdiWizardDoc*)m_pDocument;
}
#endif //_DEBUG
// CMFCSdiWizardView message handlers
void CMFCSdiWizardView::OnLButtonDown(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default
CView::OnLButtonDown(nFlags, point);
}
void CMFCSdiWizardView::OnTest()
{
// TODO: Add your command handler code here
AfxMessageBox("点了菜单项");
}
类向导
项目->添加类
处理WM_COMMAND消息
处理系统消息
处理添加虚函数
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!