SAMPLE: MFCDISP: Replacing MFC IDispatch ImplementationID: Q140616
|
MFCDISP demonstrates how to replace MFC's IDispatch implementation with a type-library-based IDispatch implementation that uses the OLE system API DispInvoke and DispGetIDsOfNames to implement IDispatch::Invoke and IDispatch::GetIDsOfNames.
The following file is available for download from the Microsoft Software Library:
~ Mfcdisp.exeFor more information about downloading files from the Microsoft Software Library, please see the following article in the Microsoft Knowledge Base:
Q119591 How to Obtain Microsoft Support Files from Online ServicesAfter downloading the file, use the following command to extract the sample and build the appropriate directory structure:
MFCDISP.EXE -dMFC's implementation of server OLE Automation currently has the following limitations. These limitations can be removed by replacing or modifying MFC's IDispatch implementation with a type-library-based implementation of IDispatch.
[ uuid(C04AADF0-2A82-11CF-84F5-00AA00C006CF), version(1.0), lcid(0x09)
]
library Test
{
importlib("stdole32.tlb");
[
uuid(C04AADF1-2A82-11CF-84F5-00AA00C006CF),
oleautomation,
dual
]
interface ITest : IDispatch
{
[id(1), propput] HRESULT TestProperty([in]short nNewValue);
[id(1), propget] HRESULT TestProperty([out, retval] short *retval);
[id(2)] HRESULT TestMethod([in] short n, [out,retval] short
*retval);
};
// Primary dispatch interface for CTestDoc
/* // Replace this dispinterface with a interface
[ uuid(C04AADF1-2A82-11CF-84F5-00AA00C006CF) ]
dispinterface ITest
{
properties:
// NOTE - ClassWizard will maintain property information here.
// Use extreme caution when editing this section.
//{{AFX_ODL_PROP(CTestDoc)
//}}AFX_ODL_PROP
methods:
// NOTE - ClassWizard will maintain method information here.
// Use extreme caution when editing this section.
//{{AFX_ODL_METHOD(CTestDoc)
//}}AFX_ODL_METHOD
};
*/
[ uuid(943B3F80-CD85-11CE-815A-00AA0060D733) ]
coclass CTestDoc
{
[default] interface ITest;
};
//{{AFX_APPEND_ODL}}
};
A coclass must be provided if the object is a top-level object (that
is, if the object can be created by CoCreateInstance). The UUID of the
coclass must be the CLSID of the object. The GUID generated by
AppWizard for the dispinterface can be used for the interface that
replaces it. Add a locale id for the type library (the sample uses
lcid(0x09) for English).
DECLARE_INTERFACE_MAP()
BEGIN_INTERFACE_PART(MyDispatch, ITest)
STDMETHOD(GetTypeInfoCount)(UINT FAR* pctinfo);
STDMETHOD(GetTypeInfo)(
UINT itinfo,
LCID lcid,
ITypeInfo FAR* FAR* pptinfo);
STDMETHOD(GetIDsOfNames)(
REFIID riid,
OLECHAR FAR* FAR* rgszNames,
UINT cNames,
LCID lcid,
DISPID FAR* rgdispid);
STDMETHOD(Invoke)(
DISPID dispidMember,
REFIID riid,
LCID lcid,
WORD wFlags,
DISPPARAMS FAR* pdispparams,
VARIANT FAR* pvarResult,
EXCEPINFO FAR* pexcepinfo,
UINT FAR* puArgErr);
/* ITest methods */
STDMETHOD(put_TestProperty)(short nNewValue);
STDMETHOD(get_TestProperty)(short FAR* retval);
STDMETHOD(TestMethod)(short n, short FAR* retval);
END_INTERFACE_PART(MyDispatch)
Add a private class member to the object's class to hold the typeinfo
of the interface:
private:
LPTYPEINFO m_ptinfo; // ITest type information
BEGIN_INTERFACE_MAP(CTestDoc, CDocument)
INTERFACE_PART(CTestDoc, IID_IDispatch, MyDispatch)
INTERFACE_PART(CTestDoc, IID_ITest, MyDispatch)
END_INTERFACE_MAP()
Remove the interface map inserted by AppWizard. For example, the
sample removes the following interface map from Testdoc.cpp:
BEGIN_INTERFACE_MAP(CTestDoc, CDocument)
INTERFACE_PART(CTestDoc, IID_ITest, Dispatch)
END_INTERFACE_MAP()
static const IID IID_ITest =
{0xc04aadf1, 0x2a82, 0x11cf, { 0x84, 0xf5, 0x0, 0xaa, 0x0, 0xc0,
0x6, 0xcf } };
BOOL CTestDoc::OnNewDocument()
{
HRESULT hr;
LPTYPELIB ptlib;
if (!CDocument::OnNewDocument())
return FALSE;
hr = LoadRegTypeLib(LIBID_Test, 1, 0, 0x09, &ptlib);
if (FAILED(hr))
{
AfxMessageBox("Can't find type library test.tlb. Re-register \
by running test.exe");
return FALSE;
}
hr = ptlib->GetTypeInfoOfGuid(IID_ITest, &m_ptinfo);
if (FAILED(hr))
{
ptlib->Release();
return FALSE;
}
ptlib->Release();
return TRUE;
}
CTestDoc::~CTestDoc()
{
m_ptinfo->Release();
AfxOleUnlockApp();
}
ULONG FAR EXPORT CTestDoc::XMyDispatch::AddRef()
{
METHOD_PROLOGUE(CTestDoc, MyDispatch)
return pThis->ExternalAddRef();
}
ULONG FAR EXPORT CTestDoc::XMyDispatch::Release()
{
METHOD_PROLOGUE(CTestDoc, MyDispatch)
return pThis->ExternalRelease();
}
STDMETHODIMP CTestDoc::XMyDispatch::QueryInterface(REFIID riid,
LPVOID FAR* ppvObj)
{
METHOD_PROLOGUE(CTestDoc, MyDispatch)
return (HRESULT)pThis->ExternalQueryInterface(&riid, ppvObj);
}
STDMETHODIMP
CTestDoc::XMyDispatch::GetTypeInfoCount(UINT FAR* pctinfo)
{
METHOD_PROLOGUE(CTestDoc, MyDispatch)
*pctinfo = 1;
return NOERROR;
}
STDMETHODIMP CTestDoc::XMyDispatch::GetTypeInfo(
UINT itinfo,
LCID lcid,
ITypeInfo FAR* FAR* pptinfo)
{
METHOD_PROLOGUE(CTestDoc, MyDispatch)
*pptinfo = NULL;
if(itinfo != 0)
return ResultFromScode(DISP_E_BADINDEX);
pThis->m_ptinfo->AddRef();
*pptinfo = pThis->m_ptinfo;
return NOERROR;
}
STDMETHODIMP CTestDoc::XMyDispatch::GetIDsOfNames(
REFIID riid,
OLECHAR FAR* FAR* rgszNames,
UINT cNames,
LCID lcid,
DISPID FAR* rgdispid)
{
METHOD_PROLOGUE(CTestDoc, MyDispatch)
return DispGetIDsOfNames(pThis->m_ptinfo, rgszNames, cNames,
rgdispid);
}
STDMETHODIMP CTestDoc::XMyDispatch::Invoke(
DISPID dispidMember,
REFIID riid,
LCID lcid,
WORD wFlags,
DISPPARAMS FAR* pdispparams,
VARIANT FAR* pvarResult,
EXCEPINFO FAR* pexcepinfo,
UINT FAR* puArgErr)
{
METHOD_PROLOGUE(CTestDoc, MyDispatch)
return DispInvoke(
&pThis->m_xMyDispatch, pThis->m_ptinfo,
dispidMember, wFlags, pdispparams,
pvarResult, pexcepinfo, puArgErr);
}
STDMETHODIMP CTestDoc::XMyDispatch::get_TestProperty(short
*pnRetVal)
{
METHOD_PROLOGUE(CTestDoc, MyDispatch)
*pnRetVal = pThis->m_nTestProperty;
return NOERROR;
}
STDMETHODIMP CTestDoc::XMyDispatch::put_TestProperty(short
nNewValue)
{
METHOD_PROLOGUE(CTestDoc, MyDispatch)
pThis->m_nTestProperty = nNewValue;
return NOERROR;
}
STDMETHODIMP CTestDoc::XMyDispatch::TestMethod(short n, short
*pnRetVal)
{
*pnRetVal = n;
return NOERROR;
}
// Register type library and the interfaces in it
AfxOleRegisterTypeLib(AfxGetInstanceHandle(), LIBID_Test,
_T("test.TLB"));
Dim o As Object
Set o = CreateObject("Test.Document")
Value = o.TestProperty
o.TestProperty = Value
Value = o.TestMethod(99)
vbvtbl.vbp, vbvtbl.frm uses vtbl-binding (ITest) to control the server
using code similar to the following. Use the Tools/References menu in VB
to select the server's type library (Test) before executing this code.
Dim o As ITest
Set o = New CTestDoc 'Use the name of the coclass
Value = o.TestProperty
o.TestProperty = Value
Value = o.TestMethod(99)
Q139073 How To Fill EXCEPINFO in IDispatch Implementation
Additional query words: override
Keywords : kbcode kbfile kbsample kbMFC kbVC400 kbVC500 kbVC600 LeTwoAt
Version : 3.51 4.0 5.0 6.0
Platform : NT WINDOWS
Issue type :
Last Reviewed: July 15, 1999