Article ID: 190985
Article Last Modified on 3/30/2007
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.
// 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;
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.
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.
void COffCntrDispCtrl::GetDocDispatch()
{
// No need, if we already have it.
if(m_pDocDisp != NULL) return;
// Get a BindCtx.
IBindCtx *pbc;
HRESULT hr = CreateBindCtx(0, &pbc);
if(FAILED(hr)) {
DoErr("CreateBindCtx()", hr);
return;
}
// Get running-object table.
IRunningObjectTable *prot;
hr = pbc->GetRunningObjectTable(&prot);
if(FAILED(hr)) {
DoErr("GetRunningObjectTable()", hr);
pbc->Release();
return;
}
// Get enumeration interface.
IEnumMoniker *pem;
hr = prot->EnumRunning(&pem);
if(FAILED(hr)) {
DoErr("EnumRunning()", hr);
prot->Release();
pbc->Release();
return;
}
// Start at the beginning.
pem->Reset();
// Churn through enumeration.
ULONG fetched;
IMoniker *pmon;
int n = 0;
while(pem->Next(1, &pmon, &fetched) == S_OK) {
// Get DisplayName.
LPOLESTR pName;
pmon->GetDisplayName(pbc, NULL, &pName);
// Convert it to ASCII.
char szName[512];
WideCharToMultiByte(CP_ACP, 0, pName, -1, szName, 512, NULL,
NULL);
// Compare it against the name we got in SetHostNames().
if(!strcmp(szName, m_szDocName)) {
DoMsg("Found document in ROT!");
// Bind to this ROT entry.
IDispatch *pDisp;
hr = pmon->BindToObject(pbc, NULL, IID_IDispatch, (void
**)&pDisp);
if(!FAILED(hr)) {
// Remember IDispatch.
m_pDocDisp = pDisp;
// Notice...
sprintf(buf, "Document IDispatch = %08lx",
m_pDocDisp);
DoMsg(buf);
}
else {
DoErr("BindToObject()", hr);
}
}
// Release interfaces.
pmon->Release();
// Break out if we obtained the IDispatch successfully.
if(m_pDocDisp != NULL) break;
}
// Release interfaces.
pem->Release();
prot->Release();
pbc->Release();
}
void COffCntrDispCtrl::TestDispatch()
{
ASSERT(m_pDocDisp);
COleDispatchDriver doc(m_pDocDisp);
DISPID dispID = 0;
unsigned short *ucPtr = L"Name";
// Get DISPID for Name.
HRESULT hr = m_pDocDisp->GetIDsOfNames(IID_NULL, &ucPtr, 1,
LOCALE_USER_DEFAULT, &dispID);
ASSERT(!FAILED(hr));
// Get Name property.
CString name;
doc.GetProperty(dispID, VT_BSTR, &name);
AfxMessageBox(
CString("Document name is ") + name,
MB_SETFOREGROUND
);
}
Additional query words: getobject XL2007
Keywords: kbautomation kbhowto KB190985