现在的位置: 首页 > 自动控制 > 工业·编程 > 正文

将Doc/View 应用程序打造成 ActiveX 控件

2012-08-26 00:29 工业·编程 ⁄ 共 3342字 ⁄ 字号 暂无评论

    众所周知,MFC提供了一个非常强大的,但是又不太容易理解的编程模型叫做文档/视图结构。它的基本思想就是将数据的表现和数据的存在分开管理。MFC提供了很多现在的类来达成这个目标,通常,利用CFrameWnd,CView和CDocument这三个类,再利用CSingleDocTemplate的魔法将它们串联起来,就可以很容易的构建出一个单文档的Doc/View应用程序

    但是,随着互联网的发展,一切东西都跃然于网络上。我们能不能将文档/视图结构的应用程序做成一个酷酷的,可以用于网络发布的应用程序呢。比如说我们可以通过浏览器操作该应用程序。上面的框架界面嵌入到浏览器当中。嗯,一个很好的选择就是将该应用程序打造成ActiveX控件。下面开始介绍该魔法产生的过程:

    首先,我们要考虑到该ActiveX控件可以会显示在Html页上做为浏览器的一个子窗口。而如果使用传统的CDocTemplate类将文档,视图相联系,则每当产生一个新的框架时,都会弹出一个具有框架窗口,达不到内嵌的目的,所以,改造CDocTemplate类是必须的。其中关键的几点是:

      1、考虑到要嵌在OleControl当中,所以新产生的框架窗口将要以该OleControl作为父窗口。
      2、考虑到作为内嵌的子窗口,而子窗口是不能具有菜单的,因此该控件不具有菜单。但是可以用下拉菜单来加以代替,当然,工具条也是可以的。
      3、除了菜单外,大部分Doc/View的功能都将要保留。

   第一步:我们从CSingleDocTemplate派生一个类,叫做CActiveDocTemplate.其中关键是要修改二个函数:CreateNewFrame和OpenDocumentFile函数。使得每当创那一个新的框架时,都会以外围的OleControl窗口作为父窗口。这两个函数改变如下:
        CDocument* CActiveXDocTemplate::OpenDocumentFile(LPCTSTR lpszPathName,BOOL bVerifyExists) {
       SaveDocumentFile();  //保存当前文档
       m_docFile=lpszPathName;
      if(bVerifyExists) {
  DWORD dwAttrib=GetFileAttributes(lpszPathName);  //得到文档类型
  if(dwAttrib==0xFFFFFFFF||
   dwAttrib==FILE_ATTRIBUTE_DIRECTORY)    //如果是目录的话
  {
   lpszPathName=NULL;
  }

}

return CSingleDocTemplate::OpenDocumentFile(lpszPathName,TRUE);
}
CFrameWnd* CActiveXDocTemplate::CreateNewFrame(CDocument* pDoc,CFrameWnd* pOther) {
ASSERT(pOther==NULL);
ASSERT(m_pFrameClass!=NULL);

if(pDoc!=NULL)
  ASSERT_VALID(pDoc);  //检查对象的有效性
//创建一个框架和相应的文档连接起来
CCreateContext context;
context.m_pCurrentFrame=pOther;
context.m_pCurrentDoc=pDoc;
context.m_pNewViewClass=m_pViewClass;
context.m_pNewDocTemplate=this;

m_pFrameWnd=(CFrameWnd*)m_pFrameClass->CreateObject();
if(m_pFrameWnd==NULL) {
  TRACE1("Warning: Dynamic create of frame %hs failed./n",
            m_pFrameClass->m_lpszClassName);
        return NULL;
}

ASSERT_KINDOF(CFrameWnd,m_pFrameWnd);
if(context.m_pNewViewClass==NULL)
  TRACE0("Warning: creating frame with no default view./n");

ASSERT_KINDOF(CActiveXDocControl,m_pParentWnd);
if(!m_pFrameWnd->Create(NULL,"",WS_CHILD|WS_VISIBLE,CFrameWnd::rectDefault,m_pParentWnd,NULL,0,&context)) {
  TRACE0("Warning: CDocTemplate couldn't create a frame./n");
        return NULL;
}
return m_pFrameWnd;

}
第二步:从COleControl类派生一个CActiveXDocControl类,以改造COleControl类,使之在包含一个指向CActiveDocTemplate的指针。利用该指针,我们可以创建框架窗口,保存文档内容,以完成常规Doc/View应用程序应完成的功能。下面是改造后的CActiveXDocControl头文件的内容:
   class CActiveXDocControl:public COleControl {
enum {WM_IDLEUPDATECMDUI=0x0363};

static BOOL m_bDocInitialized;
CActiveXDocTemplate* m_pDocTemplate;
CFrameWnd* m_pFrameWnd;
// SetInitialSize(100,100);
DECLARE_DYNAMIC(CActiveXDocControl)
protected:
void AddDocTemplate(CActiveXDocTemplate* pDocTemplate);
CDocTemplate* GetDocTemplate() {return m_pDocTemplate;}
afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
afx_msg void OnSize(UINT nType,int cx,int cy);
afx_msg void OnTimer(UINT nIDEvent);
afx_msg void OnDestroy();

DECLARE_MESSAGE_MAP();
DECLARE_DISPATCH_MAP();
DECLARE_EVENT_MAP();

public:
CActiveXDocControl();
virtual ~CActiveXDocControl();

enum {
};
};
并且在控件类的构造函数中加入DocTemplate:
AddDocTemplate(new CActiveXDocTemplate(
  RUNTIME_CLASS(CMy55Doc),
  RUNTIME_CLASS(CMy55Frame),
  RUNTIME_CLASS(CMy55View)
  ));
至此,基本框架都已经建立完成,剩下的步骤就是打造Doc/View应用程序了。
通过这几部,我们可以很容易的把现有的文档/视图结构的应用程序改造成可以在浏览器上显示的ActiveX控件。使得现有程序的功能大部分都保留下来,并且可以在网上进行发布,使得用户可以通过浏览器访问并且使用它。
下面是将上面的文档/视图应用程序改造后在浏览器中运行并操作的界面:
                                                                                             本文参考了msdn 上的Designing ActiveX Components with the MFC Document/View Model。

给我留言

留言无头像?