我們手頭上經常會有現成的應用程序,但它們往往不具有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中的效果