资源描述
文档类
1 文档类相关
对数据的管理
CDocument-父类是CCmdTarget类,提供文档数据的管理
2 文档类的使用
2.1 创建过程
2.1.1 调用CFrameWnd的LoadFrame函数,调用Create函数创建Frame窗口
2.1.2 在Frame的OnCreate函数中,先动态创建视图对象,在根据对象动态的创建View(视图)窗口
2.1.3 在View的OnCreate函数中,将View的地址保存到Document(文档)中,将Document的地址保存到View中
例://文档类
class CMyDocument:public CDocument
{
DECLARE_DYNCREATE(CMyDocument)//动态创建声明宏
public:
CMyDocument();
CString m_strData;//保存文档中数据的成员
};
IMPLEMENT_DYNCREATE(CMyDocument,CDocument)//动态创建实现宏
//视图类
class CDocView:public CEditView
{
DECLARE_DYNCREATE(CDocView)//动态创建声明宏
public:
virtual void OnInitialUpdate();//CView中的OnInitialUpdate()虚函数
};
IMPLEMENT_DYNCREATE(CDocView,CEditView)//动态创建实现宏
// OnInitialUpdate()虚函数的重写(为了在视图中显示文档中数据)【1】
void CDocView::OnInitialUpdate()
{
//获取文档的指针
CMyDocument *pDc=(CMyDocument*)GetDocument();
//根据文档指针显示文档中定义好的数据
SetWindowText(pDc->m_strData);
}
//应用程序类
class CMainApp:public CWinApp
{
public:
virtual BOOL InitInstance();
};
//主窗体类
class CMainFrame:public CFrameWnd
{
public:
};
CMainApp theApp;
BOOL CMainApp::InitInstance()
{
CMainFrame *pFrame=new CMainFrame();
CCreateContext context;//定义一个结构体保存构成窗口的视图,文档等信息【2】
context.m_pCurrentDoc=new CMyDocument();//动态绑定文档类保存进结构
context.m_pNewViewClass=RUNTIME_CLASS(CDocView);//动态绑定视图类保存进结构
//调用CFrameWnd::Create函数创建主窗体,在创建消息处理函数中动态的创建了视图
//在视图的创建消息处理函数中,将视图和文档的地址相互保存进对方
pFrame->LoadFrame(IDR_MENU1,WS_OVERLAPPEDWINDOW,NULL,&context);
//让框架通知文档视图更新(视图根据文档中数据更新)
pFrame->InitialUpdateFrame(NULL,TRUE);
m_pMainWnd=pFrame;
m_pMainWnd->ShowWindow(SW_SHOW);
m_pMainWnd->UpdateData();
return TRUE;
}
相关:【1】OnInitialUpdate
视图窗口完全建立后第一个被框架调用的函数。框架在第一次调用OnDraw前会调用
OnInitialUpdate,因此OnInitialUpdate是设置滚动视图的逻辑尺寸和映射模式的最合
的地方。 时间上,两者先后顺序不同,构造函数生成本类的对象,但没有产生窗口,OnCreate
后窗口产生, 然后才是视图的OnInitialUpDate,一般在这里对视图的显示做初始化。简
单点,就是ONCREATE只是产生VIEW的基本结构和变量而在OnInitialUpDate()中,主要初
始化视图中控件等。对各个变量进行初始化操作。
【2】CCreateContext
在主程序创建框架窗口、以及文档相关的视图时,会使用CCreateContext结构。建立窗
口时,此结构中的值用于连接构成文档的组件和文档数据的视图。仅当覆盖了创建过程时
才需要使用CCreateContext。
CCreateContext结构包含了指向文档、框架窗口和文档模板的指针,包括了一个
CRuntimeClass指针,CRuntimeClass标志了待创建的视图的类型。运行时类信息和当前
文档指针用于动态地创建视图。下表列出了CCreateContext的每个成员的用法:
m_pNewViewClass:待创建的视图的CRuntimeClass
m_pCurrentDoc:将在其上创建视图的文档
m_pNewDocTemplate:待创建的新MDI框架窗口的文档模板
m_pLastView:待创建视图所依据的原始视图,例如在创建分裂窗口的视图或文档的第二个框架窗口时
m_pCurrentFrame:待创建框架窗口所依据的框架窗口,例如在文档上创建第二个框架窗口时
2.2 创建的这些类是如何相关联的(都有一个变量保存相关联的那个的地址)
CWinApp
|->m_pMainWnd(CFrameWnd)
|->m_pViewActive(CView)
|->m_pDocument(CDocument)
|->m_viewList(Ciew的LIst)
一个文档数据可以用多个视图来创建,一个视图只能显示一个文档那个数据
2.3 命令消息的响应顺序
View->Document->Frame->App
自己定义的类也可以响应命令消息,只需要继承字CCmdTarget而且响应的优先级也可以自定,只
需要将系统那几个主要的类中的虚消息响应函数重写即可
★ 例:自己定义的类的命令消息响应优先级高于文档类
//自己定义的类
class CMyData:public CCmdTarget
{
DECLARE_MESSAGE_MAP()//消息响应声明宏
public:
afx_msg void OnTest();//消息处理函数
};
BEGIN_MESSAGE_MAP(CMyData,CCmdTarget)//消息响应实现宏
ON_COMMAND(ID_TEST,OnTest)
END_MESSAGE_MAP()
//自定义类中对消息处理的函数
void CMyData::OnTest()
{
AfxMessageBox("CMyData::OnTest");【3】
}
//文档类
class CMyDocument:public CDocument
{
DECLARE_MESSAGE_MAP()
public:
CMyDocument();
afx_msg void OnTest();
//文档类的消息响应函数声明
virtual BOOL OnCmdMsg( UINT nID,int nCode, void* pExtra,
AFX_CMDHANDLERINFO* pHandlerInfo );
public:
CMyData m_data;//自定义类的对象
CString m_strData;
};
//文档类的构造函数实现
CMyDocument::CMyDocument()
{
m_strData="Hello Doc";
}
BEGIN_MESSAGE_MAP(CMyDocument,CDocument)
ON_COMMAND(ID_TEST,OnTest)
END_MESSAGE_MAP()
//文档类的消息响应函数重写(定义自定义类消息响应优先级高于文档类)
BOOL CMyDocument::OnCmdMsg(UINT nID, int nCode,void* pExtra,
AFX_CMDHANDLERINFO* pHandlerInfo)
{
if (m_data.OnCmdMsg(nID,nCode,pExtra,pHandlerInfo))
{
return TRUE;
}
return CDocument::OnCmdMsg(nID,nCode,pExtra,pHandlerInfo);
}
//文档类对消息处理的函数
void CMyDocument::OnTest()
{
AfxMessageBox("CMyDocument::OnTest");【3】
}
//视图类
class CDocView:public CEditView
{
DECLARE_DYNCREATE(CDocView)
DECLARE_MESSAGE_MAP()
public:
virtual void OnInitialUpdate( );
afx_msg void OnTest();
};
IMPLEMENT_DYNCREATE(CDocView,CEditView)
BEGIN_MESSAGE_MAP(CDocView,CEditView)
//ON_COMMAND(ID_TEST,OnTest)
END_MESSAGE_MAP()
//视图类消息处理函数
void CDocView::OnTest()
{
MessageBox("CDocView");【3】
}
窗口类本身调用MessageBox就行
文档类等就得调用AfxMessageBox
…
…
★2.4 View显示来自Document的数据【1】
OnInitialUpdate()->在View被创建后,首次关联文档后,显示前调用
单文档视图程序
1 单文档视图程序
只能管理一个文档
2 相关类
2.1 CWinApp/CFrameWnd/Cview/CDocument
2.2 文档模板类CDocTemplate(抽象基类)父类是CCmdTarget
两个子类:CSingleDocTemplate-单文档模板
CMultiDocTemplate-多文档模板
3 单文档CSingleDocTemplate
CSingleDocTemplate类定义了一个文档模板用于实现单文档界面(SDI)。一个SDI应用程序使用主框架窗口来显示一个文档;一次只能打开一个文档。
★一个文档模板定义了类的三个类型之间的关系:
★1 一个从CDocument派生而来的文档类。
★2 一个视图类,用来显示来自上面提到的文档类的数据。你可以从CView,CScrollView,CFormView,或CEditView派生这个类。(你也可以直接使用CEditView。)
★3 一个框架窗口类,用来包容视图。对于一个SDI文档模板,你可以从CFrameWnd派生这个类;如果你不需要定制主框架窗口的行为,你可以直接使用CFrameWnd,而不派生你自己的类。
★一个SDI应用程序通常支持一种类型的文档,因此它只有一个CSingleDocTemplate模板。一次只打开一个文档。
除了CSingleDocTemplate的构造函数,你不需要调用它的任何其它成员函数。框架在内部处理CSingleDocTemplate对象。
构造函数:
CSingleDocTemplate( UINT nIDResource,//加载资源ID
CRuntimeClass* pDocClass, //文档类
CRuntimeClass* pFrameClass, //框架窗口类
CRuntimeClass* pViewClass ); //视图类
例://文档类
class CSdiDoc:public CDocument
{
DECLARE_DYNCREATE(CSdiDoc)//动态创建声明宏
public:
};
IMPLEMENT_DYNCREATE(CSdiDoc,CDocument)//动态创建实现宏
//视图类
class CSdiView:public CEditView
{
DECLARE_DYNCREATE(CSdiView)//动态创建声明宏
public:
};
IMPLEMENT_DYNCREATE(CSdiView,CEditView)//动态创建实现宏
//应用程序类
class CMainApp:public CWinApp
{
public:
virtual BOOL InitInstance();
};
//主窗体类
class CMainFrame:public CFrameWnd
{
DECLARE_MESSAGE_MAP()//消息映射(Map)声明(Declare)宏
DECLARE_DYNCREATE(CMainFrame)//动态创建声明宏
public:
};
IMPLEMENT_DYNCREATE(CMainFrame,CFrameWnd)//动态创建实现宏
BEGIN_MESSAGE_MAP(CMainFrame,CFrameWnd)//主窗体消息映射实现宏
END_MESSAGE_MAP()
CMainApp theApp;
BOOL CMainApp::InitInstance()
{ //动态创建不用指明对象,用类即可
CSingleDocTemplate *pTemplate=new CsingleDocTemplate(IDR_MENU1,
RUNTIME_CLASS(CsdiDoc),
RUNTIME_CLASS(CmainFrame),
RUNTIME_CLASS(CsdiView));
AddDocTemplate(pTemplate);//加载单文档模板
//新建文档
OnFileNew(); //创建的关键函数
m_pMainWnd->ShowWindow(SW_SHOW);
m_pMainWnd->UpdateData();
return TRUE;
}
4 创建过程
4.1 关系
CWinApp
//文档模板管理对象(AddDocTemplate函数中的,将创建好的模板给他)
|->m_pDocManager(CDocManager*)
|->m_templateList(CDocTemplate List)(保存文档模板的链表,证明模板可以有多个)
|->CSingleDocTemplate
|->CRuntimeClass *m_pDocClass//文档
|->CRuntimeClass *m_pFrameClass //主框架窗口
|->CRuntimeClass *m_pViewClass //视图
★|->CRuntimeClass *m_pOnlyDoc//单文档程序中那个文档对象指针
(单文档程序只能有一个文档)
4.2 创建过程(在OnFileNew函数中执行)
4.2.1 使用m_pDocManager从m_templateList中获取文档模板的第一个,因为是单文档视图窗口类,所以如果有多个模板的话,用字符串表区分模板,程序会弹出对话框选择用哪个模板创建程序,字符串表的信息中,用‘\n’隔开三段,分别对应(窗口的标题,视图窗口标题,文档的标题)
4.2.2 使用文档模板中的m_pDocClass创建文档对象
4.2.3 使用文档模板中的m_pFrameClass创建Frame对象
4.2.4 将文档对象和m_pViewClass传给Frame对象,并调用LoadFrame创建Frame窗口
4.2.5 在Frame的OnCreate函数中,创建视图对象和窗口
4.2.6 在View的OnCreate函数中,间View的地址保存到Document中,将Document的地址保存到View中。
多文档视图应用程序
1 多文档视图
同时能够打开多个文档进行处理
2 多文档视图相关
2.1 相关类
CWinApp / CMDIFrameWnd / CMDIChildWnd / Cview / CDocument
2.2 文档模板
CMultiDocTemplate-多文档模板
3 使用
4 创建过程
4.1关系
CWinApp
//文档模板管理器对象的指针(AddDocTemplate函数中的,将创建好的模板给他)
|->m_pDocManager(CDocManager*)
|->m_templateList(CDocTemplate List)(保存文档模板的链表,证明模板可以有多个)
|->CMultiDocTemplate
|->CRuntimeClass *m_pDocClass//子框架窗口的文档
|->CRuntimeClass *m_pFrameClass //子框架窗口
|->CRuntimeClass *m_pViewClass //子框架窗口的视图
★|->m_docList(CDocument List)//多文档子窗体存储链表
4.2创建(OnFileNew)与单文档类似
★MDI多文档视图窗口例子:
#include "stdafx.h"
#include "resource.h"
//文档类
class CMdiDoc:public CDocument
{ DECLARE_DYNCREATE(CMdiDoc)//动态创建声明宏
public:
CString m_strText;
};
IMPLEMENT_DYNCREATE(CMdiDoc,CDocument)//动态创建实现宏
//视图类
class CMdiView:public CEditView
{
DECLARE_DYNCREATE(CMdiView)//动态创建声明宏
DECLARE_MESSAGE_MAP()//消息映射(Map)声明(Declare)宏
public:
//CView的OnUpdate虚函数
virtual void OnUpdate( CView* pSender, LPARAM lHint, CObject* pHint );
afx_msg void OnEnChange();
};
IMPLEMENT_DYNCREATE(CMdiView,CEditView)//动态创建实现宏
BEGIN_MESSAGE_MAP(CMdiView,CEditView)//主窗体消息映射实现宏
ON_CONTROL_REFLECT_EX(EN_CHANGE,OnEnChange)//文档视图中数据发生变化时产生的消息
END_MESSAGE_MAP()
//应用程序类
class CMdiApp:public CWinApp
{
DECLARE_MESSAGE_MAP()//消息映射(Map)声明(Declare)宏
public:
virtual BOOL InitInstance();
afx_msg void OnNew();
};
BEGIN_MESSAGE_MAP(CMdiApp,CWinApp)//主窗体消息映射实现宏
ON_COMMAND(ID_NEW,OnNew)//新建子窗口消息映射
END_MESSAGE_MAP()
★//新建子窗口函数
void CMdiApp::OnNew()
{
OnFileNew();//直接调用应用程序类的OnFileNew即可
}
//主窗体类
class CMainFrame:public CMDIFrameWnd
{
DECLARE_MESSAGE_MAP()//消息映射(Map)声明(Declare)宏
public:
afx_msg void OnNewView();
};
BEGIN_MESSAGE_MAP(CMainFrame,CFrameWnd)//主窗体消息映射实现宏
ON_COMMAND(ID_NEWVIEW,OnNewView)//创建新视图消息映射
END_MESSAGE_MAP()
//子窗体类
class CChildFrame:public CMDIChildWnd
{ DECLARE_DYNCREATE(CChildFrame)//动态创建声明宏
public:
};
IMPLEMENT_DYNCREATE(CChildFrame,CMDIChildWnd)//动态创建实现宏
★//创建新视图消息处理函数
void CMainFrame::OnNewView()
{
//获取当前编辑文档
CFrameWnd *pFrameWnd=GetActiveFrame();//获取当前活动窗口
if(pFrameWnd->IsKindOf(RUNTIME_CLASS(CChildFrame)))
return;
CView *pView=pFrameWnd->GetActiveView();//根据当前活动窗口获取他得视图
CDocument *pDoc=pView->GetDocument();//根据视图获取当前活动窗口的文档对象
//基于这个文档创建新的Frame包含视图窗口
CDocTemplate *pTemplate=pDoc->GetDocTemplate();//获得这个文档的模板
CChildFrame *pNewFrame=(CChildFrame *)pTemplate->CreateNewFrame(pDoc,NULL);//根据模板,和文档指针,创建新的子窗口
pTemplate->InitialUpdateFrame(pNewFrame,pDoc);//使框架窗口中的每一个视图接收它们的OnInitialIpdate
}
★//视图的OnUpdate虚函数重写
void CMdiView::OnUpdate( CView* pSender, LPARAM lHint, CObject* pHint )
{
//从文档里面拿数据,显示到视图中
CMdiDoc *pDc=(CMdiDoc *)GetDocument();
SetWindowText(pDc->m_strText);
}
★//文档视图数据改变响应消息实现函数
void CMdiView::OnEnChange()
{
CMdiDoc *pDoc=(CMdiDoc *)GetDocument();//获取这个视图的文档指针
GetWindowText(pDoc->m_strText);//将视图更新的数据保存到文档中
pDoc->UpdateAllViews(this);//文档通知每个和自己相关的视图调用自己的OnUpdate
}
CMdiApp theApp;
BOOL CMdiApp::InitInstance(){
//创建多文档模板
CMultiDocTemplate *pTemplate=new CMultiDocTemplate(IDR_MDICHILD,
RUNTIME_CLASS(CMdiDoc),
RUNTIME_CLASS(CMDIChildWnd),
RUNTIME_CLASS(CMdiView)
);
//将文档模板保存进模板管理器
AddDocTemplate(pTemplate);
//创建和显示主框架窗口
CMainFrame *pFrame=new CMainFrame;
pFrame->LoadFrame(IDR_MDIMAIN);
m_pMainWnd=pFrame;
m_pMainWnd->ShowWindow(SW_SHOW);
m_pMainWnd->UpdateWindow();
//新建文档(拥有几个OnFileNew就创建几个子窗口,注意OnFileNew函数是CWinApp的成员函数,添加菜单消息要在应用程序类中添加)
OnFileNew();
return TRUE;
}
文档视图架构
1 相关类
CWinApp-应用程序类
CFrameWnd-框架窗口类,应用于单文档
CMDIFrameWnd/CMDIChildWnd-主框架/子窗口,应用于多文档
CView-视图类,显示数据
CDocument-文档类,用于管理数据
CDocTemplate(抽象类)-文档模板类
两个子类:CSingleDocTemplate-单文档模板
CMultiDocTemplate-多文档模板
CDocManager-文档模板管理器
2 数据关系
CWinApp
|->m_pDocManager(CDocManager*)//文档模板管理器对象(AddDocTemplate函数中的,将创建好的模板给他)
|->m_templateList(CDocTemplate List)(保存文档模板的链表,证明模板可以有多个)
|->CSingleDocTemplate-单文档模板, CMultiDocTemplate-多文档模板
★|->CRuntimeClass *m_pOnlyDoc ★|->m_docList(CDocument List)
|->CDocument
|->m_viewList(CcView List)
(保存视图地址)
|->m_pMainWnd(CFreameWnd)
|->m_pMainWnd(CFrameWnd)
|->m_pViewActive(CView)
|->m_pDocument(CDocument)
|->m_viewList(Ciew的LIst)
3 创建对象
3.1 CWinApp查找模板,创建文档对象
3.2 OnFileNew中创建Frame对象
3.3 Frame的OnCreate中创建View
3.4 View的OnCreate中,View与Document相关联
4 命令消息相应顺序
CView->CDocument->Frame->App
MFC绘图
向导中生成消息
添加命令消息:Ctrl+W 类向导对话框 查找ID->选择命令消息格式双击(COMMAND)->确定->编辑消息即可
添加标准消息:在所要添加的类右键->Add windows message Hander->选择消息,双击加载->Add and Edit
删除一行:Ctrl+L
1绘图相关
CDC相关-绘图设备-被绘图的地方(纸) CGdiObject相关-绘图对象-用什么绘制(笔)
2 CDC相关
2.1 CDC父类是CObject,封装了HDC绘图句柄和相应的API
2.2子类
CPaintDC-封装类BeginPaint和EndPaint函数,只能在WM_PAINT的消息处理函数中使用
绘图范围是窗口的客户区。
CClinetDC-封装了客户区DC,使用范围比CPaintDC更广一些
绘图范围也是窗口的客户区
CWindowDC-封装了窗口的DC,绘图范围是整个窗口
CMetaFileDC-封装了Windows图源文件的处理。
和别的绘图保存点坐标不一样,它保存的是绘图命令(Moveto,画矩形,画圆等)
2.3 CDC相关类使用
★创建CDC
virtual BOOL CreateDC( LPCTSTR lpszDriverName, //打印设备的类型(显示器,打印机等)
LPCTSTR lpszDeviceName, //设备名称
LPCTSTR lpszOutput,
const void* lpInitData //和设备相关的一些参数
);
例:
void CMFC_DCView::OnCdc()
{
CDC dc;
dc.CreateDC("DISPLAY",NULL,NULL,NULL);//创建设备
dc.TextOut(100,100,"CDC");//输出字符(CDC是显示器坐标为基准)
dc.DeleteDC();//即使不去删除设备,析构的时候也会删除
}
★创建CClinetDC
例:
void CMFC_DCView::OnCclinetdc()
{
CClientDC dc(this);//构造绘图设备对象(有参数,需要传入窗口指针)
dc.TextOut(0,0,"CClientDC-客户区");
dc.MoveTo(100,100);//线的起点
dc.LineTo(200,200);//线的终点
}
★创建CWindowDC
例:
void CMFC_DCView::OnCwindowdc()
{
CWindowDC dc(AfxGetMainWnd());//创建绘图设备(AfxGetMainWnd()得到窗口的句柄)
dc.TextOut(0,0,"CWindowDC-窗口");
}
★创建CMetaFileDC
void CMFC_DCView::OnCmetafiledc()
{
CMetaFileDC dcMEta;
dcMEta.Create("C:\\huai.dat");//创建对象(就是创建将保存命令的文件)
dcMEta.TextOut(100,200,"CMetaFileDC");//绘图
dcMEta.Rectangle(CRect(100,100,300,300));
HMETAFILE hMetaFile=dcMEta.Close();//保存这些命令进文件返回绘图设备通用句柄
CClientDC dc(this);//创建在当前客户区绘图的对象
dc.PlayMetaFile(hMetaFile);//显示文件绘图命令
DeleteMetaFile(hMetaFile);//删除句柄
}
3 CGdiObject相关
3.1相关子类
CBitmap-位图 CBrush-画刷 CFont-字体 CPalette-调色板 CPen-画笔
CRgn-基于基本的集合图形,构建复杂的集合图形
3.2 CRgn使用
3.2.1创建CPen
例:void CMFC_DCView::OnPen()
{
CClientDC dc(this);//创建绘图设备
CPen pen(PS_SOLID,10,RGB(230,0,0));//创建画笔对象(线型,线宽,颜色)
CPen *pOldPen=(CPen *)dc.SelectObject(&pen);//将创建好的对象选入设备
dc.Rectangle(50,50,100,100);//绘图
dc.SelectObject(pOldPen);//还回绘图对象
pen.DeleteObject();//删除对象
}
3.2.2创建CBrush—(可以直接用刷子,也可以刷位图等)
例:void CMFC_DCView::OnBrush()
{
CClientDC dc(this); //创建绘图设备
CBitmap bmp;//创建位图对象
bmp.LoadBitmap(IDB_BITMAP1);//用位图对象加载位图资源
CBrush brush(&bmp);//创建绘制此位
展开阅读全文