用过IE开发工具条的朋友对IE这个工具进行枚举的方式都会有些好奇,它是如何将一个网页中所有的元素都枚举出来的,在网页上,可能大家都学过通过JAVASCRIPT访问DOM对象来取得数据,其实在BHO中是相似的,只是要注意一些事项。
首先,我们肯定是已经定义了一个
CComQIPtr<IWebBrowser2, &IID_IWebBrowser2> m_spWebBrowser2;
而且通过SetSite方法已经将其与IE进行挂接,如果你不清楚这一点,可以在网上查找一篇文章《VC++开发BHO插件——定制你的浏览器》
其次,我们新建一个Dialog,并在其上放置一个 TreeViewCtrl,其ID为IDC_TREE1
接下来我们就可以通过 m_spWebBrowser2这个成员变量来获取数据了。
代码
代码
通过上面的代码,我们就可以将整个HTML的内容生成一个DOM结构放在一个树里面,并且每个节点中都存放了一个IHTMLElement的指针,通过它我们可以做更多的事。
代码
代码
//我们还可以像IE开发工具条一样,点击某一个节点,在IE上面高亮显示
bool HTMLElementRect(IHTMLElement *pElement, RECT &rect)
{
memset(&rect,0, sizeof(rect));
if( pElement==NULL )
return false;
pElement->get_offsetWidth(&rect.right);
pElement->get_offsetHeight(&rect.bottom);
IHTMLElement *pParentElement= NULL, *pTemp;
pParentElement = pElement;
pParentElement->AddRef();
long lx=0, ly=0;
do
{
pParentElement->get_offsetTop(&ly);
pParentElement->get_offsetLeft(&lx);
rect.left += lx;
rect.top += ly;
CComQIPtr<IHTMLElement2> pElement2 = pParentElement;
pElement2->get_scrollLeft(&lx);
pElement2->get_scrollTop(&ly);
rect.left -= lx;
rect.top -= ly;
pParentElement->get_parentElement(&pTemp);
pParentElement->Release();
pParentElement = pTemp;
} while (pParentElement);
return true;
}
void CHTMLCodeDlg::FocusElement()
{
// TODO : Add Code for control notification handler.
WTL::CTreeViewCtrlEx ctrl = GetDlgItem(IDC_TREE1);
CTreeItem item = ctrl.GetSelectedItem();
IHTMLElement *pItem = (IHTMLElement *)item.GetData();
RECT rect;
HTMLElementRect(pItem, rect);
long nBrowser = 0;
m_pParent->m_spWebBrowser2->get_HWND(&nBrowser);
HWND hWndParent = (HWND)nBrowser;
hWndParent = FindWindowEx(hWndParent, NULL, "Shell DocObject View", NULL);
if (hWndParent)
{
hWndParent = FindWindowEx(hWndParent, NULL, "Internet Explorer_Server", NULL);
}
//得到IE的节点。仅针对IE6
HDC hdc = ::GetDC(hWndParent);
HBRUSH hBrush;
hBrush = CreateSolidBrush(RGB(255,0,0));
CBrush pBrush((HBRUSH)GetStockObject(NULL_BRUSH));
SelectObject(hdc, CreatePen(PS_DASHDOTDOT, 1, RGB(0, 0, 255)));
SelectObject(hdc,GetStockObject(NULL_BRUSH));
{
::Rectangle(hdc, rect.left, rect.top, rect.left + rect.right, rect.top + rect.bottom);
Sleep(400);
SetROP2(hdc,R2_NOTXORPEN);
::Rectangle(hdc, rect.left, rect.top, rect.left + rect.right, rect.top + rect.bottom);
SetROP2(hdc,R2_NOTXORPEN);
}
::DeleteObject(hBrush);
::ReleaseDC(hWndParent, hdc);
}
bool HTMLElementRect(IHTMLElement *pElement, RECT &rect)
{
memset(&rect,0, sizeof(rect));
if( pElement==NULL )
return false;
pElement->get_offsetWidth(&rect.right);
pElement->get_offsetHeight(&rect.bottom);
IHTMLElement *pParentElement= NULL, *pTemp;
pParentElement = pElement;
pParentElement->AddRef();
long lx=0, ly=0;
do
{
pParentElement->get_offsetTop(&ly);
pParentElement->get_offsetLeft(&lx);
rect.left += lx;
rect.top += ly;
CComQIPtr<IHTMLElement2> pElement2 = pParentElement;
pElement2->get_scrollLeft(&lx);
pElement2->get_scrollTop(&ly);
rect.left -= lx;
rect.top -= ly;
pParentElement->get_parentElement(&pTemp);
pParentElement->Release();
pParentElement = pTemp;
} while (pParentElement);
return true;
}
void CHTMLCodeDlg::FocusElement()
{
// TODO : Add Code for control notification handler.
WTL::CTreeViewCtrlEx ctrl = GetDlgItem(IDC_TREE1);
CTreeItem item = ctrl.GetSelectedItem();
IHTMLElement *pItem = (IHTMLElement *)item.GetData();
RECT rect;
HTMLElementRect(pItem, rect);
long nBrowser = 0;
m_pParent->m_spWebBrowser2->get_HWND(&nBrowser);
HWND hWndParent = (HWND)nBrowser;
hWndParent = FindWindowEx(hWndParent, NULL, "Shell DocObject View", NULL);
if (hWndParent)
{
hWndParent = FindWindowEx(hWndParent, NULL, "Internet Explorer_Server", NULL);
}
//得到IE的节点。仅针对IE6
HDC hdc = ::GetDC(hWndParent);
HBRUSH hBrush;
hBrush = CreateSolidBrush(RGB(255,0,0));
CBrush pBrush((HBRUSH)GetStockObject(NULL_BRUSH));
SelectObject(hdc, CreatePen(PS_DASHDOTDOT, 1, RGB(0, 0, 255)));
SelectObject(hdc,GetStockObject(NULL_BRUSH));
{
::Rectangle(hdc, rect.left, rect.top, rect.left + rect.right, rect.top + rect.bottom);
Sleep(400);
SetROP2(hdc,R2_NOTXORPEN);
::Rectangle(hdc, rect.left, rect.top, rect.left + rect.right, rect.top + rect.bottom);
SetROP2(hdc,R2_NOTXORPEN);
}
::DeleteObject(hBrush);
::ReleaseDC(hWndParent, hdc);
}