http://blog.csdn.net/leohels/article/details/7580873
我们手头上经常会有现成的应用程序,但它们往往不具有OLE可视化编辑服务器的特性,可以通过简单的办法将它们升级,以供基于COM开发的包容器使用。
而MS Office本身就是OLE包容器和服务器,因此经过改造的程序可以直接嵌入MS Office运行。
现有程序:ToolTip程序,基于MFC,GDI+实现的一个提示控件。将它改造成OLE服务器,以便可以在Word等包容器中使用。用VS2010进行改造
步骤:
创建服务器工程
一、新建MFC Application工程,命名为:ToolTip。
新建工程是为了获得有Wizard提供的有关OLE支持的文件,需要用来替添加并替换掉要改造的工程的部分文件。
二、选择Single Document
与要改造的工程一致
三、选择Full server,如果需要从CSrollView继承,可最最后进行修改,如不需要,直接finish。
将OLE相关文件添加到原ToolTip工程中
需要拷贝的文件有
IpFrame.h
IpFrame.cpp
SrvrItem.h
SrvrItem.cpp
ToolTip.cpp (覆盖掉原有文件、实现继承CWinAppEx的实现文件)
ToolTip.reg
Hlp\AfxOleSv.rtf(如果有帮助工程时拷贝并修改hpj文件添加此帮助文件)
Res\Toolbar.bmp(覆盖原有文件)
以上文件为ToolTip提供了可视化编辑的功能,是由创建了“Full Server”,AppWizard在ToolTip.cpp中添加了相应代码。在原ToolTip工程中添加以上文件。
添加OLE服务器相关代码
1.StdAfx.h中添加 OLE支持的头文件
#include <afxole.h>
2.ToolTip.cpp的相关修改
InnitInstance()函数中,主要需要关心的是
pDocTemplate->SetServerInfo(
IDR_SRVR_EMBEDDED,IDR_SRVR_INPLACE,
RUNTIME_CLASS(CInPlaceFrame));
第一个参数是被嵌入到包容器时的菜单和加速键的资源ID,第二个参数是服务器在包容器中被现场激活时的菜单,加速键,工具条的资源ID,最后一个类继承COlePFrameWnd定义了服务器被现场激活时的框架窗口的行为。
接着在ToolTip.h中添加 COleTemplateServer m_server;
3.文档类的基类修改为COleServerDoc,并将CToolTipDoc.cpp中所有的CDocument替换为COleServerDoc
4.为文档添加嵌入支持,通过AppWizard为CToolTipDoc添加OnGetElementItem函数,在CToolTipDoc.h类定义之前添加class CToolTipSrvrItem;前置声明。
COleServerItem* CTipDemoDoc::OnGetEmbeddedItem()
{
// Instead of returning NULL, return a pointer to a new COleServerItem
// derived class that is used in conjunction with this document, then
// remove the ASSERT(FALSE) below. (i.e., return new CMyServerItem.)
CToolTipSrvrItem *pItem = new CToolTipSrvrItem(this);
ASSERT_VALID(pItem);
return pItem;
}
还可以为Doc类添加函数方便获取item:
public:
CToolTipSrvrItem * GetToolTipItem()
{
return (CToolTipSrvrItem*)COleServerDoc::GetEmbeddedItem();
}
添加OLE资源
IDR_SRVR_EMBEDDED,IDR_SRVR_INPLACE的定义一开始是没有的,我们需要添加资源和ID
1.添加OLE标准资源
在Resource View窗口右键选择Resource Includes,在弹出的对话框中Compile-time directives中添加 #include “afxolesv.rc”
2.添加OLE菜单资源
通过向导创建的OLE服务器程序,会自动生成三种不同的菜单,加速键和两种工具条。
如IDR_SRVR_EMBEDDED 和IDR_SRVR_INPLACE,其他类似,这里需要打开OLE服务器的rc和当前工程的RC,对于VS2010,不能直接从别的RC复制粘贴菜单等资源到Resource View窗口里,因此需要右键*.rc文件选择Open With-》Resource Editor打开之后就可以复制粘贴了。除了复制粘贴菜单之外,还需要将IDR_MAIN中的功能菜单项复制到IDR_SRVR_EMBEDDED 和IDR_SRVR_INPLACE等特殊菜单资源中。加速键 和工具栏复制类似。
为文档类添加服务器支持
1.通知OLE服务器嵌入对象被移动或者改变大小
void CTipDemoDoc::OnSetItemRects(LPCRECT lpPosRect, LPCRECT lpClipRect)
{
// TODO: Add your specialized code here and/or call the base class
COleServerDoc::OnSetItemRects(lpPosRect, lpClipRect);
POSITION pos = GetFirstViewPosition();
CTipDemoView *pView = (CTipDemoView *)GetNextView(pos);
pView->ResyncScrollSizes();//此函数为自定义函数,就是重新调整view的滚动条位置
}
改变大小
DOC构造函数添加:m_sizeDoc = CSize(200, 200);并提供获取函数
CSize GetDocSize(){ return m_sizeDoc; }
3.如有必要还可以实现拷贝函数。
void CTipDemoDoc::OnEditCopy()
{
// TODO: Add your command handler code here
CToolTipSrvrItem *pItem = (CToolTipSrvrItem*)GetEmbeddedItem();
pItem->CopyToClipboard(TRUE);
}
实现服务器对象
CToolTipSrvrItem类为我们实现了服务器的大部分工作,我们只需添加程序相关代码。当服务器处于非激活状态时,会调用CToolTipSrvrItem的OnDraw函数,当处于激活状态时,会调用视图类的OnDraw进行显示。因此如果可以让CToolTipSrvrItem的OnDraw实现与View的Ondraw基本的工作。视情况而定。此次就没有实现任何功能
BOOL CToolTipSrvrItem::OnGetExtent(DVASPECT dwDrawAspect, CSize& rSize)添加以下代码将窗口扩展至文档的大小
rSize = pDoc->GetDocSize();
CClientDC dc(NULL);
dc.SetMapMode(MM_ANISOTROPIC);
dc.SetViewportExt(dc.GetDeviceCaps(LOGPIXELSX), dc.GetDeviceCaps(LOGPIXELSY));
dc.SetWindowExt(100, -100);
dc.LPtoHIMETRIC(&rSize);
最终在word、excel中的效果