MFC----ATL IDispatch调度接口
概述
IDispatch接口:完成接口调度的接口,可以不使用头文件完成接口的函数调用
IDispatch 接口函数
- 1> GetIDsOfNames-根据接口函数的名称获取接口函数的ID
- 2> Invoke-根据接口函数ID,调用接口函数
- 3>GetTypeInfo-获取指定的类型信息接口
- 4>GetTypeInfoCount-获取指定类型信息接口的数量
IDispatch项目
创建项目: 增加组件和接口时,要选择“dual”,增加IDispatch接口的支持
项目变化
- 文件的变化;接口的父接口,是IDispatch接口;当添加接口函数时,会自动添加接口函数的ID
- 组件的实现类:父类增加了IDispathImpl
GetIDsOfNames函数 HRESULT GetIDsOfNames( REFIID riid, //保留值,IID_NULL OLECHAR FAR *FAR *rgszNames,//接口函数名字符串数组 unsigned int cNames, //数组长度 LCID lcid, //语言ID ,LOCALE_SYSTEM_DEFAULT DISPID FAR *rgDispId //返回查询到的接口函数的ID号数组 ); Invoke函数 HRESULT Invoke( DISPID dispIdMember,//接口函数的ID REFIID riid, //保留参数,IID_NULL LCID lcid, //语言ID WORD wFlags, //接口函数的类型 DISPPARAMS FAR *pDispParams, //函数的参数 VARIANT FAR *pVarResult, //函数的返回值 EXCEPINFO FAR *pExcepInfo, //异常信息 unsigned int FAR *puArgErr//错误代码 );
实例
一创建ATL项目ATLDIsp
1.新建ATL项目ATLDisp:下一步-->应用程序类型:动态链接库DLL;支持选项:支持COM+1.0,支持部件注册器-->完成。
2.添加MyMath类:右击--添加--类-->选择ATLCOM+1.0组件-->简称:MyMath;别的默认;COM ProgID:ATLDisp-->下一步,完成。
3.添加接口方法Add()和ShowMsg():在类视图中,右击IMyMath接口,选择 添加---方法 -->方法名:Add,参数特性 [id(1)] HRESULT Add([in] int nAdd1, [in] int nAdd2, [out,retval] int* nResult); [id(2)] HRESULT ShowMsg(void);
4.添加Add()方法的实现:在MyMath.cpp中添加:
STDMETHODIMP CMyMath::Add(int nAdd1, int nAdd2, int* nResult) { *nResult=nAdd1+nAdd2; return S_OK; } STDMETHODIMP CMyMath::ShowMsg(void) { MessageBox(NULL,L"Hello Dispatch!!!",L"ATLDisp",MB_OK); return S_OK; }
二创建MFCDialog的UseATLDisp项目
1.在用一个解决方案中创建MFC dialog UseATLDisp项目
2.在UseATLDisp.cpp中:
BOOL CUseATLDispApp::InitInstance() { CoInitialize(0); // 现在初始化COM ... return FALSE; } int CUseATLDispApp::ExitInstance() { CoUninitialize();// 卸载COM return CWinApp::ExitInstance(); }
3.按钮代码
3.按钮代码3.按钮代码
IDispatch* CUseATLDispDlg::GetDispatch() { CLSID clsid={0}; CLSIDFromProgID(L"ATLDisp",&clsid);//根据ProgID获取classID IDispatch* piDispatch=NULL; CoCreateInstance(clsid,NULL,CLSCTX_SERVER,IID_IDispatch,(LPVOID*)&piDispatch);//创建组件并返回IDispatch接口 if (piDispatch==NULL) { AfxMessageBox(L"创建IDispatch接口失败"); } return piDispatch; } //根据接口函数的名称获取接口函数的ID void CUseATLDispDlg::OnBnClickedButtonGetidsofnames() { IDispatch* piDispatch=GetDispatch(); WCHAR* pszName=L"ShowMsg";//Add DISPID nID={0}; piDispatch->GetIDsOfNames(IID_NULL,&pszName,1,LOCALE_SYSTEM_DEFAULT,&nID); CString strID; strID.Format(L"nID=%d",nID); MessageBox(strID);//Add 1; ShowMsg 2 } //不带参数 void CUseATLDispDlg::OnBnClickedButtonNoparam() { IDispatch* piDispatch=GetDispatch(); WCHAR* pszName=L"ShowMsg"; DISPID nID={0}; piDispatch->GetIDsOfNames(IID_NULL,&pszName,1,LOCALE_SYSTEM_DEFAULT,&nID); //使用Invoke调用函数,参数和返回值 DISPPARAMS params={0}; VARIANT varResult={0}; piDispatch->Invoke(nID,IID_NULL,LOCALE_SYSTEM_DEFAULT,DISPATCH_METHOD,¶ms,&varResult,NULL,NULL); } //带参数 void CUseATLDispDlg::OnBnClickedButtonparams() { IDispatch* piDispatch=GetDispatch(); WCHAR* pszName=L"Add"; DISPID nID={0}; piDispatch->GetIDsOfNames(IID_NULL,&pszName,1,LOCALE_SYSTEM_DEFAULT,&nID); //使用Invoke调用函数,构造参数和返回值 VARIANT varResult={0}; DISPPARAMS params={0}; VARIANT varParam[3]={0}; params.cArgs=3; params.rgvarg=varParam; //参数的顺序从右向左 //第一个参数 long nValue=0; varParam[0].vt=VT_I4|VT_BYREF; varParam[0].plVal=&nValue; //第二个参数 varParam[1].vt=VT_I4; varParam[1].lVal=100; //第三个参数 varParam[2].vt=VT_I4; varParam[2].lVal=100; //调用函数 piDispatch->Invoke(nID,IID_NULL,LOCALE_SYSTEM_DEFAULT,DISPATCH_METHOD,¶ms,&varResult,NULL,NULL); CString strValue; strValue.Format(L"nResult:%d",nValue); MessageBox(strValue);//输出结果 }
4.界面