.MFC 多文档工程 实现多文档用户界面

  用习惯了Delphi、VB、Windows Form(Visual C#)等称之为RAD(Rapid Application Development)的开发工具进行项目开发的都会很满足这些工具和平台提供的快速界面开发的功效:你可以很容易就可以实现一个MIS系统的管理界面,提供一个主框架,点击主框架上的某一个菜单项就打开一个处理事务的窗口,这些窗口可以重叠,可以最大/小化,一切看起来都像那么回事。但是当你在VC中进行开发的时候,发现整个世界都变了,虽然VC提供了MDI支持多文档视图的框架,但是每次你点击“打开”/“新建”菜单项的时候,你会发现新打开的窗口千孔一面,都是同一个样式,根本就不能满足项目的开发。这就需要你能够为不同的业务逻辑提供不同的显示/操作界面。这里给出一个模版,供大家参考:

Step 1:使用VC 6.0新建一个Project,命名为:MIS。除选择多文档属性外,一切使用“默认”方式。于是你可以获得六个类:CMainFrame,CChildFrame,CMISAppCMISDocCMISView,和CAboutDlg

       Step 2新建一套新的Doc/View/Frame:添加新的文档类CNewDoc,基类为CDocument(方法:Insert——>New Class(Class Type:MFC Class),基类选择CDocument)。添加新的框架类CNewChildFrame,基类为CMDIChildWnd,添加方法同上。添加新的视图类CNewView,方法:Insert——>New Form,对话框中的文档类选择为CNewDoc(默认也是它)。

       Step 3:在菜单资源IDR_MAINFRAME中添加菜单项“功能”,并添加菜单子项“功能1”和“功能2”,分别对应项目开发中的不同的业务逻辑。为了保证整个过程中菜单项的一致性,故复制两个一样的菜单,方法:首先选中IDR_MAINFRAME,再Ctrl C,然后Ctrl V 两次,生成和IDR_MAINFRAME一样的菜单两个,然后将这两个菜单分别改名为IDR_MISTYPE和IDR_VIEW2_TMPL(注意:先将后两个菜单名字Copy再删除它们,然后再改名,这里菜单的名字可以修改,但是这里为了简单,就直接使用系统生成的默认菜单名字了,如果改变了资源名字则要在New CMultiDocTemplate 时修改相应的项)。

Step 4:在CMISApp中添加两个文档模板类变量以记录这两个框架类,为简单起见在这里声明为public(方便后面的访问,也就懒得管面向对象的设计原则了,因为仅仅是示例而已):

public:

CMultiDocTemplate* m_pDocTemplate1;

     CMultiDocTemplate* m_pDocTemplate2;

并将BOOL CMISApp::InitInstance()函数中由VC自动生成的代码作如下改变:

{   // BLOCK: doc template registration

     // Register the document template.  Document templates serve

     // as the connection between documents, frame windows and views.

     // Attach this form to another document or frame window by changing

     // the document or frame class in the constructor below.

     CMultiDocTemplate* m_pDocTemplate2 = new CMultiDocTemplate(

            IDR_VIEW2_TMPL,        // 这里是菜单项目名

            RUNTIME_CLASS(CNewDoc),     // document class

            RUNTIME_CLASS(CMDIChildWnd),    // frame class

            RUNTIME_CLASS(CNewView));      // view class

     AddDocTemplate(m_pDocTemplate2);

}

改为:1)CMultiDocTemplate*去掉,否则你是新建了一个CMultiDocTemplate*的对象。2)但如果不是选用New Form 视图,就不会生成以上代码,则直接添加以下代码。

m_pDocTemplate2 = new CMultiDocTemplate(

IDR_VIEW2_TMPL,        // 这里是菜单项目名

RUNTIME_CLASS(CNewDoc),         // document class

RUNTIME_CLASS(CNewChildFrame),       // frame class

RUNTIME_CLASS(CNewView));        // view class

AddDocTemplate(m_pDocTemplate2);

以及:

       CMultiDocTemplate* pDocTemplate;

       pDocTemplate = new CMultiDocTemplate(

              IDR_MISTYPE,

              RUNTIME_CLASS(CMISDoc),

              RUNTIME_CLASS(CChildFrame), // custom MDI child frame

              RUNTIME_CLASS(CMISView));

       AddDocTemplate(pDocTemplate);*/

改为:将CMultiDocTemplate*去掉,否则你是新建一个CMultiDocTemplate*的对象。

m_pDocTemplate1 = new CMultiDocTemplate(

              IDR_MISTYPE,

              RUNTIME_CLASS(CMISDoc),

              RUNTIME_CLASS(CChildFrame), // custom MDI child frame

              RUNTIME_CLASS(CMISView));

AddDocTemplate(m_pDocTemplate1);

 

Step 5:在MainFrm.h中添加两个文档类变量记录这里的两个不同的Document,为简单起见就声明为public:

public:

CMISDoc* m_pDoc1;

CNewDoc* m_pDoc2;

注意:必须CMainFrame构造函数中将上面两个变量置为NULL并在MainFrm类应IDR_MAINFRAME的两个菜单项目“功能1”和“功能2”消息,在各自的响应菜单中分别添加响应函数:

       // TODO: Add your command handler code here

       if (m_pDoc1 != NULL)   //已经打开则激活

       {

              POSITION pos;

 

              pos =m_pDoc1->GetFirstViewPosition();

 

              CView* pView = m_pDoc1->GetNextView(pos);

 

              pView->GetParentFrame()->ActivateFrame();

       }

       else

       {

              CMISApp* pApp = (CMISApp*)AfxGetApp();

 

              m_pDoc1 = (CMISDoc*)(pApp->m_pDocTemplate1->OpenDocumentFile(NULL));

       }

和:

       // TODO: Add your command handler code here

       if (m_pDoc2 != NULL)

       {

              POSITION pos;

 

              pos =m_pDoc2->GetFirstViewPosition();

 

              CView* pView = m_pDoc2->GetNextView(pos);

 

              pView->GetParentFrame()->ActivateFrame();

       }

       else

       {

              CMISApp* pApp = (CMISApp*)AfxGetApp();

             

              m_pDoc2 = (CNewDoc*)(pApp->m_pDocTemplate2->OpenDocumentFile(NULL));

       }

 

       至此就完成了整个工作。需要说明的是:

1)  实现中由于使用到相关的类,因此在必要的地方需include相关的头文件,这里省略(编译有错误的时候添加就是了;

2)  这里给出的是一个示例代码,实际开发中可以通过参考实现以获得自己想要实现的具体应用情况(例如视图类的不同、数量不同,更重要的还有业务逻辑的不同实现等);

3)  运行的结果如下图所示:

来自http://ffwmxr.blog.163.com/blog/static/6637272220100160531374/

  • 2
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值