crdx
crdx

Reputation: 1432

How do I detect when the content of a WebBrowser control has changed (in design mode)?

I'm using a WebBrowser control in design mode.

webBrowser1.DocumentText = "<html><body></body></html>";
doc = webBrowser1.Document.DomDocument as IHTMLDocument2;
doc.designMode = "On";

I have a save button that I would like to enable or disable depending on whether the contents of the control have changed.

I also need to know when the contents of the control have changed as I need to stop the user from navigating away from the control without accepting a confirmation message box stating that their changes will be lost.

I can't find any events that would let me know that the contents have changed.

Upvotes: 5

Views: 6652

Answers (4)

Coder12345
Coder12345

Reputation: 3753

This seems to work - QueryInterface() for IPersistFile interface and use IPersistFile::IsDirty method with the return value of S_OK (if dirty or if the design mode document has been modified).

You don't need to use IPersistFile::Load to load the contents into the web browser, WebBrowser->Navigate() will also work fine.

Note - there is a same IsDirty() method also in IPersistStream and IPersistStreamInit interfaces

I don't use C# but it should be relatively easy to rewrite.

bool IsEditorDirty(WebBrowser* WB)
    {
    // beware, if it fails to get Document and IPersistFile it will not register as dirty
    bool isdirty = false;

    IHTMLDocument2* pDoc2 = WB->Document;

    if (pDoc2) {
        IPersistFile* pPFile;

        if (pDoc2->QueryInterface(IID_IPersistFile, (void**)&diPFile) == S_OK) {
            isdirty = (pPFile->IsDirty() == S_OK);
            pPFile->Release();
            }
    
        pDoc2->Release();
        }

    return isdirty;
    }

Upvotes: 0

Sheng Jiang 蒋晟
Sheng Jiang 蒋晟

Reputation: 15281

QueryInterface() the document for IMarkupContainer2, then call IMarkupContainer2::RegisterForDirtyRange with your own implementation of IHTMLChangeSink. Your IHTMLChangeSink::Notify implementation will be called when a change is made.

Note: Do this after you set the design mode. The document gets reloaded and event hook get lost, if you toggle the design mode.

Upvotes: 3

Laynor
Laynor

Reputation: 1543

another solution, if you implement IDocHostUIHandler, you can use its method UpdateUI

Upvotes: 0

nxu
nxu

Reputation: 2272

There is no such event since DocumentText is a simple string. I would create a string variable storing the last saved text and check it at each KeyDown / MouseDown / Navigating event.

string lastSaved;

private void Form_Load(object sender, System.EventArgs e)
{
   // Load the form then save WebBrowser text
   this.lastSaved = this.webBrowser1.DocumentText;
}

private void webBrowser1_KeyDown(object sender, System.Windows.Forms.KeyEventArgs e)
{
    // Check if it changed
    if (this.lastSaved != this.webBrowser1.DocumentText)
    {
        // TODO: changed, enable save button
        this.lastSaved = this.webBrowser1.DocumentText;
    }
}

private void webBrowser1_Navigating(object sender, WebBrowserNavigatingEventArgs e)
{
    // Check if it changed
    if (this.lastSaved != this.webBrowser1.DocumentText)
    {
        // TODO: ask user if he wants to save
        // You can set e.Cancel = true to cancel loading the next page
    }
}

Upvotes: 3

Related Questions