ActiveX控件的MFC设计之旅 联系客服

发布时间 : 星期四 文章ActiveX控件的MFC设计之旅更新完毕开始阅读0008256ca98271fe910ef902

}

//这三个函数是新添加的接口实现的函数,一般实现还是调用原接口的函数,这里加上一个描述,表示是从vtable中调用的。

STDMETHODIMP CTDualCtrl::XTDual::put_Hello(BSTR newText) {

METHOD_PROLOGUE(CTDualCtrl, TDual)

// MFC automatically converts from Unicode BSTR to // Ansi CString, if necessary... CString str = newText;

pThis->m_hello = \ pThis->OnHelloChanged(); return NOERROR; }

STDMETHODIMP CTDualCtrl::XTDual::get_Hello(BSTR* ret) {

METHOD_PROLOGUE(CTDualCtrl, TDual)

// MFC automatically converts from Ansi CString to // Unicode BSTR, if necessary... pThis->m_hello.SetSysString(ret); return NOERROR; }

STDMETHODIMP CTDualCtrl::XTDual::SayHello(BSTR strHello) {

METHOD_PROLOGUE(CTDualCtrl, TDual)

// MFC automatically converts from Ansi CString to // Unicode BSTR, if necessary... CString str = strHello;

str = \ pThis->SayHello(str); return NOERROR; }

4.连接新的接口到MFC的QueryInterface接口表机制,使能够通过QueryInterface获得ITDual接口。

在.h 中添加 public:

///////////////////////////////////////////////////////////////////////////// // Double Interface Part

DECLARE_INTERFACE_MAP()

BEGIN_DUAL_INTERFACE_PART(TDual, ITDual)

STDMETHOD(put_Hello)(THIS_ BSTR newText); STDMETHOD(get_Hello)(THIS_ BSTR FAR* ret); STDMETHOD(SayHello)(THIS_ BSTR strHello); END_DUAL_INTERFACE_PART(TDual)

在.cpp中添加

///////////////////////////////////////////////////////////////////////////// // Event map

BEGIN_EVENT_MAP(CTDualCtrl, COleControl) //{{AFX_EVENT_MAP(CTDualCtrl)

// NOTE - ClassWizard will add and remove event map entries

// DO NOT EDIT what you see in these blocks of generated code ! //}}AFX_EVENT_MAP END_EVENT_MAP()

//将新的接口连接到QueryInterface机制

BEGIN_INTERFACE_MAP(CTDualCtrl, COleControl)

INTERFACE_PART(CTDualCtrl, IID_IDispatch, Dispatch) INTERFACE_PART(CTDualCtrl, DIID__DTDual, Dispatch) INTERFACE_PART(CTDualCtrl, IID_ITDual, TDual) END_INTERFACE_MAP()

5.这时编译的话,会提示错误,因为没有ITDual接口声明和一些IID的定义。点击TDual.odl右键,弹出设置菜单,选择 Setting菜单项,在Output header file name中键入你想要输出的接口.h文件名,这里用的是ITDual.h,然后将ITDual.h包括在stdafx.h中,以便可以在各处用到。

接下来新建一个initIIDs.cpp文件,加上下面代码 #include #include #include \

这个initIIDs.cpp没什么用处,只是用来实现要用到的几个IID的,不过要在Project-Setting中把 initIIDs.cpp的Precompiled Headers设置为Not using precompiled headers。 编译一下TDual.odl,OK了

6.添加异常处理和自动化错误接口,这部分本例未提供,有兴趣的可以参考acdual例子。

7.新建一个普通的MFC对话框exe工程testdual,在工程中引入TDual.ocx,这里用的方法是在stdafx.h中加入#import \。

为CTestdualDlg添加成员变量CWnd m_wnd,响应WM_CREATE消息,添加如下代码 CRect rect(10, 10, 100, 100);

BOOL b = m_wnd.CreateControl(__uuidof( TDual ), NULL, WS_CHILD | WS_VISIBLE, rect, this, 1);

if(!b){

AfxMessageBox(\ return 0; }

LPUNKNOWN pukn = m_wnd.GetControlUnknown(); if(!pukn){

AfxMessageBox(\ return 0;

}

ITDual* pdual = NULL;

pukn->QueryInterface(__uuidof(ITDual), (void**)&pdual); if(!pdual){

AfxMessageBox(\ return 0; }

CString str = \

pdual->SayHello(str.AllocSysString()); pdual->put_Hello(str.AllocSysString()); pdual->Release();

编译运行,具体结果就不说了,一看便知。

因为本文主要讲述如何做,至于为什么要如此做就不说了,有兴趣的朋友可以自己研究,这里提供几个网址,仅供参考

http://www.microsoft.com/china/m ... /visualc/atlmfc.asp

http://blog.csdn.net/RedStar81/archive/2003/04/03/19761.aspx

下面是acdual例子中的一些宏定义代码

#define BEGIN_DUAL_INTERFACE_PART(localClass, baseClass) \\ BEGIN_INTERFACE_PART(localClass, baseClass) \\

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); \\

///////////////////////////////////////////////////////////////////// // END_DUAL_INTERFACE_PART is just like END_INTERFACE_PART. It // is only added for symmetry...

#define END_DUAL_INTERFACE_PART(localClass) \\ END_INTERFACE_PART(localClass) \\

/////////////////////////////////////////////////////////////////////

// DELEGATE_DUAL_INTERFACE expands to define the standard IDispatch // methods for a dual interface, delegating back to the default // MFC implementation

#define DELEGATE_DUAL_INTERFACE(objectClass, dualClass) \\

STDMETHODIMP_(ULONG) objectClass::X##dualClass::AddRef() \\ { \\

METHOD_PROLOGUE(objectClass, dualClass) \\ return pThis->ExternalAddRef(); \\ } \\

STDMETHODIMP_(ULONG) objectClass::X##dualClass::Release() \\

{ \\

METHOD_PROLOGUE(objectClass, dualClass) \\ return pThis->ExternalRelease(); \\ } \\

STDMETHODIMP objectClass::X##dualClass::QueryInterface( \\ REFIID iid, LPVOID* ppvObj) \\ { \\

METHOD_PROLOGUE(objectClass, dualClass) \\

return pThis->ExternalQueryInterface(&iid, ppvObj); \\ } \\

STDMETHODIMP objectClass::X##dualClass::GetTypeInfoCount( \\ UINT FAR* pctinfo) \\ { \\

METHOD_PROLOGUE(objectClass, dualClass) \\

LPDISPATCH lpDispatch = pThis->GetIDispatch(FALSE); \\ ASSERT(lpDispatch != NULL); \\

return lpDispatch->GetTypeInfoCount(pctinfo); \\ } \\

STDMETHODIMP objectClass::X##dualClass::GetTypeInfo( \\ UINT itinfo, LCID lcid, ITypeInfo FAR* FAR* pptinfo) \\ { \\

METHOD_PROLOGUE(objectClass, dualClass) \\

LPDISPATCH lpDispatch = pThis->GetIDispatch(FALSE); \\ ASSERT(lpDispatch != NULL); \\

return lpDispatch->GetTypeInfo(itinfo, lcid, pptinfo); \\ } \\

STDMETHODIMP objectClass::X##dualClass::GetIDsOfNames( \\ REFIID riid, OLECHAR FAR* FAR* rgszNames, UINT cNames, \\ LCID lcid, DISPID FAR* rgdispid) \\ { \\

METHOD_PROLOGUE(objectClass, dualClass) \\

LPDISPATCH lpDispatch = pThis->GetIDispatch(FALSE); \\ ASSERT(lpDispatch != NULL); \\

return lpDispatch->GetIDsOfNames(riid, rgszNames, cNames, \\ lcid, rgdispid); \\ } \\

STDMETHODIMP objectClass::X##dualClass::Invoke( \\

DISPID dispidMember, REFIID riid, LCID lcid, WORD wFlags, \\ DISPPARAMS FAR* pdispparams, VARIANT FAR* pvarResult, \\ EXCEPINFO FAR* pexcepinfo, UINT FAR* puArgErr) \\ { \\

METHOD_PROLOGUE(objectClass, dualClass) \\

LPDISPATCH lpDispatch = pThis->GetIDispatch(FALSE); \\ ASSERT(lpDispatch != NULL); \\