实现浏览器自定义查找功能,参见开源项目:http://www.ookii.org/Software/FindAsYouType,在此贴出相关核心代码。
BOOL LbWebNoteHandler::DoHighlightText( const CString& strText , CComPtr<IHTMLTxtRange>& pTxtRange , CComPtr<IHTMLDocument2>& pDoc )
{
BSTR pStr = strText.AllocSysString();
long t = 0; long findflag = 0 | 4; // 向下搜索、匹配大小写
VARIANT_BOOL bFound = FALSE; BOOL bFristFind = TRUE;
while ( pTxtRange->findText( pStr , 0 , findflag , &bFound) , bFound )
{
CComPtr<IHTMLElement> pElement = NULL;
HRESULT hr = pTxtRange->parentElement( &pElement );
if ( FAILED( hr ) || pElement == NULL )
break ;
if ( CheckVisible(pElement) ) // 忽略不可见元素
{
HighlightRange( pTxtRange , pDoc );
}
pTxtRange->moveStart( (BSTR)CComBSTR( _T("Character") ) , 1, &t );
pTxtRange->moveEnd( (BSTR)CComBSTR( _T("Textedit") ) , 1 , &t );
}
SysFreeString( pStr );
return TRUE;
}
BOOL LbWebNoteHandler::HighlightRange( CComPtr<IHTMLTxtRange>& pTxtRange , CComPtr<IHTMLDocument2>& pDoc )
{
CComPtr<IMarkupServices> markup = NULL;
CComPtr<IMarkupPointer> start = NULL;
CComPtr<IMarkupPointer> end = NULL;
HRESULT hr = pDoc->QueryInterface( __uuidof(IMarkupServices) , (void**)&markup );
if ( FAILED( hr ) || markup == NULL )
return FALSE ;
hr = markup->CreateMarkupPointer( &start );
if ( FAILED( hr ) || start == NULL )
return FALSE ;
hr = markup->CreateMarkupPointer( &end );
if ( FAILED( hr ) || end == NULL )
return FALSE ;
hr = markup->MovePointersToRange( pTxtRange , start , end );
if ( FAILED( hr ) )
return FALSE ;
// Get display pointers from the markup pointers
CComPtr<IDisplayPointer> displayStart = CreateDisplayPointer(pDoc, start);
CComPtr<IDisplayPointer> displayEnd = CreateDisplayPointer(pDoc, end);
if( displayStart == NULL || displayEnd == NULL )
return FALSE;
CComPtr<IHTMLDocument4> doc = NULL;
doc = pDoc;
CComPtr<IHTMLRenderStyle> style = NULL;
hr = doc->createRenderStyle( NULL , &style );
if ( FAILED( hr ) || style == NULL )
return FALSE ;
style->put_defaultTextSelection( _bstr_t("false") );
style->put_textBackgroundColor( _variant_t("#FFFF11") );
style->put_textColor( _variant_t("#686868") );
// Create a highlight segment to highlight the range
CComPtr<IHighlightRenderingServices> highlight = NULL;
hr = pDoc->QueryInterface( __uuidof(IHighlightRenderingServices) , (void**)&highlight );
if ( FAILED( hr ) || highlight == NULL )
return FALSE ;
CComPtr<IHighlightSegment> segment = NULL;
hr = highlight->AddSegment(displayStart,displayEnd,style,&segment);
if ( FAILED( hr ) || segment == NULL )
return FALSE ;
// Store the segment so we can un-highlight it later.
m_highlights.push_back(segment);
return TRUE;
}
CComPtr<IDisplayPointer> LbWebNoteHandler::CreateDisplayPointer( CComPtr<IHTMLDocument2>& pDoc , CComPtr<IMarkupPointer>& markupPointer )
{
CComPtr<IDisplayServices> display = NULL;
HRESULT hr = pDoc->QueryInterface( __uuidof(IDisplayServices) , (void**)&display );
if ( FAILED( hr ) || display == NULL )
return NULL ;
CComPtr<IDisplayPointer> displayPointer = NULL;
hr = display->CreateDisplayPointer( &displayPointer );
if ( FAILED( hr ) || displayPointer == NULL )
return NULL ;
hr = displayPointer->MoveToMarkupPointer( markupPointer , NULL );
if ( FAILED( hr ) )
return NULL ;
return displayPointer;
}
BOOL LbWebNoteHandler::CancleHighlight( void )
{
if( m_highlights.empty() )
return TRUE;
CComPtr<IHTMLDocument2> pDoc = m_pIEWebBrowserRef->GetHTMLDocument2();
if( pDoc == NULL )
return FALSE;
CComPtr<IHighlightRenderingServices> highlight = NULL;
HRESULT hr = pDoc->QueryInterface( __uuidof(IHighlightRenderingServices) , (void**)&highlight );
if ( FAILED( hr ) || highlight == NULL )
return FALSE;
typedef std::vector<CComPtr<IHighlightSegment> >::iterator SegmentListIterator;
for( SegmentListIterator segment = m_highlights.begin(); segment != m_highlights.end(); ++segment )
highlight->RemoveSegment( *segment );
m_highlights.clear();
return TRUE;
}