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