Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there an event that fires when DOM is modified in MSHTML IE8?

Trying to detect if new elements are added or removed from the DOM in MSHTML. Is there such event that will fire?

http://msdn.microsoft.com/en-us/library/aa741877(v=VS.85).aspx

In IE9 there is IDOMMutationEvent::initMutationEvent

http://msdn.microsoft.com/en-us/library/ff975905(v=vs.85).aspx

like image 457
GeorgeU Avatar asked Feb 24 '11 18:02

GeorgeU


1 Answers

Yes, it is possible now in IE8, though it is not part of the MSHTML event structure, but Accessibility.

Trigger (EVENT_OBJECT_REORDER) is new in IE8 - See http://blogs.msdn.com/b/ie/archive/2008/12/10/new-accessibility-features-in-ie8.aspx?PageIndex=7

We use it with out BHO, but you could equally hook outside of IE if you choose.

BHOClass::BHOClass()
{ 
if( TrackDHTML ) {
// end event is not used so +1.
// out of process notifications from accessibility
    m_eHook = ::SetWinEventHook(EVENT_OBJECT_REORDER, EVENT_OBJECT_REORDER+1, 0, MSAALib_WinEventProc, GetCurrentProcessId(), GetCurrentThreadId(), WINEVENT_OUTOFCONTEXT );
// in process injecting the dll into IE
//  m_eHook = ::SetWinEventHook(EVENT_OBJECT_REORDER, EVENT_OBJECT_REORDER+1, GetModuleHandle(L"yourhook.dll"), MSAALib_WinEventProc, GetCurrentProcessId(), GetCurrentThreadId(), WINEVENT_INCONTEXT );
}
}

And here is how you might look at the accessibility and get the document/browser

static void CALLBACK MSAALib_WinEventProc(HWINEVENTHOOK hook, 
  DWORD event, 
  HWND hwnd,  // this appears to be the hwnd for the tab and not the specific frame
  LONG idObject,  
  LONG idChild,
  DWORD dwEventThread, // the thread being watched that triggered this call
  DWORD dwmsEventTime)
{
if( hwnd != NULL // exclude most mouse move 
    && ( OBJID_WINDOW == idObject ) // || OBJID_CLIENT == idObject )
    )
{ 
    switch( event ) {
        case EVENT_OBJECT_REORDER: break;
        case EVENT_OBJECT_SHOW: break;
        case EVENT_OBJECT_HIDE: break;
        default:
            return;
    }

    Log(L"Event START - (%ld) object %ld on window(0x%x)%ld thread (0x%x)%ld\n", event, idObject, hwnd, hwnd, dwEventThread, dwEventThread);
    CComPtr<IAccessible> acc;
    VARIANT varChild;
    AccessibleObjectFromEvent(hwnd, idObject, idChild, &acc, &varChild);
    if( acc ) {
        // step 1 - change from Accessibility interface to html to check we have right type of reorder message
        CComPtr<IServiceProvider> provider;
        HRESULT hr = acc->QueryInterface(IID_IServiceProvider,(LPVOID *)&provider);
        if( SUCCEEDED(hr) && provider ){
            CComPtr<IHTMLElement> spElement;
            hr = provider->QueryService(IID_IHTMLElement,IID_IHTMLElement,(LPVOID *)&spElement);

            if( spElement ) {
                // step 2 - for this doc element get the service provider and then the browser element
                CComPtr<IServiceProvider> provider2;
                HRESULT hr = spElement->QueryInterface(IID_IServiceProvider,(LPVOID *)&provider2);
                CComPtr<IServiceProvider> provider3;
                if( provider2 )
                    hr = provider2->QueryService(SID_STopLevelBrowser,IID_IServiceProvider,(LPVOID *)&provider3);
                CComPtr<IWebBrowser2> browser;
                if( provider3 )
                    hr = provider3->QueryService(SID_SWebBrowserApp,IID_IWebBrowser2,(LPVOID *)&browser);

                if( browser ) {
                    // step 3 - Do stuff 
                }
            }
        }
    }
    Log(L"Event DONE - (%ld) object %ld on window(0x%x)%ld thread (0x%x)%ld\n", event, idObject, hwnd, hwnd, dwEventThread, dwEventThread);
}
}
like image 123
Greg Domjan Avatar answered Sep 23 '22 20:09

Greg Domjan