1
votes

I need to implement the Search functionality provided by the Find dialog box which pops up when Ctrl+F is pressed.

I have a textbox where the user enters the string to be searched for, and a "Search" button. When the button is clicked clicked, matches in the HTML document need to be highlighted - exactly as implemented in the Find dialog box.

Is there a way to bypass the Find dialog box in a WebBrowser control? Is it possible to send the search parameters to the "find" functionality?

Thanks in advance for the help.

EDIT

Ideally, I would be able to use the full functionality provided by the Find dialog box, including "Match whole world only", "Match case" and "Highlight all matches"...

2

2 Answers

0
votes

Its not that hard to do yourself, all you do is replace whatever is in the Search TextBox with the following, say the search term is "hello", then you replace all occurances of hello with the following:

<font color="yellow">hello</font>

Of course, this HTML can be replaced with the SPAN tag (which is an inline version of the DIV tag, so your lines wont break using SPAN, but will using DIV). But in either case, both these tags have a style attribute, where you can use CSS to change its color or a zillion other properties that are CSS compatible, like follows:

<SPAN style="background-color: yellow;">hello</SPAN>

Of course, there are a zillion other ways to change color using HTML, feel free to search the web for more if you want.

Now, you can use the .Replace() function in dotnet to do this (replace the searched text), it's very easy. So, you can Get the Whole document as a string using .DocumentText, and once all occurances are replaced (using .Replace()), you can set it back to .DocumentText (so, you're using .DocumentText to get the original string, and setting .DocumentText with the replaced string). Of course, you probably don't want to do this to items inside the actual HTML, so you can just loop through all the elements on the page by doing a For Each loop over all elements like below:

For Each someElement as HTMLElement in WebBrowser1.Document.All

And each element will have a .InnerText/.InnerHTML and .OuterText/.OuterHTML that you can Get (read from) and Set (overwrite with replaced text).

Of course, for your needs, you'd probably just want to be replacing and overwriting the .InnerText and/or the .OuterText.

If you need more help, let me know. In either case, i'd like to know how it worked out for you anyway, or if there is anything more any of us can do to add value to your problem. Cheers.

0
votes

I had a lot of difficulty with this one, but I finally got a solution working. It's somewhat messy but it works as intended for the Winforms WebBrowser control. This is in .Net 4.0 with the Microsoft.mshtml 7.0.3300 reference imported.

using mshtml;

private int _findClicks = 0;
private string _searchText = "";

public string SearchText
    {
        get { return _searchText; }
        set
        {
            if (value.ToUpper() != _searchText)
            {
                ClearFind();
                _searchText = value.ToUpper();
                txtSearch.Text = value.ToUpper();

                _findClicks = 0;
            }
        }
    }

private void btnSearch_Click(object sender, EventArgs e)
    {
        SearchText = txtSearch.Text;
        if (_findClicks == 0)
            FindFirst();
        else
            FindNext();
    }

 /// <summary>
    /// Search through all text to find. Sets all occurrences to background color yellow.
    /// </summary>
    private void FindFirst()
    {
            if (_searchText == "")
                return;
            IHTMLDocument2 doc = webBrowser1.Document.DomDocument as IHTMLDocument2;
            IHTMLSelectionObject sel = doc.selection;
            IHTMLTxtRange range = sel.createRange() as IHTMLTxtRange;
            //Mark all occurrences with background color yellow
            while (true)
            {
                if ((range.findText(_searchText)) && (range.htmlText != "span style='background-color: yellow;'>" + _searchText + "</span>"))
                {
                    range.pasteHTML("<span style='background-color: yellow;'>" + _searchText + "</span>");
                }
                else
                    break;
            }
            //Move to beginning and select first occurence.
            range.moveStart("word", -9999999);
            range.findText(_searchText);
            range.select();
            _findClicks++;
        }

/// <summary>
    /// Finds next occurrence of searched text and selects it.
    /// </summary>
    private void FindNext()
    {
            if (_searchText == "")
                return;
            IHTMLDocument2 doc = webBrowser1.Document.DomDocument as IHTMLDocument2;
            IHTMLSelectionObject sel = doc.selection;
            IHTMLTxtRange range = sel.createRange() as IHTMLTxtRange;
            range.collapse(false); // collapse the current selection so we start from the end of the previous range

            if (range.findText(_searchText, 1000000, 0))
            {
                range.select();
            }
            else // If at end of list, go to beginning and search one more time.
            {
                range.moveStart("word", -9999999);
                if (range.findText(_searchText, 1000000, 0))
                {
                    range.select();
                }
            }
    }

/// <summary>
    /// Remove highlighting on all words from previous search.
    /// </summary>
    private void ClearFind()
    {
            if (_searchText == "" || webBrowser1.ReadyState != WebBrowserReadyState.Complete)
                return;
            IHTMLDocument2 doc = webBrowser1.Document.DomDocument as IHTMLDocument2;
            IHTMLSelectionObject sel = doc.selection;
            IHTMLTxtRange range = sel.createRange() as IHTMLTxtRange;
            range.moveStart("word", -9999999);
            while (true)
            {
                if ((range.findText(_searchText)) && (!range.htmlText.Contains("span style='background-color: white")))
                {
                    range.pasteHTML("<span style='background-color: white;'>" + _searchText + "</span>");
                }
                else
                    break;
            }

    }

Again, this is somewhat messy and could probably be cleaned up quite a bit. This pretty much replicates the basics of the Ctrl+F function in the Web Browser control. Hope it helps to all future readers.