DLL封装框架视图经验总结二

作者:朱金灿

来源:http://www.cnblogs.com/clever101


    上次我谈了DLL封装框架视图的第一种方式动态创建窗口,下面我谈谈第二种方式新建文档模板。实际上这种方式更为简单。(下面所有代码的开发环境为:VS C++ 2005+sp1, Win XP + sp2)

 

方式二 新建文档模板

 

 首先我们建一个使用共享MFC的规则DLL工程Custom1。我的基本想法是这样的:定义五个类,各类描述如下:

类名

描述

备注

CCustomManage1

对外接口类,该类负责动态窗口的创建和销毁。

 

CMySingleDocTemplate

派生自CMySingleDocTemplate类,为新建文档模板类。

 

CCustomDoc

派生自CDocument,为新建窗口对应的文档类。

 

CCustomFrameWnd2

派生自CFrameWnd,为新建框架窗口类。

 

CCustomView

派生自CView,为新建视图类。

 

 

CCustomManage1类的定义和实现,具体代码如下:

    

复制代码
// CustomManage2.h

#pragma once

class AFX_EXT_CLASS CCustomManage2
{
public:
    CCustomManage2(
void);
    
~CCustomManage2(void);

public:

    
void CreateDocTemple();

    CCustomFrameWnd2 
* GetFrameWnd();

private:

   CMySingleDocTemplate 
*m_pMySingleDocTemplate;

   CCustomFrameWnd2 
*m_pFrameWnd;
}
;


// CustomManage2.cpp 


#include 
"StdAfx.h"
#include 
"CustomManage2.h"
#include 
"resource.h"
#include 
"CustomDoc.h"
#include 
"CustomView.h"
#include 
"Custom2.h"

CCustomManage2::CCustomManage2(
void)
{
    m_pMySingleDocTemplate 
= NULL;
    m_pFrameWnd 
= NULL;
}


CCustomManage2::
~CCustomManage2(void)
{
    delete m_pMySingleDocTemplate;
}


extern CCustom2App theApp;
void CCustomManage2::CreateDocTemple()
{
    
// 确保资源句柄有效
    AfxSetResourceHandle(theApp.m_hInstance);

    m_pMySingleDocTemplate 
=  new CMySingleDocTemplate(
        IDR_MENU1,  
// 菜单栏ID
        RUNTIME_CLASS(CCustomDoc),
        RUNTIME_CLASS(CCustomFrameWnd2), 
// custom MDI child frame
        RUNTIME_CLASS(CCustomView));

    CString csTile 
= _T("使用新建文档模板的方式封装框架试图");
    CDocument
* pDoc = m_pMySingleDocTemplate->CreateNewDocument();
    m_pFrameWnd 
= static_cast<CCustomFrameWnd2 *>(m_pMySingleDocTemplate->CreateNewFrame(pDoc, NULL));
    pDoc
->SetTitle(csTile);
    m_pMySingleDocTemplate
->InitialUpdateFrame(m_pFrameWnd, pDoc);
    
}



CCustomFrameWnd2 
* CCustomManage2::GetFrameWnd()
{
     
return m_pFrameWnd;
}

复制代码

 

现在说说如何外部调用。新建一个调用该DLL的单文档工程Ower,现在Ower工程,在框架类CMainFrame类定义一个CCustomManage2类的私有变量:

private:

    CCustomManage2 m_CustomManage2;

  

     然后新建一个菜单项,在菜单项的命令响应函数里弹出新建窗口,具体代码如下:

void CMainFrame::OnTest2()
{
    
// TODO: 在此添加命令处理程序代码
    m_CustomManage2.CreateDocTemple();
}

 

     下面谈谈如何销毁窗口防止内存泄露。这时我们需要考虑用户是怎么关闭新建窗口,用户就是要么是单击调用程序的关闭按钮把两个窗口都关闭;要么单击DLL弹出的新建窗口的关闭按钮。用户先关新建窗口,再关闭调用程序,这个是没有内存泄露的。但是如果用户一下关闭应用程序(就是同时关闭两个窗口),就会出现内存泄露。为此我们需要重写CMainFrame类的WM_CLOSE消息:

    

复制代码
void CMainFrame::OnClose()
{
    
// TODO: 在此添加消息处理程序代码和/或调用默认值

      
// 获取框架窗口指针
          CCustomFrameWnd2 * pFrameWnd = m_CustomManage2.GetFrameWnd();
          
// 如果新建DLL窗口还存在,在确保窗口句柄有效的情况下发送关闭消息关闭它
          if (NULL!=pFrameWnd)
          
{
              HWND hWnd 
= NULL;

              hWnd 
= pFrameWnd->GetSafeHwnd();
              
if(::IsWindow(hWnd))
                   pFrameWnd
->SendMessage(WM_CLOSE,NULL,NULL);
          }


    CFrameWnd::OnClose();
}

复制代码

 

      这样就可以确保内存没有泄露。效果图如下:

 

     上面可以看作是在DLL封装了一个单文档程序。从这个角度看,这种方式比动态新建窗口看起来更为自然一下。另外举一反三,可以封装MDI程序,只须将上面的自定义的文档模板类派生自CMultiDocTemplate。有兴趣的朋友可以去做一下。

    使用DLL封装框架视图的意义在哪里呢?其实是可以应对更多样的需求,很多时候仅仅是对话框并不满足需求,比如图像处理软件中往往是多视图的,当然也可以在对话框绘图,但感觉不如在视图类画图方便,对话框没有大小化窗口的按钮,这也是一个缺点。在一个大系统里,使用DLL封装框架视图可以很方便地将多个业务逻辑划分为多个模块,开发起来更为方便。

  

 

 

 

 

 

 

posted @   是金子就会灿烂  阅读(1060)  评论(1编辑  收藏  举报
编辑推荐:
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
阅读排行:
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· Ollama——大语言模型本地部署的极速利器
· [AI/GPT/综述] AI Agent的设计模式综述
点击右上角即可分享
微信分享提示