同上!
解决方案 »
- directX截屏的问题
- 怎么将客户端的程序做成多线程的 在线等待啊
- 关于MDI与对话框
- 谢谢aaasng() 帮忙解决一个排列组合的算法问题,请进来回复一下,我好给你加分。
- classwizard生成对话框类是不是没有析构函数的?
- 请问ret=WSARecv(s,&databuf,1,&recvbyte,&flags,&AcceptOverLapped,NULL) 返回-1是什么意思
- ◆200分,请教大哥一个状态 栏的问题?????????????
- 大家说VC好还是JAVA好呢
- 图象采集中捕获到的帧怎么显示在窗口中
- 谁用过 DeviceIoControl
- 保佑我303可以考上研究生!
- 保佑我303可以考上研究生!
The information in this article applies to:
Microsoft Excel 2000
Microsoft Visual C++, 32-bit Enterprise Edition 5.0
Microsoft Visual C++, 32-bit Enterprise Edition 6.0
Microsoft Visual C++, 32-bit Professional Edition 5.0
Microsoft Visual C++, 32-bit Professional Edition 6.0
Microsoft Visual C++, 32-bit Learning Edition 6.0
Microsoft Excel 2002
Microsoft Excel 97 for Windows
Microsoft Word 2002
Microsoft Word 2000
Microsoft Word 97 for WindowsThis article was previously published under Q190985
SUMMARYIt is common for an OLE control to need the IDispatch of its container. You can often get the IDispatch by using QueryInterface() from immediately accessible interfaces on the server, such as IOleClientSite. However, for some servers, such as Microsoft Excel, this approach fails. Another way to get the IDispatch is by using the GetActiveObject() API to get the server's IDispatch from the ROT. However, this method requires that you must be able to obtain the CLSID or ProgID of the server. Furthermore, ambiguous situations can occur where you can't distinguish between multiple instances of the server. This article uses another approach to obtain the IDispatch, which works for both Microsoft Excel and Microsoft Word, even when multiple instances are running. The steps listed below allow you to build a control that can obtain the IDispatch of the container's Document object.
MORE INFORMATIONStep By Step Example
Create a new MFC ActiveX ControlWizard application named OffCntrDisp.
Add the following member variables to your COleControl-derived class:
char m_szDocName[512];
IDispatch *m_pDocDisp;
NOTE: m_szDocName holds the name of the document containing our control, and m_pDocDisp is the IDispatch interface for that document.
Add the following to the end of your COleControl-derived class definition:
// Interface Maps.
protected:
// IoleObject.
BEGIN_INTERFACE_PART(MyOleObject, IOleObject)
INIT_INTERFACE_PART(COffCtlDispCtrl, MyOleObject)
STDMETHOD(SetClientSite)(LPOLECLIENTSITE);
STDMETHOD(GetClientSite)(LPOLECLIENTSITE*);
STDMETHOD(SetHostNames)(LPCOLESTR, LPCOLESTR);
STDMETHOD(Close)(DWORD);
STDMETHOD(SetMoniker)(DWORD, LPMONIKER);
STDMETHOD(GetMoniker)(DWORD, DWORD, LPMONIKER*);
STDMETHOD(InitFromData)(LPDATAOBJECT, BOOL, DWORD);
STDMETHOD(GetClipboardData)(DWORD, LPDATAOBJECT*);
STDMETHOD(DoVerb)(LONG, LPMSG, LPOLECLIENTSITE, LONG, HWND,
LPCRECT);
STDMETHOD(EnumVerbs)(IEnumOLEVERB**);
STDMETHOD(Update)();
STDMETHOD(IsUpToDate)();
STDMETHOD(GetUserClassID)(CLSID*);
STDMETHOD(GetUserType)(DWORD, LPOLESTR*);
STDMETHOD(SetExtent)(DWORD, LPSIZEL);
STDMETHOD(GetExtent)(DWORD, LPSIZEL);
STDMETHOD(Advise)(LPADVISESINK, LPDWORD);
STDMETHOD(Unadvise)(DWORD);
STDMETHOD(EnumAdvise)(LPENUMSTATDATA*);
STDMETHOD(GetMiscStatus)(DWORD, LPDWORD);
STDMETHOD(SetColorScheme)(LPLOGPALETTE);
END_INTERFACE_PART(MyOleObject) DECLARE_INTERFACE_MAP();
This is added to override COleControl's default implementation of IOleObject with your custom MyOleObject.
m_pDocDisp = NULL;
Just after the following line in OffCntrDispCtl.cpp:
IMPLEMENT_OLECTLTYPE(COffCntrDispCtrl, IDS_OFFCNTRDISP, _dwOffCntrDispOleMisc)
add the following code:
BEGIN_INTERFACE_MAP(COffCntrDispCtrl, COleControl)
INTERFACE_PART(COffCntrDispCtrl, IID_IOleObject, MyOleObject)
END_INTERFACE_MAP()
This, along with the modifications in step 3, override COleControl's IOleObject.
Just below the code added in step 5, add the following:
static char buf[8192];
static void DoMsg(char *msg) {
::MessageBox(NULL, msg, "Message", MB_SETFOREGROUND);
} static void DoErr(char *msg, long err) {
static char errBuf[8192];
sprintf(errBuf, "%s, Error: %ld (%08lx)", msg, err,err);
::MessageBox(NULL, errBuf, "Error", MB_SETFOREGROUND);
}
These are helpful routines used later for displaying messages.
STDMETHODIMP COffCntrDispCtrl::XMyOleObject::SetHostNames(LPCOLESTR
pwApp, LPCOLESTR pwObj)
{
METHOD_MANAGE_STATE(COffCntrDispCtrl, MyOleObject)
ASSERT_VALID(pThis); // Convert OLESTR into ASCII string. WideCharToMultiByte(CP_ACP, 0, pwObj, -1, pThis->m_szDocName,
512, NULL, NULL); // Get IDispatch.
pThis->GetDocDispatch(); // Test it out by getting the document name.
pThis->TestDispatch(); return S_OK;
} STDMETHODIMP
COffCntrDispCtrl::XMyOleObject::SetClientSite(LPOLECLIENTSITE
pClientSite)
{
METHOD_MANAGE_STATE(COffCntrDispCtrl, MyOleObject)
ASSERT_VALID(pThis);
return pThis->m_xOleObject.SetClientSite(pClientSite);
} STDMETHODIMP
COffCntrDispCtrl::XMyOleObject::SetColorScheme(LPLOGPALETTE plp)
{
METHOD_MANAGE_STATE(COffCntrDispCtrl, MyOleObject)
ASSERT_VALID(pThis);
return pThis->m_xOleObject.SetColorScheme(plp);
} STDMETHODIMP COffCntrDispCtrl::XMyOleObject::GetMiscStatus(DWORD
dwAspect, DWORD* pdwStatus)
{
METHOD_MANAGE_STATE(COffCntrDispCtrl, MyOleObject)
ASSERT_VALID(pThis);
return pThis->m_xOleObject.GetMiscStatus(dwAspect, pdwStatus);
} STDMETHODIMP
COffCntrDispCtrl::XMyOleObject::EnumAdvise(LPENUMSTATDATA*
ppenumAdvise)
{
METHOD_MANAGE_STATE(COffCntrDispCtrl, MyOleObject)
ASSERT_VALID(pThis);
return pThis->m_xOleObject.EnumAdvise(ppenumAdvise);
} STDMETHODIMP COffCntrDispCtrl::XMyOleObject::Unadvise(DWORD
dwConnection)
{
METHOD_MANAGE_STATE(COffCntrDispCtrl, MyOleObject)
ASSERT_VALID(pThis);
return pThis->m_xOleObject.Unadvise(dwConnection);
} STDMETHODIMP COffCntrDispCtrl::XMyOleObject::Advise(LPADVISESINK
pAdvSink, DWORD* pdwConnection)
{
METHOD_MANAGE_STATE(COffCntrDispCtrl, MyOleObject)
ASSERT_VALID(pThis);
return pThis->m_xOleObject.Advise(pAdvSink, pdwConnection);
} STDMETHODIMP COffCntrDispCtrl::XMyOleObject::GetExtent(DWORD
dwDrawAspect, LPSIZEL lpsizel)
{
METHOD_MANAGE_STATE(COffCntrDispCtrl, MyOleObject)
ASSERT_VALID(pThis);
return pThis->m_xOleObject.GetExtent(dwDrawAspect, lpsizel);
}
STDMETHODIMP COffCntrDispCtrl::XMyOleObject::SetExtent(DWORD
dwDrawAspect, LPSIZEL lpsizel)
{
METHOD_MANAGE_STATE(COffCntrDispCtrl, MyOleObject)
ASSERT_VALID(pThis);
return pThis->m_xOleObject.SetExtent(dwDrawAspect, lpsizel);
} STDMETHODIMP COffCntrDispCtrl::XMyOleObject::GetUserType(DWORD
dwFormOfType, LPOLESTR* ppszUserType)
{
METHOD_MANAGE_STATE(COffCntrDispCtrl, MyOleObject)
ASSERT_VALID(pThis); return pThis->m_xOleObject.GetUserType(dwFormOfType,
ppszUserType);
} STDMETHODIMP COffCntrDispCtrl::XMyOleObject::GetUserClassID(CLSID*
pClsid)
{
METHOD_MANAGE_STATE(COffCntrDispCtrl, MyOleObject)
ASSERT_VALID(pThis);
return pThis->m_xOleObject.GetUserClassID(pClsid);
} STDMETHODIMP COffCntrDispCtrl::XMyOleObject::IsUpToDate()
{
METHOD_MANAGE_STATE(COffCntrDispCtrl, MyOleObject)
ASSERT_VALID(pThis); return pThis->m_xOleObject.IsUpToDate();
} STDMETHODIMP COffCntrDispCtrl::XMyOleObject::Update()
{
METHOD_MANAGE_STATE(COffCntrDispCtrl, MyOleObject)
ASSERT_VALID(pThis);
return pThis->m_xOleObject.Update();
} STDMETHODIMP COffCntrDispCtrl::XMyOleObject::EnumVerbs(LPENUMOLEVERB*
ppenumOleVerb)
{
METHOD_MANAGE_STATE(COffCntrDispCtrl, MyOleObject)
ASSERT_VALID(pThis); return pThis->m_xOleObject.EnumVerbs(ppenumOleVerb);
} STDMETHODIMP COffCntrDispCtrl::XMyOleObject::DoVerb(LONG iVerb, LPMSG
lpmsg, LPOLECLIENTSITE pActiveSite, LONG lindex, HWND hwndParent,
LPCRECT lprcPosRect)
{
METHOD_MANAGE_STATE(COffCntrDispCtrl, MyOleObject)
ASSERT_VALID(pThis);
return pThis->m_xOleObject.DoVerb(iVerb, lpmsg, pActiveSite,
lindex, hwndParent, lprcPosRect);
} STDMETHODIMP COffCntrDispCtrl::XMyOleObject::GetClipboardData(DWORD
dwReserved, LPDATAOBJECT *ppDataObject)
{
METHOD_MANAGE_STATE(COffCntrDispCtrl, MyOleObject)
ASSERT_VALID(pThis);
return pThis->m_xOleObject.GetClipboardData(dwReserved,
ppDataObject);
} STDMETHODIMP
COffCntrDispCtrl::XMyOleObject::InitFromData(LPDATAOBJECT
pDataObject, BOOL fCreation, DWORD dwReserved)
{
METHOD_MANAGE_STATE(COffCntrDispCtrl, MyOleObject)
ASSERT_VALID(pThis);
return pThis->m_xOleObject.InitFromData(pDataObject, fCreation,
dwReserved);
} STDMETHODIMP COffCntrDispCtrl::XMyOleObject::GetMoniker(DWORD
dwAssign, DWORD dwWhichMoniker, LPMONIKER *ppmk)
{
METHOD_MANAGE_STATE(COffCntrDispCtrl, MyOleObject)
ASSERT_VALID(pThis);
return pThis->m_xOleObject.GetMoniker(dwAssign, dwWhichMoniker,
ppmk);
} STDMETHODIMP COffCntrDispCtrl::XMyOleObject::SetMoniker(DWORD
dwWhichMoniker, LPMONIKER pmk)
{
METHOD_MANAGE_STATE(COffCntrDispCtrl, MyOleObject)
ASSERT_VALID(pThis);
return pThis->m_xOleObject.SetMoniker(dwWhichMoniker, pmk);
} STDMETHODIMP COffCntrDispCtrl::XMyOleObject::Close(DWORD
dwSaveOption)
{
METHOD_MANAGE_STATE(COffCntrDispCtrl, MyOleObject)
ASSERT_VALID(pThis);
return pThis->m_xOleObject.Close(dwSaveOption);
} STDMETHODIMP
COffCntrDispCtrl::XMyOleObject::GetClientSite(LPOLECLIENTSITE*
ppClientSite)
{
METHOD_MANAGE_STATE(COffCntrDispCtrl, MyOleObject)
ASSERT_VALID(pThis);
return pThis->m_xOleObject.GetClientSite(ppClientSite); } STDMETHODIMP_(ULONG) COffCntrDispCtrl::XMyOleObject::Release()
{
METHOD_MANAGE_STATE(COffCntrDispCtrl, MyOleObject)
ASSERT_VALID(pThis);
return pThis->m_xOleObject.Release();
} STDMETHODIMP_(ULONG) COffCntrDispCtrl::XMyOleObject::AddRef()
{
METHOD_MANAGE_STATE(COffCntrDispCtrl, MyOleObject)
ASSERT_VALID(pThis);
return pThis->m_xOleObject.AddRef();
} STDMETHODIMP COffCntrDispCtrl::XMyOleObject::QueryInterface(REFIID
iid, LPVOID* ppvObj)
{
METHOD_MANAGE_STATE(COffCntrDispCtrl, MyOleObject)
ASSERT_VALID(pThis);
return pThis->m_xOleObject.QueryInterface(iid, ppvObj);
}
This is your implementation of IOleObject, which mostly delegates all of its calls to the default COleControl's IOleObject implementation, except for SetHostNames(). You trap SetHostNames() and store the document name where the control is inserted.Unfortunately, Microsoft PowerPoint doesn't call this method, so this example won't work with that product. However, Microsoft Powerpoint is a single-instance server, so you could use GetActiveObject() to uniquely get the IDispatch pointer.