Search code examples
c++winapicommshtmlie-automation

MSHTML: Callback on image insertion


Currently I am working on embedding a HTML editor into a C++ WinAPI application using the MSHTML component.

I got everything set up (activating editing mode, changing font face, etc.), but now I have to support inserting images. MSHTML already has support for it built in, but this support is - to my knowledge - not enough.

Somehow I need a way to intercept the insertion of images into the HTML-editor, since I have to create a list of images in the UI of our application. So, whenever the user uses the default-dialog of the MSHTML-component to insert an image or updates its source (e.g. from file://xyz.jpg to file://abc.jpg), I want my code to be notified.

I already looked at the conecpt of "Edit Designers", the implementation of IHTMLEditHost, or the DWebBrowserEvents2 interface. But nothing seems to do the trick.

Perhaps someone can give me a hint?


Solution

  • Okay,

    it looks like you cannot explicitly subscribe for specific changes of the document. What you can do is to create a so-called "Change Sink".

    Everytime you change the document, either by user input or programmatically, you can get a notification that "something" changed in your document. This can be done by implementing the IHTMLChangeSink interface and attaching it to the IMarkupContainer2 of the IHTMLDocument2.

    Example code (not complete):

    class CHTMLChangeSink : public IHTMLChangeSink
    {
        public:
            // Implement IUnknown: QueryInterface, AddRef, Release
            // Implement IHTMLChangeSink:
            HRESULT STDMETHODCALLTYPE Notify()
            {
                // Notify() is called everytime the document changes
                return S_OK;
            }
    };
    
    CHTMLChangeSink * pChangeSink = new CHTMLChangeSink();
    IHTMLDocument2 * pDoc; // lets suppose we already have it
    IMarkupContainer2 * pMarkupContainer = nullptr;
    if (pDoc->QueryInterface(IID_IMarkupContainer2, reinterpret_cast<void **>(&pMarkupContainer)) == S_OK) {
        DWORD dwCookie = 1;
        // registration is done here
        pMarkupContainer->RegisterForDirtyRange(pChangeSink, &dwCookie);
    }
    

    Please be aware, that the document has to be loaded completely (register for DIID_DWebBrowserEvents2::DocumentComplete).

    From now on, whenever a change in the document occurs, your Notify-method will be called and you can do further processing to find out what has changed (e.g. process the list of images in the document).

    Have fun!