MFC 单文档视图架构

2024-01-09 14:38:03

目录

单文档视图架构

模仿单文档视图结构

InitInstance()函数执行分析

框架生成单文档视图项目

框架窗口类

应用程序类

文档类

视图类

类向导


单文档视图架构

只能管理一个文档,但可以有多个视图窗口。

参与架构的类: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消息

处理系统消息

处理添加虚函数

文章来源:https://blog.csdn.net/qq_61553520/article/details/135472047
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。