深入浅出MFC学习笔记4--简单而完整:MFC骨干程序

来源:互联网 发布:苹果手机照片传不到mac 编辑:程序博客网 时间:2024/06/06 03:21
  1. 一个骨干MFC程序【不含ODBC或OLE】用到的类:
    CObject->CCmdTarget->CWinThread->CWinApp->CMyWinApp
    ->CWnd ->CView->CMyView
    ->CFrameWnd->CMDIFrameWnd
    ->CMDIChildWnd
    ->CControlBar->CStatusBar
    ->CToolBar
    ->CDialog
    ->CDocument
    ->CDocTemplate

所谓工具栏,是将几个常用的菜单项目以按钮类型呈现出来,这个工具栏可以随处停驻【dockable】。
所谓状态栏是主窗口最下方的文字显示区。【只要菜单拉下,状态栏就会显示鼠标落座的菜单项目的说明文字,状态栏右侧有3个小窗口,可以用来显示一些特殊按键的状态】

2.Document/View支撑你的应用程序
CDocument简单的说,就是负责处理数据的类。
CDocument的另一价值在于它搭配了另一重要的类:CView

数据有体有面,实际的数据数值是体,显示的屏幕或打印机上的画面是面。
数值的处理用一系列数据结构,数据的显示应使用绘图工具,如坐标系统,笔刷颜色,点线圆弧,字形...。
CView为了数据的表现而设计的。CView还负责程序和使用者间的交谈接口。

Document/View的价值在于,这些MFC类已经把一个应用程序所需的“数据处理与显示”的函数空壳都设计好了。
有关文件读写的操作在CDocument的Serialize函数中进行,有关画面显示的操作在CView的OnDraw或OnPaint函数中进行。

MFC已为我们做的:
1. 按下【File/Open】,Application Framework会激活对话框,让你指定文件名,然后调用CMyDoc::Serialize读文件。Application Framework还会调用CMyView::OnDraw把数据显示出来。
2. 如屏幕状态改变,产生了WM_PAINT,Framework会自动调用你的CMyView::OnDraw,传一个Display DC,让你重新绘制窗口内容。
3. 如果按下【File/Print…】Framework会自动调用你的CMyView::OnDraw,这次传进去的是个Printer DC,因此绘图操作的输出对象就成了打印机。

GUI系统为了让程序员的精力放到应用软件的真正目标上。
MFC的Document/View为了让程序员的精力放到真正的数据结构设计和真正的数据显示上。

ScibbleApp step0程序中各类的相关数据

类名称 基类 类声明于 类定义于 CScribbleApp CWinApp Scribble.h Scribble.cpp CMainFrame CMDIFrameWnd Mainfrm.h Mainfrm.cpp CChildFrame CMDIChildWnd Childfrm.h Childfrm.cpp CScribbleDoc CDocument ScribbleDoc.h ScribbleDoc.cpp CScribbleView CView ScribbleView.h ScribbleView.cpp CAboutDlg CDialog Scribble.cpp Scribble.cpp

骨干程序使用哪些MFC类:
如果把标准图形界面(工具栏和状态栏)以及Document/View考虑在内,一个标准的MFC MDI程序使用这些类。

MFC类名称 我的类名称 功能 CWinApp CScribbleApp Application object CMDIFrameWnd CMainFrame MDI主窗口 CMultiDocTemplate 直接使用 管理Document/View CDocument CScribbleDoc Document,负责数据结构与文件操作 CView CScribbleView View,负责数据的显示与打印 CMDIChildWnd CChildFrame MDI子窗口 CToolBar 直接使用 直接使用 CStatusBar 直接使用 状态栏 CDialog CAboutDlg About对话框

关于改写的InitInstance中:
new CMainFrame【注册并显示主窗口对象】
LoadFrame(x)产生主窗口并加挂菜单等诸元素,并指定窗口标题,文件标题,文件扩展名等【关键在IDR_MAINFRAME常量】,LoadFrame中调用Create,Create中调用CreateWindowEx,于是触发WM_CREATE消息,消息被CMainFrame的OnCreate函数处理【在此为主窗口挂上工具栏和状态栏】

Document Template的意义:
数据的内容,数据的表象,容纳数据表象之外框窗口三者是一体的,即,程序每打开一份文件【数据】,就应该产生三分对象:
1. 一份Document对象
2. 一份View对象
3. 一份CMDIChildWnd对象

这三份对象由一个所谓的Document Template对象来管理,让这三份对象产生关系的关键在于CMultiDocTemplate。
如果程序支持不同的数据格式【TEXT,BITMAP…】,那么就需要不同的Document Template

关于这一句:
CMultiDocTemplate::CMultiDocTemplate(
UINT nIDResource,
CRuntimeClass* pDocClass,
CRuntimeClass* pFrameClass,
CRuntimeClass* pViewClass
);
第一个参数IDR_SCRIBTYPE,代表RC档中的菜单,图标,字符串三种资源。
字符串以’\n’分隔为7个子字符串,用以描述文件类型。每一个字符串在程序进行过程中取得,只要调用CDocTemplate::GetDocString,并在其第二个中指定索引值【1-7】即可。
建议用CDocTemplate定义的7个常量代替没有字面意义的索引值。
class CDocTemplate : public CCmdTarget
{

enum DocStringIndex{    windowTitle,    docName,    fileNewName,    filterName,    filterExt,    regFileTypeId,    regFileTypeName};..

};

Scribble的Document/View设计:
我们用CDocument管理数据,借Collections Classes【MFC中一组专门用来处理数据的类】处理实际的数据。借CView负责数据的显示,借CDC和CGdiObject实际绘图。

数据的管理操作:
1. 读写文件是必要的。文件存取操作称为Serialization,由Serialize函数负责,我么可以也应该在CMyDoc中改写Serialize函数使它符合个人需求。
2. 数据的显示,数据的接受编辑。两者都由View负责,使用者对Document的任何编辑操作都必须通过Document Frame窗口,消息随后传到CView。
当Document Frame窗口收到WM_PAINT,窗口内的View的OnPaint函数会被调用,OnPaint又调用OnDraw。为了显示数据我们必须改写OnDraw。
为了接受编辑操作,必须在View类中接受鼠标或键盘消息并处理之。

主窗口的诞生:
CMainFrame* pMainFrame = new CMainFrame;
pMainFrame->LoadFrame(IDR_MAINFRAME);

鼠标拖放:
意思是,你可以从Shell中以鼠标拉动一个文件,拖到你的程序中,你的程序因而打开此文件并读其内容,将内容放到一个Document Frame窗口中。甚至,使用者在Shell中以鼠标对某个文件【你的应用程序的文件】快按两下,也能激活你这个程序,并自动完成打开文件,读文件和显示等操作。
原理和做法:
当使用者从Shell中拖放一个文件到程序A,Shell就配置一块全局内存,填入被拖拽的文件名称【含路径】,然后发出WM_DROPFILES传到程序A的消息队列。程序A取得此消息后,应该把内存的内容取出,再想办法打开文件读文件。

BOOL CScribbleApp::InitInstance(){    m_pMainWnd->DragAcceptFiles();    EnableShellOpen();    RegisterShellFileTypes(TRUE);    ...}
  1. CWnd::DragAcceptFiles(BOOL bAccept = TRUE);
    参数为TRUE表示你的主窗口和每个子窗口都愿意接受来自Shell的拖放文件,CFrameWnd内有一OnDropFiles成员函数,负责对WM_DROPFILES消息做反应,它会通知application对象的OnOpenDocument,且夹带被拖放文件的名称。
  2. CWinApp::EnableShellOpen()
    允许使用者对本程序文件快按两下,本程序打开文件读入内容。如当时本程序已执行,Framework不会再执行程序的另一副本,而以DDE通知程序吧文件读进来。
  3. CWinApp::RegisterShellFileTypes()
    向Shell注册本程序的文件类型。有了这样的注册,在Shell的双击才有着力点,这个函数搜寻Document Template链表的每一种文件类型,然后把它加到系统所维护的registry【注册表】中。
    【一种文件类型只能与一种程序对应】

消息映射

标准菜单File/Edit/View/Window/Help
各种MDI程序的菜单,有两组。
一组是没任何子窗口存在时出现。【本例IDR_MAINFRAME】
一组是有任何子窗口存在时出现【本例是IDR_SCRIBTYPE】

默认的菜单命令项及其处理程序的摘要整理:
【预有关联为Yes,表示菜单中有此命令项时,当它被单击,自然就引发对应的命令处理程序,不需在Message Map中拦截】

菜单内容 命令项ID 默认的处理函数 预有关联 File New ID_FILE_NEW CWinApp::OnFileNew No Open ID_FILE_OPEN CWinApp::OnFileOpen No Close ID_FILE_CLOSE CDocument::OnFileClose Yes Save ID_FILE_Save CDocument::OnFileSave Yes Save As ID_FILE_SAVEAS CDocument::OnFileSaveAs Yes Print ID_FILE_PRINT CView::OnFilePrint No Print Pre & View ID_FILE_PRINT_PREVIEW CView::OnFilePrintPreView No Print Setup ID_FILE_PRINT_SETUP CWinApp::OnFilePrintSetup No “Recent File Name” ID_FILE_MRU_FILE1~4 CWinApp::OnOpenRecentFile Yes Exit ID_APP_EXIT CWinApp::OnFileExit Yes Edit Undo ID_EDIT_UNDO None Cut ID_EDIT_CUT None Copy ID_EDIT_COPY None Paste ID_EDIT_PASTE None View Toolbar ID_VIEW_TOOLBAR FrameWnd::OnBarCheck Yes Status Bar ID_VIEW_STATUS_BAR FrameWnd::OnBarCheck Yes Window(MDI only) New Window ID_WINDOW_NEW MDIFrameWnd::OnWindowNew Yes Cascade ID_WINDOW_CASCADE MDIFrameWnd::OnWindowCmd Yes Title ID_WINDOW_TILE_HORZ MDIFrameWnd::OnWindowCmd Yes Arrange Icons ID_WINDOW_ARRANGE MDIFrameWnd::OnWindowCmd Yes Help About AppName ID_APP_ABOUT None

上述5个需设定Message Map的AppWizard已自动为我们设置好。

0 0
原创粉丝点击