zoukankan      html  css  js  c++  java
  • VC 多文档用户界面设计

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

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

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

           Step 3:将菜单资源IDR_MAINFRAME中添加菜单项“功能”,并添加菜单子项“功能1和“功能2,分别对应项目开发中的不同的业务逻辑。为了保证整个过程中菜单项的一致性,在IDR_MAINFRAMECtrl + C,然后Ctrl +V两次生成和IDR_MAINFRAME一样的菜单两个,然后将这两个菜单分别改名为IDR_MISTYPEIDR_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(否则:))。并响应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)  运行的结果为:



    但是呢,到目前为止,程序有点bug,当点击功能1,再关闭,再打开,出现内存错误。这是由于功能1窗口关闭后,m_pDoc1并没有相应地置为NULL。解决方法就是在View类中添加OnDestroy消息响应:

    void CMISView::OnDestroy()
    {
    CView::OnDestroy();
    
    // TODO: Add your message handler code here
    ((CMainFrame*)AfxGetMainWnd())->m_pDoc1 = NULL;
    }
    





  • 相关阅读:
    java基础3 循环语句:While 循环语句、do while 循环语句、 for 循环语句 和 break、continue关键字
    java基础2 判断语句:if ... else 语句和 switch 语句
    IT行业经典面试技巧及方法思路。
    Java基础1,入门基础知识
    SVN的使用、分支合并及解决冲突详解
    VC工程产生文件后缀名解释
    ireport报表,打印时,报表加载失败的解决方法
    MySQL 事务、视图、索引
    MySQL高级查询
    MySQL中的主键约束和外键约束
  • 原文地址:https://www.cnblogs.com/luoshupeng/p/2151970.html
Copyright © 2011-2022 走看看