接著把這個總結繼續。
執行個體
以常用的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