]> git.saurik.com Git - wxWidgets.git/commitdiff
Add support for searching and highlighting a wxWebView.
authorSteve Lamerton <steve.lamerton@gmail.com>
Tue, 28 Aug 2012 17:13:13 +0000 (17:13 +0000)
committerSteve Lamerton <steve.lamerton@gmail.com>
Tue, 28 Aug 2012 17:13:13 +0000 (17:13 +0000)
Currently supports WebView on GTK and IE. Closes #14045.

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@72390 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775

docs/changes.txt
include/wx/gtk/webview_webkit.h
include/wx/msw/webview_ie.h
include/wx/osx/webview_webkit.h
include/wx/webview.h
interface/wx/webview.h
samples/webview/webview.cpp
src/gtk/webview_webkit.cpp
src/msw/webview_ie.cpp

index 86e107d3da401906bb92edb21b3edba4b4828cb2..119b685d34b7721145dacb37e33b6795dc86fbc5 100644 (file)
@@ -535,6 +535,7 @@ All:
 
 All (GUI):
 
+- Add support for searching in wxWebView for MSW and GTK (Allonii).
 - Respect window max size in wxBoxSizer (Nathan Ridge).
 - Add possibility to hide and show again wxRibbonBar pages (wxBen).
 - Add wxRibbonBar pages highlighting (wxBen).
index d130b827e362ae3932b62d0791eeb9722f9be72d..72b41c15ceb02b43be74b4aec7b44b31e16187f3 100644 (file)
@@ -96,6 +96,9 @@ public:
     virtual void Undo();
     virtual void Redo();
 
+    //Find function
+    virtual long Find(const wxString& text, int flags = wxWEB_VIEW_FIND_DEFAULT);
+
     //Editing functions
     virtual void SetEditable(bool enable = true);
     virtual bool IsEditable() const;
@@ -142,6 +145,9 @@ private:
     void SetWebkitZoom(float level);
     float GetWebkitZoom() const;
 
+    //Find helper function
+    void FindClear();
+
     // focus event handler: calls GTKUpdateBitmap()
     void GTKOnFocus(wxFocusEvent& event);
 
@@ -150,6 +156,12 @@ private:
 
     wxVector<wxSharedPtr<wxWebViewHandler> > m_handlerList;
 
+    //variables used for Find()
+    int m_findFlags;
+    wxString m_findText;
+    int m_findPosition;
+    int m_findCount;
+
     wxDECLARE_DYNAMIC_CLASS(wxWebViewWebKit);
 };
 
index 99b41af17422e044b0f66ebee4a2d6f8dbb06963..0a1f150d5fc63cdaf1b23f9c0156fa835c1225b9 100644 (file)
@@ -244,10 +244,13 @@ public:
 /* END OF MSHTMHST.H implementation */
 
 struct IHTMLDocument2;
+struct IHTMLElement;
+struct IMarkupPointer;
 class wxFSFile;
 class ClassFactory;
 class wxIEContainer;
 class DocHostUIHandler;
+class wxFindPointers;
 
 class WXDLLIMPEXP_WEBVIEW wxWebViewIE : public wxWebView
 {
@@ -320,6 +323,9 @@ public:
     virtual void Undo();
     virtual void Redo();
 
+    //Find function
+    virtual long Find(const wxString& text, int flags = wxWEB_VIEW_FIND_DEFAULT);
+
     //Editing functions
     virtual void SetEditable(bool enable = true);
     virtual bool IsEditable() const;
@@ -384,10 +390,21 @@ private:
     bool m_historyLoadingFromList;
     bool m_historyEnabled;
 
-    //Generic helper functions for IHtmlDocument commands
+    //We store find flag, results and position.
+    wxVector<wxFindPointers> m_findPointers;
+    int m_findFlags;
+    wxString m_findText;
+    int m_findPosition;
+
+    //Generic helper functions
     bool CanExecCommand(wxString command) const;
     void ExecCommand(wxString command);
     wxCOMPtr<IHTMLDocument2> GetDocument() const;
+    bool IsElementVisible(IHTMLElement* elm);
+    //Find helper functions.
+    void FindInternal(const wxString& text, int flags, int internal_flag);
+    long FindNext(int direction = 1);
+    void FindClear();
     //Toggles control features see INTERNETFEATURELIST for values.
     bool EnableControlFeature(long flag, bool enable = true);
 
@@ -517,6 +534,18 @@ public:
     DECLARE_IUNKNOWN_METHODS;
 };
 
+class wxFindPointers
+{
+public:
+    wxFindPointers(IMarkupPointer *ptrBegin, IMarkupPointer *ptrEnd)
+    {
+        begin = ptrBegin;
+        end = ptrEnd;
+    }
+    //The two markup pointers.
+    IMarkupPointer *begin, *end;
+};
+
 #endif // wxUSE_WEBVIEW && wxUSE_WEBVIEW_IE && defined(__WXMSW__)
 
 #endif // wxWebViewIE_H
index 193057fcdf7d38d91c2c9b52f1674e689fe35379..e876aadf0146508dc6a27e352cbba1ec6ab5b565 100644 (file)
@@ -86,6 +86,9 @@ public:
     virtual void Undo();
     virtual void Redo();
 
+    //Find function
+    virtual long Find(const wxString& text, int flags = wxWEB_VIEW_FIND_DEFAULT) { return wxNOT_FOUND; };
+
     //Clipboard functions
     virtual bool CanCut() const { return true; }
     virtual bool CanCopy() const { return true; }
index 72f9f180de28759e2f9df6cb8ce81d587015151a..050c31953e5092a42a0742984cf640021f7cde19 100644 (file)
@@ -68,6 +68,16 @@ enum wxWebViewReloadFlags
     wxWEB_VIEW_RELOAD_NO_CACHE
 };
 
+enum wxWebViewFindFlags
+{
+    wxWEB_VIEW_FIND_WRAP =             0x0001,
+    wxWEB_VIEW_FIND_ENTIRE_WORD =      0x0002,
+    wxWEB_VIEW_FIND_MATCH_CASE =       0x0004,
+    wxWEB_VIEW_FIND_HIGHLIGHT_RESULT = 0x0008,
+    wxWEB_VIEW_FIND_BACKWARDS =        0x0010,
+    wxWEB_VIEW_FIND_DEFAULT =          0
+};
+
 enum wxWebViewBackend
 {
     wxWEB_VIEW_BACKEND_DEFAULT,
@@ -181,6 +191,8 @@ public:
 
     //Get the pointer to the underlying native engine.
     virtual void* GetNativeBackend() const = 0;
+    //Find function
+    virtual long Find(const wxString& text, int flags = wxWEB_VIEW_FIND_DEFAULT) = 0;
 
 protected:
     virtual void DoSetPage(const wxString& html, const wxString& baseUrl) = 0;
index e7a75785f7e52621a838363046eac0296cf6dc9e..58d1f974b8ff5dbdce36818b4e925d95586792b1 100644 (file)
@@ -69,6 +69,30 @@ enum wxWebViewReloadFlags
     wxWEB_VIEW_RELOAD_NO_CACHE
 };
 
+/**
+    Find flags used when searching for text on page.
+*/
+enum wxWebViewFindFlags
+{
+    /** Causes the search to restart when end or beginning reached */
+    wxWEB_VIEW_FIND_WRAP =             0x0001,
+
+    /** Matches an entire word when searching */
+    wxWEB_VIEW_FIND_ENTIRE_WORD =      0x0002,
+
+    /** Match case, i.e. case sensitive searching */
+    wxWEB_VIEW_FIND_MATCH_CASE =       0x0004,
+
+    /** Highlights the search results */
+    wxWEB_VIEW_FIND_HIGHLIGHT_RESULT = 0x0008,
+
+    /** Searches for phrase in backward direction */
+    wxWEB_VIEW_FIND_BACKWARDS =        0x0010,
+
+    /** The default flag, which is simple searching */
+    wxWEB_VIEW_FIND_DEFAULT =          0
+};
+
 /**
  * List of available backends for wxWebView
  */
@@ -572,6 +596,30 @@ public:
     */
     virtual void Undo() = 0;
 
+    /**
+        @name Finding
+    */
+
+    /**
+        Finds a phrase on the current page and if found, the control will
+        scroll the phrase into view and select it.
+        @param text The phrase to search for.
+        @param flags The flags for the search.
+        @return If search phrase was not found in combination with the flags
+                then @c wxNOT_FOUND is returned. If called for the first time
+                with search phrase then the total number of results will be 
+                returned. Then for every time its called with the same search
+                phrase it will return the number of the current match.
+        @note This function will restart the search if the flags
+              @c wxWEB_VIEW_FIND_ENTIRE_WORD or @c wxWEB_VIEW_FIND_MATCH_CASE
+              are changed, since this will require a new search. To reset the
+              search, for example reseting the highlights call the function 
+              with an empty search phrase. This always returns @c wxNOT_FOUND
+              on the OSX WebKit backend.
+        @since 2.9.5
+    */
+    virtual long Find(const wxString& text, wxWebViewFindFlags flags = wxWEB_VIEW_FIND_DEFAULT) = 0;
+
     /**
         @name Zoom
     */
index 6e7ab1435a387f3696296e7f95f4a62829912409..6c0773b6fe2eb742d0e8cedbbd152176db486ed2 100644 (file)
@@ -136,6 +136,10 @@ public:
     void OnDeleteSelection(wxCommandEvent& evt);
     void OnSelectAll(wxCommandEvent& evt);
     void OnLoadScheme(wxCommandEvent& evt);
+    void OnFind(wxCommandEvent& evt);
+    void OnFindDone(wxCommandEvent& evt);
+    void OnFindText(wxCommandEvent& evt);
+    void OnFindOptions(wxCommandEvent& evt);
 
 private:
     wxTextCtrl* m_url;
@@ -148,6 +152,15 @@ private:
     wxToolBarToolBase* m_toolbar_reload;
     wxToolBarToolBase* m_toolbar_tools;
 
+    wxToolBarToolBase* m_find_toolbar_done;
+    wxToolBarToolBase* m_find_toolbar_next;
+    wxToolBarToolBase* m_find_toolbar_previous;
+    wxToolBarToolBase* m_find_toolbar_options;
+    wxMenuItem* m_find_toolbar_wrap;
+    wxMenuItem* m_find_toolbar_highlight;
+    wxMenuItem* m_find_toolbar_matchcase;
+    wxMenuItem* m_find_toolbar_wholeword;
+
     wxMenu* m_tools_menu;
     wxMenu* m_tools_history_menu;
     wxMenuItem* m_tools_layout;
@@ -171,11 +184,16 @@ private:
     wxMenuItem* m_scroll_page_down;
     wxMenuItem* m_selection_clear;
     wxMenuItem* m_selection_delete;
+    wxMenuItem* m_find;
 
     wxInfoBar *m_info;
     wxStaticText* m_info_text;
+    wxTextCtrl* m_find_ctrl;
+    wxToolBar* m_find_toolbar;
 
     wxMenuHistoryMap m_histMenuItems;
+    wxString m_findText;
+    int m_findFlags, m_findCount;
 };
 
 class SourceViewDialog : public wxDialog
@@ -240,6 +258,47 @@ WebFrame::WebFrame(const wxString& url) :
 
     m_toolbar->Realize();
 
+    // Set find values.
+    m_findFlags = wxWEB_VIEW_FIND_DEFAULT;
+    m_findText = wxEmptyString;
+    m_findCount = 0;
+
+    // Create panel for find toolbar.
+    wxPanel* panel = new wxPanel(this);
+    topsizer->Add(panel, wxSizerFlags().Expand());
+
+    // Create sizer for panel.
+    wxBoxSizer* panel_sizer = new wxBoxSizer(wxVERTICAL);
+    panel->SetSizer(panel_sizer);
+
+    // Create the find toolbar.
+    m_find_toolbar = new wxToolBar(panel, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTB_HORIZONTAL|wxTB_TEXT|wxTB_HORZ_LAYOUT);
+    m_find_toolbar->Hide();
+    panel_sizer->Add(m_find_toolbar, wxSizerFlags().Expand());
+
+    // Create find control.
+    m_find_ctrl = new wxTextCtrl(m_find_toolbar, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize(140,-1), wxTE_PROCESS_ENTER);
+
+
+    //Find options menu
+    wxMenu* findmenu = new wxMenu;
+    m_find_toolbar_wrap = findmenu->AppendCheckItem(wxID_ANY,"Wrap");
+    m_find_toolbar_matchcase = findmenu->AppendCheckItem(wxID_ANY,"Match Case");
+    m_find_toolbar_wholeword = findmenu->AppendCheckItem(wxID_ANY,"Entire Word");
+    m_find_toolbar_highlight = findmenu->AppendCheckItem(wxID_ANY,"Highlight");
+    // Add find toolbar tools.
+    m_find_toolbar->SetToolSeparation(7);
+    m_find_toolbar_done = m_find_toolbar->AddTool(wxID_ANY, "Close", wxArtProvider::GetBitmap(wxART_CROSS_MARK));
+    m_find_toolbar->AddSeparator();
+    m_find_toolbar->AddControl(m_find_ctrl, "Find");
+    m_find_toolbar->AddSeparator();
+    m_find_toolbar_next = m_find_toolbar->AddTool(wxID_ANY, "Next", wxArtProvider::GetBitmap(wxART_GO_DOWN, wxART_TOOLBAR, wxSize(16,16)));
+    m_find_toolbar_previous = m_find_toolbar->AddTool(wxID_ANY, "Previous", wxArtProvider::GetBitmap(wxART_GO_UP, wxART_TOOLBAR, wxSize(16,16)));
+    m_find_toolbar->AddSeparator();
+    m_find_toolbar_options = m_find_toolbar->AddTool(wxID_ANY, "Options", wxArtProvider::GetBitmap(wxART_PLUS, wxART_TOOLBAR, wxSize(16,16)), "", wxITEM_DROPDOWN);
+    m_find_toolbar_options->SetDropdownMenu(findmenu);
+    m_find_toolbar->Realize();
+
     // Create the info panel
     m_info = new wxInfoBar(this);
     topsizer->Add(m_info, wxSizerFlags().Expand());
@@ -275,6 +334,10 @@ WebFrame::WebFrame(const wxString& url) :
     m_tools_handle_new_window = m_tools_menu->AppendCheckItem(wxID_ANY, _("Handle New Windows"));
     m_tools_menu->AppendSeparator();
 
+    //Find
+    m_find = m_tools_menu->Append(wxID_ANY, _("Find"));
+    m_tools_menu->AppendSeparator();
+
     //History menu
     m_tools_history_menu = new wxMenu();
     wxMenuItem* clearhist =  m_tools_history_menu->Append(wxID_ANY, _("Clear History"));
@@ -339,6 +402,20 @@ WebFrame::WebFrame(const wxString& url) :
     Connect(m_url->GetId(), wxEVT_COMMAND_TEXT_ENTER,
             wxCommandEventHandler(WebFrame::OnUrl), NULL, this );
 
+    // Connect find toolbar events.
+    Connect(m_find_toolbar_done->GetId(), wxEVT_COMMAND_TOOL_CLICKED,
+            wxCommandEventHandler(WebFrame::OnFindDone), NULL, this );
+    Connect(m_find_toolbar_next->GetId(), wxEVT_COMMAND_TOOL_CLICKED,
+            wxCommandEventHandler(WebFrame::OnFindText), NULL, this );
+    Connect(m_find_toolbar_previous->GetId(), wxEVT_COMMAND_TOOL_CLICKED,
+            wxCommandEventHandler(WebFrame::OnFindText), NULL, this );
+
+    // Connect find control events.
+    Connect(m_find_ctrl->GetId(), wxEVT_COMMAND_TEXT_UPDATED,
+            wxCommandEventHandler(WebFrame::OnFindText), NULL, this );
+    Connect(m_find_ctrl->GetId(), wxEVT_COMMAND_TEXT_ENTER,
+            wxCommandEventHandler(WebFrame::OnFindText), NULL, this );
+
     // Connect the webview events
     Connect(m_browser->GetId(), wxEVT_COMMAND_WEB_VIEW_NAVIGATING,
             wxWebViewEventHandler(WebFrame::OnNavigationRequest), NULL, this);
@@ -404,6 +481,8 @@ WebFrame::WebFrame(const wxString& url) :
             wxCommandEventHandler(WebFrame::OnSelectAll),  NULL, this );
     Connect(loadscheme->GetId(), wxEVT_COMMAND_MENU_SELECTED,
             wxCommandEventHandler(WebFrame::OnLoadScheme),  NULL, this );
+    Connect(m_find->GetId(), wxEVT_COMMAND_MENU_SELECTED,
+            wxCommandEventHandler(WebFrame::OnFind),  NULL, this );
 
     //Connect the idle events
     Connect(wxID_ANY, wxEVT_IDLE, wxIdleEventHandler(WebFrame::OnIdle), NULL, this);
@@ -549,6 +628,72 @@ void WebFrame::OnLoadScheme(wxCommandEvent& WXUNUSED(evt))
     m_browser->LoadURL(path);
 }
 
+void WebFrame::OnFind(wxCommandEvent& WXUNUSED(evt))
+{
+    wxString value = m_browser->GetSelectedText();
+    if(value.Len() > 150)
+    {
+        value.Truncate(150);
+    }
+    m_find_ctrl->SetValue(value);
+    if(!m_find_toolbar->IsShown()){
+        m_find_toolbar->Show(true);
+        SendSizeEvent();
+    }
+    m_find_ctrl->SelectAll();
+}
+
+void WebFrame::OnFindDone(wxCommandEvent& WXUNUSED(evt))
+{
+    m_browser->Find("");
+    m_find_toolbar->Show(false);
+    SendSizeEvent();
+}
+
+void WebFrame::OnFindText(wxCommandEvent& evt)
+{
+    int flags = 0;
+
+    if(m_find_toolbar_wrap->IsChecked())
+        flags |= wxWEB_VIEW_FIND_WRAP;
+    if(m_find_toolbar_wholeword->IsChecked())
+        flags |= wxWEB_VIEW_FIND_ENTIRE_WORD;
+    if(m_find_toolbar_matchcase->IsChecked())
+        flags |= wxWEB_VIEW_FIND_MATCH_CASE;
+    if(m_find_toolbar_highlight->IsChecked())
+        flags |= wxWEB_VIEW_FIND_HIGHLIGHT_RESULT;
+
+    if(m_find_toolbar_previous->GetId() == evt.GetId())
+        flags |= wxWEB_VIEW_FIND_BACKWARDS;
+
+    wxString find_text = m_find_ctrl->GetValue();
+    long count = m_browser->Find(find_text, flags);
+
+    if(m_findText != find_text)
+    {
+        m_findCount = count;
+        m_findText = find_text;
+    }
+
+    if(count != wxNOT_FOUND || find_text.IsEmpty())
+    {
+        m_find_ctrl->SetBackgroundColour(*wxWHITE);
+    }
+    else
+    {
+        m_find_ctrl->SetBackgroundColour(wxColour(255, 101, 101));
+    }
+
+    m_find_ctrl->Refresh();
+
+    //Log the result, note that count is zero indexed.
+    if(count != m_findCount)
+    {
+        count++;
+    }
+    wxLogMessage("Searching for:%s  current match:%i/%i", m_findText.c_str(), count, m_findCount);
+}
+
 /**
   * Callback invoked when there is a request to load a new page (for instance
   * when the user clicks a link)
index ea5abe7c0a2c388a7a39919e810c754cfd30ae50..278f445f5971c811517550239535d698720f684c 100644 (file)
@@ -400,6 +400,7 @@ bool wxWebViewWebKit::Create(wxWindow *parent,
 {
     m_busy = false;
     m_guard = false;
+    FindClear();
 
     // We currently unconditionally impose scrolling in both directions as it's
     // necessary to show arbitrary pages.
@@ -927,6 +928,80 @@ void wxWebViewWebKit::RegisterHandler(wxSharedPtr<wxWebViewHandler> handler)
     m_handlerList.push_back(handler);
 }
 
+long wxWebViewWebKit::Find(const wxString& text, int flags)
+{
+    bool newSearch = false;
+    if(text != m_findText || 
+       (flags & wxWEB_VIEW_FIND_MATCH_CASE) != (m_findFlags & wxWEB_VIEW_FIND_MATCH_CASE))
+    {
+        newSearch = true;
+        //If it is a new search we need to clear existing highlights
+        webkit_web_view_unmark_text_matches(m_web_view);
+        webkit_web_view_set_highlight_text_matches(m_web_view, false);
+    }
+
+    m_findFlags = flags;
+    m_findText = text;
+
+    //If the search string is empty then we clear any selection and highlight
+    if(text == "")
+    {
+        webkit_web_view_unmark_text_matches(m_web_view);
+        webkit_web_view_set_highlight_text_matches(m_web_view, false);
+        ClearSelection();
+        return wxNOT_FOUND;
+    }
+
+    bool wrap = false, matchCase = false, forward = true;
+    if(flags & wxWEB_VIEW_FIND_WRAP)
+        wrap = true;
+    if(flags & wxWEB_VIEW_FIND_MATCH_CASE)
+        matchCase = true;
+    if(flags & wxWEB_VIEW_FIND_BACKWARDS)
+        forward = false;
+
+    if(newSearch)
+    {
+        //Initially we mark the matches to know how many we have
+        m_findCount = webkit_web_view_mark_text_matches(m_web_view, wxGTK_CONV(text), matchCase, 0);
+        //In this case we return early to match IE behaviour
+        m_findPosition = -1;
+        return m_findCount;
+    }
+    else
+    {
+        if(forward)
+            m_findPosition++;
+        else
+            m_findPosition--;
+        if(m_findPosition < 0)
+            m_findPosition += m_findCount;
+        if(m_findPosition > m_findCount)
+            m_findPosition -= m_findCount;
+    }
+
+    //Highlight them if needed
+    bool highlight = flags & wxWEB_VIEW_FIND_HIGHLIGHT_RESULT ? true : false;
+    webkit_web_view_set_highlight_text_matches(m_web_view, highlight);     
+
+    if(!webkit_web_view_search_text(m_web_view, wxGTK_CONV(text), matchCase, forward, wrap))
+    {
+        m_findPosition = -1;
+        ClearSelection();
+        return wxNOT_FOUND;
+    }
+    wxLogMessage(wxString::Format("Returning %d", m_findPosition));
+    return newSearch ? m_findCount : m_findPosition;
+}
+
+void wxWebViewWebKit::FindClear()
+{
+    m_findCount = 0;
+    m_findFlags = 0;
+    m_findText = "";
+    m_findPosition = -1;
+}
+
 // static
 wxVisualAttributes
 wxWebViewWebKit::GetClassDefaultAttributes(wxWindowVariant WXUNUSED(variant))
index 5797f01c78e0246cc5a6830e3e05d5826ba2b11e..de67e1ee32bfdc6f062e7879d5cf75aef1c9e446 100644 (file)
@@ -39,6 +39,12 @@ DEFINE_GUID(wxIID_IInternetProtocolRoot,0x79eac9e3,0xbaf9,0x11ce,0x8c,0x82,0,0xa
 DEFINE_GUID(wxIID_IInternetProtocol,0x79eac9e4,0xbaf9,0x11ce,0x8c,0x82,0,0xaa,0,0x4b,0xa9,0xb);
 DEFINE_GUID(wxIID_IDocHostUIHandler, 0xbd3f23c0, 0xd43e, 0x11cf, 0x89, 0x3b, 0x00, 0xaa, 0x00, 0xbd, 0xce, 0x1a);
 
+enum //Internal find flags
+{
+    wxWEB_VIEW_FIND_ADD_POINTERS =      0x0001,
+    wxWEB_VIEW_FIND_REMOVE_HIGHLIGHT =  0x0002
+};
+
 }
 
 wxIMPLEMENT_DYNAMIC_CLASS(wxWebViewIE, wxWebView);
@@ -68,6 +74,7 @@ bool wxWebViewIE::Create(wxWindow* parent,
     m_historyEnabled = true;
     m_historyPosition = -1;
     m_zoomType = wxWEB_VIEW_ZOOM_TYPE_TEXT;
+    FindClear();
 
     if (::CoCreateInstance(CLSID_WebBrowser, NULL,
                            CLSCTX_INPROC_SERVER, // CLSCTX_INPROC,
@@ -98,6 +105,7 @@ wxWebViewIE::~wxWebViewIE()
     {
         m_factories[i]->Release();
     }
+    FindClear();
 }
 
 void wxWebViewIE::LoadURL(const wxString& url)
@@ -591,6 +599,53 @@ void wxWebViewIE::Redo()
     ExecCommand("Redo");
 }
 
+long wxWebViewIE::Find(const wxString& text, int flags)
+{
+    //If the text is empty then we clear.
+    if(text.IsEmpty())
+    {
+        ClearSelection();
+        if(m_findFlags & wxWEB_VIEW_FIND_HIGHLIGHT_RESULT)
+        {
+            FindInternal(m_findText, (m_findFlags &~ wxWEB_VIEW_FIND_HIGHLIGHT_RESULT), wxWEB_VIEW_FIND_REMOVE_HIGHLIGHT);
+        }
+        FindClear();
+        return wxNOT_FOUND;
+    }
+    //Have we done this search before?
+    if(m_findText == text)
+    {
+        //Just do a highlight?
+        if((flags & wxWEB_VIEW_FIND_HIGHLIGHT_RESULT) != (m_findFlags & wxWEB_VIEW_FIND_HIGHLIGHT_RESULT))
+        {
+            m_findFlags = flags;
+            if(!m_findPointers.empty())
+            {
+                FindInternal(m_findText, m_findFlags, ((flags & wxWEB_VIEW_FIND_HIGHLIGHT_RESULT) == 0 ? wxWEB_VIEW_FIND_REMOVE_HIGHLIGHT : 0));
+            }
+            return m_findPosition;
+        }
+        else if(((m_findFlags & wxWEB_VIEW_FIND_ENTIRE_WORD) == (flags & wxWEB_VIEW_FIND_ENTIRE_WORD)) && ((m_findFlags & wxWEB_VIEW_FIND_MATCH_CASE) == (flags&wxWEB_VIEW_FIND_MATCH_CASE)))
+        {
+            m_findFlags = flags;
+            return FindNext(((flags & wxWEB_VIEW_FIND_BACKWARDS) ? -1 : 1));
+        }
+    }
+    //Remove old highlight if any.
+    if(m_findFlags & wxWEB_VIEW_FIND_HIGHLIGHT_RESULT)
+    {
+        FindInternal(m_findText, (m_findFlags &~ wxWEB_VIEW_FIND_HIGHLIGHT_RESULT), wxWEB_VIEW_FIND_REMOVE_HIGHLIGHT);
+    }
+    //Reset find variables.
+    FindClear();
+    ClearSelection();
+    m_findText = text;
+    m_findFlags = flags;
+    //find the text and return count.
+    FindInternal(text, flags, wxWEB_VIEW_FIND_ADD_POINTERS);
+    return m_findPointers.empty() ? wxNOT_FOUND : m_findPointers.size();
+}
+
 void wxWebViewIE::SetEditable(bool enable)
 {
     wxCOMPtr<IHTMLDocument2> document(GetDocument());
@@ -856,6 +911,232 @@ wxCOMPtr<IHTMLDocument2> wxWebViewIE::GetDocument() const
     return document;
 }
 
+bool wxWebViewIE::IsElementVisible(IHTMLElement* elm)
+{
+    IHTMLCurrentStyle* style;
+    IHTMLElement *elm1 = elm;
+    IHTMLElement2 *elm2;
+    BSTR tmp_bstr;
+    bool is_visible = true;
+    //This method is not perfect but it does discover most of the hidden elements.
+    //so if a better solution is found, then please do improve.
+    while(elm1)
+    {
+        if(SUCCEEDED(elm1->QueryInterface(IID_IHTMLElement2, (void**) &elm2)))
+        {
+            if(SUCCEEDED(elm2->get_currentStyle(&style)))
+            {
+                //Check if the object has the style display:none.
+                if((style->get_display(&tmp_bstr) != S_OK) || 
+                   (tmp_bstr != NULL && (_wcsicmp(tmp_bstr, L"none") == 0)))
+                {
+                    is_visible = false;
+                }
+                //Check if the object has the style visibility:hidden.
+                if(is_visible && (style->get_visibility(&tmp_bstr) != S_OK) || 
+                  (tmp_bstr != NULL && _wcsicmp(tmp_bstr, L"hidden") == 0))
+                {
+                    is_visible = false;
+                }
+                style->Release();
+            }
+            elm2->Release();
+        }
+
+        //Lets check the object's parent element.
+        IHTMLElement* parent;
+        if(is_visible && SUCCEEDED(elm1->get_parentElement(&parent)))
+        {
+            elm1->Release();
+            elm1 = parent;
+        }
+        else
+        {
+            elm1->Release();
+            break;
+        }
+    }
+    return is_visible;
+}
+
+void wxWebViewIE::FindInternal(const wxString& text, int flags, int internal_flag)
+{
+    IMarkupServices *pIMS;
+    IMarkupContainer *pIMC;
+    IMarkupPointer *ptrBegin, *ptrEnd;
+    IHTMLElement* elm;
+    long find_flag = 0;
+    IHTMLDocument2 *document = GetDocument();
+    //This function does the acutal work.
+    if(SUCCEEDED(document->QueryInterface(IID_IMarkupServices, (void **)&pIMS)))
+    {
+        if(SUCCEEDED(document->QueryInterface(IID_IMarkupContainer, (void **)&pIMC)))
+        {
+            BSTR attr_bstr = SysAllocString(L"style=\"background-color:#ffff00\"");
+            BSTR text_bstr = SysAllocString(text.wc_str());
+            pIMS->CreateMarkupPointer(&ptrBegin);
+            pIMS->CreateMarkupPointer(&ptrEnd);
+
+            ptrBegin->SetGravity(POINTER_GRAVITY_Right);
+            ptrBegin->MoveToContainer(pIMC, TRUE);
+            //Create the find flag from the wx one.
+            if(flags & wxWEB_VIEW_FIND_ENTIRE_WORD)
+            {
+                find_flag |= FINDTEXT_WHOLEWORD;
+            }
+            if(flags & wxWEB_VIEW_FIND_MATCH_CASE)
+            {
+                find_flag |= FINDTEXT_MATCHCASE;
+            }
+
+            //A little speed-up to avoid to re-alloc in the positions vector.
+            if(text.Len() < 3 && m_findPointers.capacity() < 500)
+            {
+               m_findPointers.reserve(text.Len() == 1 ? 1000 : 500);
+            }
+
+            while(ptrBegin->FindText(text_bstr, find_flag, ptrEnd, NULL) == S_OK)
+            {
+                if(ptrBegin->CurrentScope(&elm) == S_OK)
+                {
+                    if(IsElementVisible(elm))
+                    {
+                        //Highlight the word if the flag was set.
+                        if(flags & wxWEB_VIEW_FIND_HIGHLIGHT_RESULT)
+                        {
+                            IHTMLElement* pFontEl;
+                            pIMS->CreateElement(TAGID_FONT, attr_bstr, &pFontEl);
+                            pIMS->InsertElement(pFontEl, ptrBegin, ptrEnd);
+                        }
+                        if(internal_flag & wxWEB_VIEW_FIND_REMOVE_HIGHLIGHT)
+                        {
+                            IHTMLElement* pFontEl;
+                            ptrBegin->CurrentScope(&pFontEl);
+                            pIMS->RemoveElement(pFontEl);
+                            pFontEl->Release();
+                        }
+                        if(internal_flag & wxWEB_VIEW_FIND_ADD_POINTERS)
+                        {
+                            IMarkupPointer *cptrBegin, *cptrEnd;
+                            pIMS->CreateMarkupPointer(&cptrBegin);
+                            pIMS->CreateMarkupPointer(&cptrEnd);
+                            cptrBegin->MoveToPointer(ptrBegin);
+                            cptrEnd->MoveToPointer(ptrEnd);
+                            m_findPointers.push_back(wxFindPointers(cptrBegin,cptrEnd));
+                        }
+                    }
+                    elm->Release();
+                }
+                ptrBegin->MoveToPointer(ptrEnd);
+            }
+            //Clean up.
+            SysFreeString(text_bstr);
+            SysFreeString(attr_bstr);
+            pIMC->Release();
+            ptrBegin->Release();
+            ptrEnd->Release();
+        }
+        pIMS->Release();
+    }
+    document->Release();
+}
+
+long wxWebViewIE::FindNext(int direction)
+{
+    //Don't bother if we have no pointers set.
+    if(m_findPointers.empty())
+    {
+        return wxNOT_FOUND;
+    }
+    //Manage the find position and do some checks.
+    if(direction > 0)
+    {
+        m_findPosition++;
+    }
+    else
+    {
+        m_findPosition--;
+    }
+
+    if(m_findPosition >= (signed)m_findPointers.size())
+    {
+        if(m_findFlags & wxWEB_VIEW_FIND_WRAP)
+        {
+            m_findPosition = 0;
+        }
+        else
+        {
+            m_findPosition--;
+            return wxNOT_FOUND;
+        }
+    }
+    else if(m_findPosition < 0)
+    {
+        if(m_findFlags & wxWEB_VIEW_FIND_WRAP)
+        {
+            m_findPosition = m_findPointers.size()-1;
+        }
+        else
+        {
+            m_findPosition++;
+            return wxNOT_FOUND;
+        }
+    }
+    //some variables to use later on.
+    IHTMLElement *body_element;
+    IHTMLBodyElement *body;
+    IHTMLTxtRange *range = NULL;
+    IMarkupServices *pIMS;
+    IHTMLDocument2 *document = GetDocument();
+    long ret = -1;
+    //Now try to create a range from the body.
+    if(SUCCEEDED(document->get_body(&body_element)))
+    {
+        if(SUCCEEDED(body_element->QueryInterface(IID_IHTMLBodyElement,(void**)&body)))
+        {
+            if(SUCCEEDED(body->createTextRange(&range)))
+            {
+                //So far so good, now we try to position our find pointers.
+                if(SUCCEEDED(document->QueryInterface(IID_IMarkupServices,(void **)&pIMS)))
+                {
+                    IMarkupPointer *begin = m_findPointers[m_findPosition].begin, *end = m_findPointers[m_findPosition].end;
+                    if(pIMS->MoveRangeToPointers(begin,end,range) == S_OK && range->select() == S_OK)
+                    {
+                        ret = m_findPosition;
+                    }
+                    pIMS->Release();
+                }
+                range->Release();
+            }
+            body->Release();
+        }
+        body_element->Release();
+    }
+    document->Release();
+    return ret;
+}
+
+void wxWebViewIE::FindClear()
+{
+    //Reset find variables.
+    m_findText.Empty();
+    m_findFlags = wxWEB_VIEW_FIND_DEFAULT;
+    m_findPosition = -1;
+
+    //The m_findPointers contains pointers for the found text.
+    //Since it uses ref counting we call release on the pointers first
+    //before we remove them from the vector. In other words do not just
+    //remove elements from m_findPointers without calling release first
+    //or you will get a memory leak.
+    size_t count = m_findPointers.size();
+    for(size_t i = 0; i < count; i++)
+    {
+        m_findPointers[i].begin->Release();
+        m_findPointers[i].end->Release();
+    }
+    m_findPointers.clear();
+}
+
 bool wxWebViewIE::EnableControlFeature(long flag, bool enable)
 {
 #if wxUSE_DYNLIB_CLASS
@@ -989,6 +1270,8 @@ void wxWebViewIE::onActiveXEvent(wxActiveXEvent& evt)
             }
             //Reset as we are done now
             m_historyLoadingFromList = false;
+            //Reset the find values.
+            FindClear();
             // TODO: set target parameter if possible
             wxString target = wxEmptyString;
             wxWebViewEvent event(wxEVT_COMMAND_WEB_VIEW_LOADED, GetId(),