return DoPreparePrinting (pInfo) /主框架类 class CMainFrame public CframeWnd DECLARE DYNCREATE(CMainFrame IMPLEMENT DYNCREATE(CMainFrame, CFrameWnd) /应用程序类 # define Idr mainframe128主框架的资源代号 class CMy app public CWinApp virtual BOOL InitInstance o DECLARE MESSAGE MAP O BEGIN MESSAGE MAP(CMyApp, CWinApp ON COMMAND(ID FILE NEW, CWinApp: OnFileNew) ON COMMAND(ID FILE OPEN, CWinApp: OnFileOpen) ON COMMAND (ID FILE PRINT SETUP, CWinApp: OnFilePrint Setup) END MESSAGE MAP O ′初始化程序实例:建立并登记文档模板 BOOL CMyApp: InitInstanceo leDocTemplate* pDocTemplate pDocTemplate= new CSingleDocTemplate(//登记文档模板 IDR MAINFRAME RUNTIME CLASS(CMyDoc) RUNTIME CLASS(CMainFrame) RUNTIME CLASS (CMy View)) CCommandLinelnfo cmdInfo //创建及处理命令行信息SDI ParseCommandLine(cmdInfo) if ( ProcessShellCommand(cmdInfo)) m pMainWnd-> ShowWindow(SW_SHoW);//初始化框架窗口 m pMainWnd->UpdateWindowO return TRUE
第 12 单元 文档/视图结构 - 240 - return DoPreparePrinting(pInfo); } // 主框架类 ////////////////////////////////////////////////// class CMainFrame : public CFrameWnd { DECLARE_DYNCREATE(CMainFrame) }; IMPLEMENT_DYNCREATE(CMainFrame, CFrameWnd) // 应用程序类 /////////////////////////////////////////////// #define IDR_MAINFRAME 128 // 主框架的资源代号 class CMyApp : public CWinApp { public: virtual BOOL InitInstance(); DECLARE_MESSAGE_MAP() }; BEGIN_MESSAGE_MAP(CMyApp, CWinApp) 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() // 初始化程序实例:建立并登记文档模板 BOOL CMyApp::InitInstance() { CSingleDocTemplate* pDocTemplate; pDocTemplate = new CSingleDocTemplate( // 登记文档模板 IDR_MAINFRAME, RUNTIME_CLASS(CMyDoc), RUNTIME_CLASS(CMainFrame), RUNTIME_CLASS(CMyView)); AddDocTemplate(pDocTemplate); CCommandLineInfo cmdInfo; // 创建及处理命令行信息 SDI ParseCommandLine(cmdInfo); if (!ProcessShellCommand(cmdInfo)) return FALSE; m_pMainWnd->ShowWindow(SW_SHOW); // 初始化框架窗口 m_pMainWnd->UpdateWindow(); return TRUE;
//全局应用程序对象 CMy App theapp 输入输出:用鼠标左键可在窗口生成一系列泡泡。程序的框架窗口附有一个文件菜单, 其中包括“新建”、“打开”、“保存”和 “打印”等文档操作选项,如图121所 分析:在本程序中一共用到4 个类,即 CMy App、 CMy Wnd、 CMy View 0设置g 退出C) 和 CMyDoc,它们分别是应用程序类 CWinApp、框架窗口类 FRame Wnd、视 图类CVew和文档类 CDocument的派生 类 文档派生类 CMy Doc用于管理吹泡 泡程序的数据,即所有泡泡的包含矩形 图12-1SD结构的吹泡泡程序 由于我们无法断定用户会生成多少泡 泡,所以声明了一个数组 m rect Bubble来存放所有泡泡的包含矩形。 m rect Bubble是 CMyDoc类的私有数据成员,在类外不可见:所以要为其定义一组成员函数作为该数据成员 与外界的接口。函数 Get ListSize()用来统计数组中泡泡的个数:函数 GetBubble()用 于从数组中取一个泡泡的包含矩形:函数 Add Bubble()用于将一个泡泡的包含矩形加入数 组。由于这些成员函数都比较简单,所以采用内联函数的形式 视图派生类的 OnLButton Down()函数用于响应用户的鼠标消息, Ondraw()函数用 于在视图上输出(当然也是在框架窗口的客户区输出)。这些原来都是框架窗口类的工作, 在文档/视图结构中转移到视图类来了 由于数据放到了文档类中,消息响应和输出工作放到了视图类中,因此框架窗口类就显 得非常简洁了。 应用程序类与以前不同的是增加了三个消息响应宏,用于处理文件菜单的选项。由于这 些工作都是标准化的,所以无需重载消息响应函数 在应用程序类的 InitInstance()函数中建立了一个文档模板 在以下几节中,将根据本例详细说明文档/视图结构的程序构造 123文档/视图结构中的应用程序类 应用程序类负责唯一的全局应用程序对象的创建、初始化、运行和退出清理过程,这个 过程我们已经很熟悉了 对于文档/视图结构,要在应用程序类的 InitInstance()函数中创建一个文档模板,来 管理文档/视图结构涉及的框架窗口、文档和视图 文档模板负责在运行时创建(动态创建)文档、视图和框架窗口。一个应用程序对象可
第 12 单元 文档/视图结构 - 241 - } // 全局应用程序对象 CMyApp theApp; 输入输出:用鼠标左键可在窗口生成一系列泡泡。程序的框架窗口附有一个文件菜单, 其中包括“新建”、“打开”、“保存”和 “打印”等文档操作选项,如图 12-1 所 示。 分 析:在本程序中一共用到 4 个类,即 CMyApp、CMyWnd、CMyView 和 CMyDoc,它们分别是应用程序类 CWinApp、框架窗口类 CFrameWnd、视 图类 CView 和文档类 CDocument 的派生 类。 文档派生类 CMyDoc 用于管理吹泡 泡程序的数据,即所有泡泡的包含矩形。 由于我们无法断定用户会生成多少泡 泡,所以声明了一个数组 m_rectBubble 来存放所有泡泡的包含矩形。m_rectBubble 是 CMyDoc 类的私有数据成员,在类外不可见;所以要为其定义一组成员函数作为该数据成员 与外界的接口。函数 GetListSize()用来统计数组中泡泡的个数;函数 GetBubble()用 于从数组中取一个泡泡的包含矩形;函数 AddBubble()用于将一个泡泡的包含矩形加入数 组。由于这些成员函数都比较简单,所以采用内联函数的形式。 视图派生类的 OnLButtonDown()函数用于响应用户的鼠标消息,OnDraw()函数用 于在视图上输出(当然也是在框架窗口的客户区输出)。这些原来都是框架窗口类的工作, 在文档/视图结构中转移到视图类来了。 由于数据放到了文档类中,消息响应和输出工作放到了视图类中,因此框架窗口类就显 得非常简洁了。 应用程序类与以前不同的是增加了三个消息响应宏,用于处理文件菜单的选项。由于这 些工作都是标准化的,所以无需重载消息响应函数。 在应用程序类的 InitInstance()函数中建立了一个文档模板。 在以下几节中,将根据本例详细说明文档/视图结构的程序构造。 12.3 文档/视图结构中的应用程序类 应用程序类负责唯一的全局应用程序对象的创建、初始化、运行和退出清理过程,这个 过程我们已经很熟悉了。 对于文档/视图结构,要在应用程序类的 InitInstance()函数中创建一个文档模板,来 管理文档/视图结构涉及的框架窗口、文档和视图。 文档模板负责在运行时创建(动态创建)文档、视图和框架窗口。一个应用程序对象可 图 12-1 SDI 结构的吹泡泡程序
第12单元文档/视图结构 以管理一个或多个文档模板,每个文档模板用于动态创建和管理一个或多个同类型的文档 (这取决于应用程序是sD程序还是MD程序)。MFC的文档模板类 CDocTemplate用于支 持文档模板操作。由于文档模板类是一个抽象基类,因此不能直接用其声明对象,只能使用 其派生类。对于单文档界面程序,应使用 CSingleDoc Template(单文档模板类),对于一个 多文档界面程序,使用 CMultiple Doc Template(多文档模板类)。例12-1的吹泡泡程序是单 文档界面程序,所以使用单文档界面模板: CSingleDoc Template* pDoc Template pDoc Template new CSingle DocTemplate( IDR MAINFRAME RUNTIME CLASS(CMY D RUNTIME CLASS(CMain Frame) RUNTIME CLASS(CMy View)); 文档模板定义了文档、视图和框架窗口这三个类的关系。通过文档模板,可以知道在创 建或打开一个文档时,需要用什么样的视图和框架窗口显示它。这是因为文档模板保存了文 档及其对应视图和框架窗口的 CRuntimeclass对象的指针。此外,文档模板还保存了所支持 的全部文档类的信息,包括这些文档的文件扩展名信息、文档在框架窗口中的名字、代表文 档的图标等信息 由于文档模板要在运行时动态创建相应的框架程序对象、文档对象和视图对象,因此要 求程序中使用的上述类支持动态创建功能。通过 CMy Wnd、 CMy View和 CMy Doc类中的 DECLARE DYNCREATE()宏和程序中的 IMPLEMENT DYNCREATE()将它们说明为 动态创建类,文档模板即可动态创建这些类的对象。 在 SIngle Doc Template类的构造函数中,还有一个 IDR MAINFRAME参数,用于标明 资源文件中的某些资源。本程序共使用了两项资源,一个文件菜单和一个字符串(应用程序 名)。 在创建了文档模板之后, InitInstance()函数调用 Add Doc Template()函数将创建好 的文档模板加入到应用程序的可用文档模板链表中去。这样,如果用户选择了 File/New或 File/Open菜单选项要求创建或打开一个文档时,应用程序类的 OnNewDocument()成员函 数和 OnOpenDocument()成员函数就可以从文档模板链表中检索出相应的文档模板提示用 户选择适当的文档类型并创建文档及其相关的视图和框架窗口 应用程序类的消息映射 BEGIN MESSAGE MAP(CMy App, CWinApp) ON COMMAND(ID FILE NEW, CWinApp: OnFileNew) ON COMMAND(ID FILE OPEN, CWinApp: OnFileOpen) END MESSAGE MAPO 用于响应新立文档和打开文档消息,这些消息在用户选择文件处理菜单的有关选项时送出 相应的的消息处理函数 OnNewDocument()和 OnOpen Document()中已经包含了有关新 建文档和打开文档的全部标准代码,因此不必再重载这些函数并添加代码了
第 12 单元 文档/视图结构 - 242 - 以管理一个或多个文档模板,每个文档模板用于动态创建和管理一个或多个同类型的文档 (这取决于应用程序是 SDI 程序还是 MDI 程序)。MFC 的文档模板类 CDocTemplate 用于支 持文档模板操作。由于文档模板类是一个抽象基类,因此不能直接用其声明对象,只能使用 其派生类。对于单文档界面程序,应使用 CSingleDocTemplate(单文档模板类),对于一个 多文档界面程序,使用 CMultipleDocTemplate(多文档模板类)。例 12-1 的吹泡泡程序是单 文档界面程序,所以使用单文档界面模板: CSingleDocTemplate* pDocTemplate; pDocTemplate = new CSingleDocTemplate( IDR_MAINFRAME, RUNTIME_CLASS(CMyDoc), RUNTIME_CLASS(CMainFrame), RUNTIME_CLASS(CMyView)); 文档模板定义了文档、视图和框架窗口这三个类的关系。通过文档模板,可以知道在创 建或打开一个文档时,需要用什么样的视图和框架窗口显示它。这是因为文档模板保存了文 档及其对应视图和框架窗口的 CRuntimeClass 对象的指针。此外,文档模板还保存了所支持 的全部文档类的信息,包括这些文档的文件扩展名信息、文档在框架窗口中的名字、代表文 档的图标等信息。 由于文档模板要在运行时动态创建相应的框架程序对象、文档对象和视图对象,因此要 求程序中使用的上述类支持动态创建功能。通过 CMyWnd、CMyView 和 CMyDoc 类中的 DECLARE_DYNCREATE()宏和程序中的 IMPLEMENT_DYNCREATE()将它们说明为 动态创建类,文档模板即可动态创建这些类的对象。 在 CSingleDocTemplate 类的构造函数中,还有一个 IDR_MAINFRAME 参数,用于标明 资源文件中的某些资源。本程序共使用了两项资源,一个文件菜单和一个字符串(应用程序 名)。 在创建了文档模板之后,InitInstance()函数调用 AddDocTemplate()函数将创建好 的文档模板加入到应用程序的可用文档模板链表中去。这样,如果用户选择了 File/New 或 File/Open 菜单选项要求创建或打开一个文档时,应用程序类的 OnNewDocument()成员函 数和 OnOpenDocument()成员函数就可以从文档模板链表中检索出相应的文档模板提示用 户选择适当的文档类型并创建文档及其相关的视图和框架窗口。 应用程序类的消息映射 BEGIN_MESSAGE_MAP(CMyApp, CWinApp) ON_COMMAND(ID_FILE_NEW, CWinApp::OnFileNew) ON_COMMAND(ID_FILE_OPEN, CWinApp::OnFileOpen) END_MESSAGE_MAP() 用于响应新立文档和打开文档消息,这些消息在用户选择文件处理菜单的有关选项时送出。 相应的的消息处理函数 OnNewDocument()和 OnOpenDocument()中已经包含了有关新 建文档和打开文档的全部标准代码,因此不必再重载这些函数并添加代码了