接着把这个总结继续。
实例
以常用的HTML文档的处理为例,深入地描述一下COM的使用,其他的类别使用类同(如Office的编程对象)
首先工程包含
#include <mshtml.h>
具体的代码如下:
//以DOM对象的形式遍历HTML文档
int WalkTree(CComPtr<IHTMLDOMNode> domNode)
{
ASSERT(domNode!=NULL);
long type;
CComBSTR tag;
if(domNode->get_nodeType(&type)==S_OK)
{
switch(type)
{
case 1://MSXML::NODE_ELEMENT:
{
// Get the element name and set the tag name...
if(SUCCEEDED(domNode->get_nodeName(&tag)) )
{
///查到 <a ... 这样的元素 if(wcscmp(tag.m_str, L"A")==0)
{
CComPtr<IDispatch> pDisp;
domNode->get_attributes(&pDisp);
CComQIPtr<IHTMLAttributeCollection, &IID_IHTMLAttributeCollection> pAttrs;
pAttrs = pDisp;
pDisp = NULL;
long l;
COleVariant index;
index.vt = VT_I4;
pAttrs->get_length(&l);
for (long i = 0; i < l; i++)
{
pDisp = NULL;
index.lVal = i;
pAttrs->item(index, &pDisp);
///查询接口 也可用 CComQIPtr
CComPtr<IHTMLDOMAttribute> phref;
if(SUCCEEDED(pDisp->QueryInterface(IID_IHTMLDOMAttribute, (void**)&phref)) )
{
VARIANT_BOOL vbSpecified;
phref->get_specified(&vbSpecified);
if(VARIANT_TRUE==vbSpecified)
{
CComBSTR text;
if(SUCCEEDED(phref->get_nodeName(&text)) )
{
///You can do...
}
COleVariant v;
if(SUCCEEDED(phref->get_nodeValue(&v)) )
{
///You can do...
}
}
}
}
}
}
CComPtr<IHTMLDOMNode> pChild;
if(domNode->get_firstChild(&pChild)==S_OK)
{
// If we have children, loop through and handle each one...
if (pChild)
{
// Recurse for all the children of this tag...
CComPtr<IHTMLDOMNode> domChild;
while (pChild)
{
WalkTree(pChild);
domChild=NULL;
domChild=pChild;
pChild=NULL;
domChild->get_nextSibling(&pChild);
}
}
}
break;
}
case 3://MSXML::NODE_TEXT:
{
COleVariant val;
if(domNode->get_nodeValue(&val)==S_OK)
{
///You can do...
}
}
break;
}
}
return 0;
}
void CBrowserDomDlg::OnBnClickedOk()
{
CComPtr<IDispatch> pDisp;
pDisp = m_Web.get_Document();
CComQIPtr<IHTMLDocument2, &IID_IHTMLDocument2> pHTML;
pHTML = pDisp;
///可以查看HTML的 title内容
CComBSTR bstrTitle;
if(pHTML!=NULL && pHTML->get_title(&bstrTitle)==S_OK)
{
//title is
}
CComPtr<IHTMLElementCollection> pElems;
HRESULT hr;
pHTML->get_all(&pElems);
if(pElems==NULL) return;
long l;
if(!SUCCEEDED(pElems->get_length(&l)) )
return;
//遍历元素找到BODY节点
CComPtr<IHTMLElement> htmlBody;
COleVariant index;
for(int i=0;i<l;i++)
{
CComPtr<IDispatch> pChild;
index.vt = VT_I4;
index.lVal = i;
hr=pElems->item(index,index ,&pChild);
htmlBody=NULL;
if(SUCCEEDED(hr) && SUCCEEDED(pChild.QueryInterface(&htmlBody)) && htmlBody!=NULL)
{
CComBSTR name;
hr=htmlBody->get_tagName(&name);
if(wcscmp(name.m_str, L"BODY")==0)
break;
}
}
if(htmlBody==NULL) return;
CComPtr<IHTMLDOMNode>pDOM;
htmlBody->QueryInterface(&pDOM);
if(pDOM==NULL) return;
WalkTree(pDOM);
}
还有我们在应用中常用的ADO数据存取的方式:
#import "C:\Program Files\common files\system\ado\msado15.dll " no_namespace rename( "EOF ", "EndOfFile ") rename( "BOF ", "FirstOfFile ")
_RecordsetPtr m_pRs;
具体的操作和以上的例子类似
部署
一般的COM组件都是C++开发的[因为现在.net提供了更好的实现形式,单纯使用COM的时机少了很多],部署时只要注意对应的MFC库和ATL库的设置即可
部署有两个形式[在项目编译选项设置]:
静态链接 |
把MFC和ATL静态链接到组件中 [减少了部署的麻烦,组件的大小比动态连接大] 如项目就一个COM组件,那这种形式最好 |
动态连接 |
此时部署有两个方法: 1、 安装对应版本的MFC和ATL发行库[VS就包含] 2、 把Microsoft.VC**.CRT Microsoft.VC**.MFC Microsoft.VC**.ATL 这些需要的目录和其中的文件放在和组件库相同的地方即可 |
全部的实例代码参见:
http://cid-56b433ad3d1871e3.office.live.com/self.aspx/.Public/ComTutorial.zip