本站首页    管理页面    写新日志    退出


«may 2026»
12
3456789
10111213141516
17181920212223
24252627282930
31


公告
暂无公告...

我的分类(专题)

日志更新

最新评论

留言板

链接

Blog信息
blog名称:
日志总数:2
评论数量:0
留言数量:0
访问次数:17982
建立时间:2005年3月12日




[ASP开发]在VC++6.0中用MFC进行COM编程
电脑与网络

wantstudio 发表于 2005/4/13 8:39:31

首先应当明确,MFC中是通过嵌套类而不是多重继承来实现COM接口的,通过接口映射机制将接口和实现该接口的嵌套类关联起来;MFC中提供一套简明的宏来实现嵌套类的定义.其次,MFC通过CCmdTarget类实现了IUnknown接口。   本文首先描述创建一个COM服务器的步骤和核心代码.然后说明客户程序关键代码。  此COM服务器实现一个TimeLogServer组件,为简明起见,此组件只有一个接口ITimeLog,通过ITimeLog的方法OutputLog可以将日志文本输出至日志文件。  创建一个MFC DLL工程,选择支持Automation(当然本程序不一定是自动化服务器,在这里这样做好处在于自动实现了几个必要的输出函数如DllGetClassObject,DllRegisterServer等,否则要自己写)   第一节 COM服务器   一. 声明组件和接口   1.写一个GUIDs.h,在GUIDs.h中声明组件和接口的GUID //声明组件GUID {A433E701-E45E-11d3-97B5-52544CBA7F28}//DEFINE_GUID(CLSID_TimeLogServer, //0xa433e701, 0xe45e, 0x11d3, 0x97, 0xb5, 0x52, 0x54, 0x4c, 0xba, 0x7f, 0x28);static const IID CLSID_TimeLogServer = {0xa433e701, 0xe45e, 0x11d3, {0x97, 0xb5, 0x52, 0x54, 0x4c, 0xba, 0x7f, 0x28}};// 声明接口GUID{A433E702-E45E-11d3-97B5-52544CBA7F28}//DEFINE_GUID(IID_ITimeLog,//0xa433e702, 0xe45e, 0x11d3, 0x97, 0xb5, 0x52, 0x54, 0x4c, 0xba, 0x7f, 0x28);static const IID IID_ITimeLog = {0xa433e702, 0xe45e, 0x11d3, {0x97, 0xb5, 0x52, 0x54, 0x4c, 0xba, 0x7f, 0x28}};   2.写一个ITimeLogServer.h,在ITimeLogServer.h文件中声明组件和接口 //ITimeLogServer.h#include ";GUIDs.h";//接口ITimeLog的声明DECLARE_INTERFACE_(ITimeLog,IUnknown){    STDMETHOD(OutputLog)(BSTR* varLogText)PURE;};   说明:  1.宏DEFINE_GUID将组件和接口的progid与GUID相关联.可以用guidgen.exe工具产生。  2.宏DECLARE_INTERFACE_声明接口;该宏第一个参数为接口名,第二个参数为该接口的基类.声明没有基类的接口用DECLARE_INTERFACE宏。  3.宏STDMETHOD声明接口中的方法.此方法的返回值为HRESULT.PURE被解释为";=0";,即此方法为纯虚函数.当方法的返回值不是HRESULT时,用宏STDMETHOD_(返回类型,函数名)(参数)PURE; 二.声明组件类CTimeLogServer和实现接口的嵌套类   在ClassWizard中添加新类CTimeLogServer,其基类选择为CCmdTarget.修改其头文件TimeLogServer1.h,加上#include ";ITimeLogServer.h";;同时在类声明体中加上 //声明实现ITimelog接口的嵌套类    BEGIN_INTERFACE_PART(TimeLog,ITimeLog)//自动声明IUnknown接口的三个方法    STDMETHOD(OutputLog)(BSTR* varLogText);    END_INTERFACE_PART(TimeLog)    //声明接口映射    DECLARE_INTERFACE_MAP()    //声明类厂    DECLARE_OLECREATE(CTimeLogServer)   三.实现类厂和接口映射   在CTimeLogServer的实现文件中写入: //实现类厂IMPLEMENT_OLECREATE(CTimeLogServer,";TimeLogServer";,0xa433e701, 0xe45e, 0x11d3, 0x97, 0xb5, 0x52, 0x54, 0x4c, 0xba, 0x7f, 0x28);//映射接口到相应的嵌套类BEGIN_INTERFACE_MAP(CTimeLogServer,CCmdTarget)INTERFACE_PART(CTimeLogServer,IID_ITimeLog,TimeLog)END_INTERFACE_MAP()   四.在组件的构造和析构函数中对全局对象计数CTimeLogServer::CTimeLogServer(){    ::AfxOleLockApp();}CTimeLogServer::~CTimeLogServer(){    ::AfxOleUnlockApp();}  五.为嵌套类实现IUnknown接口 //为嵌套类而实现IUnknown接口 STDMETHODIMP_(ULONG)CTimeLogServer::XTimeLog::AddRef(){    METHOD_PROLOGUE(CTimeLogServer,TimeLog)    return pThis->;ExternalAddRef();}STDMETHODIMP_(ULONG)CTimeLogServer::XTimeLog::Release(){    METHOD_PROLOGUE(CTimeLogServer,TimeLog)    return pThis->;ExternalRelease();}STDMETHODIMPCTimeLogServer::XTimeLog::QueryInterface(REFIID riid,void**ppvObj){    METHOD_PROLOGUE(CTimeLogServer,TimeLog)    return pThis->;ExternalQueryInterface(&;riid,ppvObj);}  说明:虽然CCmdTarget类已经实现了IUnknown接口,但是还必须通过上述代码来将嵌套类的IUnknown映射到CCmdTarget支持的IUnknown接口.METHOD_PROLOGUEH宏的两个参数分别是实现组件对象的类和实现接口的嵌套类。六.实现ItimeLog接口的方法OutputLog   注意本组件的功能是往日志文件中输入日志.   1. 在组件类中添加一个文件指针:  // Attributes public: protected:      FILE* m_logfile;   2. 初始化和退出   首先在CTimeLogServer的构造函数中进行一些初始化: CTimeLogServer::CTimeLogServer(){    ::AfxOleLockApp();    CTime TimeStamp = CTime::GetCurrentTime();    CString FileName;    FileName.Format(_T(";%s.log";),TimeStamp.Format(";%Y%m%d";));    m_logfile = fopen(FileName,_T(";a";));    if(m_logfile)    {        fprintf(m_logfile,_T(";# # # # # # # # # # # # # # # # # \n";));        fprintf(m_logfile,_T(";开始于:%s";),(LPCTSTR)TimeStamp.Format(";%Y年%m月%d日%H:%M %S";));        fprintf(m_logfile,_T(";\n";));    }}//然后在析构函数中关闭文件CTimeLogServer::~CTimeLogServer(){    ::AfxOleUnlockApp();    if(m_logfile)    {        CTime TimeStamp = CTime::GetCurrentTime();        fprintf(m_logfile,_T(";\n";));        fprintf(m_logfile,_T(";结束于:%s";),(LPCTSTR)TimeStamp.Format(";%Y年%m月%d日%H:%M %S";));    fprintf(m_logfile,_T(";\n";));        fprintf(m_logfile,_T(";# # # # # # # # # # # # # # # # #\n";));        fclose(m_logfile);    }}   3. 实现接口ITimeLog方法 //实现接口ITimeLog方法STDMETHODIMPCTimeLogServer::XTimeLog::OutputLog(BSTR* varLogText){    METHOD_PROLOGUE(CTimeLogServer,TimeLog)    if(pThis->;m_logfile)    {        CTime TimeStamp = CTime::GetCurrentTime();        CString NowTime = TimeStamp.Format(";%Y年%m月%d日%H:%M:%S";);        CString LogText((LPCWSTR)*varLogText);fprintf(pThis->;m_logfile,";\n%s\n%s\n%";,NowTime,LogText);        return NOERROR;    }    else    {AfxMessageBox(";没有日志文件!";);        return S_FALSE;    }}   七.完善组件服务器   在应用对象CTimeLogServerApp的 实现文件中,处理Instance()和ExitInstance() BOOL CTimeLogServerApp::InitInstance(){    ::AfxOleLockApp();    // Register all OLE server (factories) as running. This enables the    // OLE libraries to create objects from other applications.    COleObjectFactory::RegisterAll();    return TRUE;}int CTimeLogServerApp::ExitInstance() {    // TODO: Add your specialized code here and/or call the base class  ::AfxOleUnlockApp();     return CWinApp::ExitInstance();}  第二节 客户程序   使用COM组件服务器的客户程序关键步骤是:初始化COM库,创建组件对象并获取IUnknown接口指针,查询接口并使用,释放组件。  #include ";ITimeLogServer.h";  //初始化COM库,对组件实例化    HRESULT hResult;  IUnknown* pIUnknown;    hResult = ::CoInitialize(NULL);    if(FAILED(hResult))    {        ::AfxMessageBox(";不能初始化COM库!";);        return FALSE;    }  //创建组件实例  pIUnknown = NULL;    hResult = ::CoCreateInstance(CLSID_TimeLogServer,NULL,        CLSCTX_INPROC_SERVER,IID_IUnknown,(void**)&;pIUnknown);    if(FAILED(hResult))    {        pIUnknown = NULL;        ::AfxMessageBox(";不能创建TimeLog对象!";);        return FALSE;    }  //查询接口并使用  if(pIUnknown!=NULL)        {            ITimeLog* pITimeLog;HResult=pIUnknown->;QueryInterface(IID_ITimeLog,(void**)&;pITimeLog);            if(FAILED(hResult))            {            ::AfxMessageBox(";不能获取接口ITimeLog!";);                pIUnknown->;Release();                return;            }            BSTR bstrLogText;            bstrLogText = m_logtext.AllocSysString();            CString text((LPCWSTR)bstrLogText);            ::AfxMessageBox(text);            if(FAILED(pITimeLog->;OutputLog(&;bstrLogText)))            {                ::AfxMessageBox(";日志输出出错!";);                pITimeLog->;Release();                return;            }            pITimeLog->;Release();            ::AfxMessageBox(";日志已经写入!";);        }    //释放组件    pIUnknown->;Release();    pIUnknown = NULL;      ::CoUninitialize();


阅读全文(1177) | 回复(0) | 编辑 | 精华
 



发表评论:
昵称:
密码:
主页:
标题:
验证码:  (不区分大小写,请仔细填写,输错需重写评论内容!)



站点首页 | 联系我们 | 博客注册 | 博客登陆

Sponsored By W3CHINA
W3CHINA Blog 0.8 Processed in 1.095 second(s), page refreshed 144825317 times.
《全国人大常委会关于维护互联网安全的决定》  《计算机信息网络国际联网安全保护管理办法》
苏ICP备05006046号