不知道有没有朋友用过搜索引擎中的关键字高亮显示(Highlight功能),这种功能的实现很简单,但是效果却是很惊人的。
首先,你要有一个IHTMLDocument2的接口指针,如果没有,你可以通过使用IWebBrowser2Ptr接口的get_Document方法得到一个IDispatch指针,然后通过它查询接口IID_IHTMLDocument2,就搞定了。(什么?你不知道怎么得到IWebBrowser2Ptr指针,OK,我也帮不了你了。)
然后,通过IHTMLDocument2接口指针,我们可以查询得到IID_IMarkupContainer和IID_IMarkupServices接口的指针,然后使用IMarkupServices接口指针生成两个关键的接口指针IMarkupPointer(注意,是两个,为什么是两个呢?在超文本里查找Element,就好像三明治一样,要用两个指针夹着去找)。
再然后,我们要把两个IMarkupPointer移到生成的IMarkupContainer上去,接着,我们就可以查找文本了,当然,之前,我们还要将文本生成适当的字符形式(稍后详细的代码中有说明),接着的事就简单了,生成一个Attribute的Element,然后利用IMarkupServices加到对象中去,再进行三明治的指针接力(后一个指针移到前一个指针的位置上去),查找下一段文本。
再然后呢?(重复了吧,汗......),没有然后了,已经给文本上色了.......慢,我们只提到了上色,怎样把上的色(Element)去掉?好,你能想到这一点,说明你一定的编程实践经验了。那么,我们还是刚才的那段代码,只要使用IMarkupPointer的CurrentScope方法和IMarkupServices的RemoveElement方法组合,就能删掉添加的Element了。
完了,这次是真的完了。
/*******************************************************************
* MarkWords(): Logic of whether set highlight text or clear it *
* parameter: sWord , the aid-Text for highlight *
* return: TRUE if set success , else return FALSE *
* DATE: 2002.3.5 * * TeddyWing *
********************************************************************/
BOOL CBiglobeToolBar::SetMyColor(CString sWord, BOOL mFlag)
{
IHTMLDocument2 * m_pHtmlDoc2;
IMarkupServices * pMS;
IMarkupContainer * pMarkup;
IMarkupPointer * pPtr1, * pPtr2;
unsigned short * mSet = L"COLOR=#0000ff STYLE=\"background-color:#ff009c\""; // Font attribute
if (0 == m_pBand->m_pIE) return FALSE;
LPDISPATCH lpDispatch;
HRESULT hr = m_pBand->m_pIE->get_Document(&lpDispatch);
ASSERT(lpDispatch);
hr = lpDispatch->QueryInterface(IID_IHTMLDocument2, (void**)&m_pHtmlDoc2);
if (m_pHtmlDoc2)
{
hr = m_pHtmlDoc2->QueryInterface( IID_IMarkupContainer, (void **) & pMarkup );
hr = m_pHtmlDoc2->QueryInterface( IID_IMarkupServices, (void **) & pMS );
}
else
return FALSE;
hr = pMS->CreateMarkupPointer( & pPtr1 );
hr = pMS->CreateMarkupPointer( & pPtr2 );
hr = pPtr1->SetGravity( POINTER_GRAVITY_Right );
hr = pPtr2->SetGravity( POINTER_GRAVITY_Left );
hr = pPtr1->MoveToContainer( pMarkup, TRUE );
hr = pPtr2->MoveToContainer( pMarkup, FALSE );
int nFromLen = sWord.GetLength()+1; // Create aid-text
OLECHAR * poSearchStr;
poSearchStr = new OLECHAR[ nFromLen];
MultiByteToWideChar( CP_ACP, 0, sWord, -1, poSearchStr, nFromLen);
while(TRUE)
{ // Find text
hr = pPtr1->FindText( poSearchStr, 0, pPtr2, NULL );
if (S_FALSE == hr) break;// did not find the text
IHTMLElement *pFontEl;
if (TRUE == mFlag){
hr = pMS->CreateElement(TAGID_FONT, mSet, &pFontEl); // create FONT element with attributes for selection
hr = pMS->InsertElement( pFontEl, pPtr1, pPtr2); // Insert created element to context
pPtr1->MoveToPointer(pPtr2); // Continue searching
}
else{
// Remove last created element in the context
hr = pPtr1->CurrentScope( &pFontEl);
hr = pMS->RemoveElement( pFontEl);
pPtr1->MoveToPointer( pPtr2); // Continue searching
}
}
delete poSearchStr;
return TRUE;
}