"Ajay" <a
...@webtechdeveloper.com> wrote in message
news:%23vu7wE7TFHA.584@TK2MSFTNGP15.phx.gbl...
> Hello Jeff Partch,
> This is a followup for your solution.
http://groups.google.co.in/groups?hl=en&lr=&threadm=OBZ71%24R4BHA.157... > In that post, you had explained how to highlight search keyword. But you
> didn't give the necessary code to clear all searched results. I could
clear
> it by refreshing a page. But my requirement is not to allow user to
refresh
> page. Will you please tell me how to clear highligheted keywords using
> MSHTML?
> Awaiting for your reply.
Hi Ajay,
It's thankfully been a long time since I had to program MSHTML, but I think
back then I did just use refresh to clear the selections. After thinking
about it again today, I came up with the idea of giving the SPAN tags a
unique id something like...
__inline LPCTSTR _stdcall GetInternalSelectionElementId(VOID)
{
static CONST LPCTSTR szInternalSelectionElementId =
_T("internalSelectionElementId:")
_T("480D3948-2E14-49a2-BE06-401501E4588A");
return szInternalSelectionElementId;
}
...and then formatting it along with the
search phrase into the SPAN tag
something like...
__inline CString _stdcall GetHtmlSelectionString(IN CONST LPCTSTR pszPhrase)
{
static CONST LPCTSTR szFormat =
_T("<SPAN id = \"%s\" STYLE=\"color: HIGHLIGHTTEXT;")
_T("background-color : HIGHLIGHT\">%s</SPAN>");
CString strRet;
if (pszPhrase)
strRet.Format(szFormat, GetInternalSelectionElementId(), pszPhrase);
return strRet;
}
...off the cuff, this may open up better options, but the implementation
rewrite I came up with today uses this unique id to figure out if we're
dealing with one of our previous selections. FWIW, it goes like this...
VOID _stdcall DoHTMLPhraseSelect2(
IN CONST LPCTSTR lpszPhrase,
IN CONST LPDISPATCH pdispDoc,
IN CONST BOOL bUnselect,
IN OUT LPBSTR pbstrBkMark
)
{
CComBSTR bstrBookMark;
if (pbstrBkMark)
{
if (*pbstrBkMark)
bstrBookMark.Attach(*pbstrBkMark);
*pbstrBkMark = NULL;
}
if (lpszPhrase && pdispDoc && pbstrBkMark)
{
CComBSTR bstrText(lpszPhrase);
if (bstrText && bstrText.Length())
{
CComQIPtr<IHTMLDocument2>piDoc(pdispDoc);
if (piDoc)
{
CComPtr<IHTMLElement>piElem;
if (SUCCEEDED(piDoc->get_body(&piElem)) && piElem)
{
CComPtr<IHTMLBodyElement>piBody;
if (SUCCEEDED(piElem.QueryInterface(&piBody)) && piBody)
{
CComPtr<IHTMLTxtRange>piRange;
if (SUCCEEDED(piBody->createTextRange(&piRange)) &&
piRange)
{
VARIANT_BOOL b = VARIANT_TRUE;
LONG lFlag = 4;
if (bstrBookMark)
{
if
(FAILED(piRange->moveToBookmark(bstrBookMark, &b)) || (!b))
b = VARIANT_FALSE;
}
if ((b) && SUCCEEDED(piRange->findText(bstrText,
0, lFlag, &b)) && (b))
{
switch (GetInternalSelectionState(piRange,
bUnselect))
{
case INTERNAL_SELECTION_STATE_REMOVE:
{
bstrText = lpszPhrase;
break;
}
case INTERNAL_SELECTION_STATE_ADD:
{
bstrText =
GetHtmlSelectionString(lpszPhrase);
break;
}
default:
{
bstrText.Empty();
break;
}
}
if (bstrText)
{
LONG l = 0;
if
(SUCCEEDED(piRange->pasteHTML(bstrText)) &&
SUCCEEDED(piRange->collapse(VARIANT_FALSE)) &&
SUCCEEDED(piRange->moveEnd(CComBSTR(_T("Textedit")), 1, &l)))
{
if
(FAILED(piRange->getBookmark(pbstrBkMark)))
{
SysFreeString(*pbstrBkMark);
*pbstrBkMark = NULL;
}
}
}
}
}
}
}
}
}
}
}
...and where the GetInternalSelectionState function goes like this...
INTERNAL_SELECTION_STATES _stdcall GetInternalSelectionState(
IN IUnknown* piUnkRange,
IN CONST BOOL fMode // FALSE = Set, TRUE = Clear
)
{
INTERNAL_SELECTION_STATES issRet = INTERNAL_SELECTION_STATE_UNKNOWN;
CComQIPtr<IHTMLTxtRange>piRange(piUnkRange);
if (piRange)
{
CComPtr<IHTMLElement>piParentElem;
BOOL bInternal = FALSE;
if (SUCCEEDED(piRange->parentElement(&piParentElem)) &&
piParentElem)
{
CComBSTR bstrElementId;
if (SUCCEEDED(piParentElem->get_id(&bstrElementId)) &&
bstrElementId)
{
CComBSTR
bstrInternalSelectionElementId(GetInternalSelectionElementId());
bInternal = (bstrElementId ==
bstrInternalSelectionElementId);
}
}
if (bInternal && fMode &&
SUCCEEDED(piRange->moveToElementText(piParentElem)))
issRet = INTERNAL_SELECTION_STATE_REMOVE;
else if (!bInternal && !fMode && SUCCEEDED(piRange->select()))
issRet = INTERNAL_SELECTION_STATE_ADD;
else
issRet = INTERNAL_SELECTION_STATE_IGNORE;
}
return issRet;
}
...and where the INTERNAL_SELECTION_STATES values are an enum something
along the lines of...
enum INTERNAL_SELECTION_STATES {
INTERNAL_SELECTION_STATE_UNKNOWN = 0,
INTERNAL_SELECTION_STATE_REMOVE = 1,
INTERNAL_SELECTION_STATE_ADD = 2,
INTERNAL_SELECTION_STATE_IGNORE = 4
};
...and which I call from a quick CHtmlView test app like so...
VOID CNg011902View::OnHtmlSetSelect(VOID)
{
LPDISPATCH pDisp = GetHtmlDocument();
if (pDisp)
{
BSTR bstrBkMk = NULL;
do {
DoHTMLPhraseSelect2(_T("test"), pDisp, FALSE, &bstrBkMk);
} while (bstrBkMk);
}
}
VOID CNg011902View::OnHtmlClearSelect(VOID)
{
LPDISPATCH pDisp = GetHtmlDocument();
if (pDisp)
{
BSTR bstrBkMk = NULL;
do {
DoHTMLPhraseSelect2(_T("test"), pDisp, TRUE, &bstrBkMk);
} while (bstrBkMk);
}
}
...anyway, apologies in advance for the ugly wrapping that OE will no doubt
impose on the above, and seriously -- do double-check me as it could very
well be hog wash. :)
--
Jeff Partch [VC++ MVP]