在 MSHTML IE8 中修改 DOM 时是不是会触发事件?

Posted

技术标签:

【中文标题】在 MSHTML IE8 中修改 DOM 时是不是会触发事件?【英文标题】:Is there an event that fires when DOM is modified in MSHTML IE8?在 MSHTML IE8 中修改 DOM 时是否会触发事件? 【发布时间】:2011-07-03 19:11:12 【问题描述】:

尝试检测是否在 MShtml 中从 DOM 中添加或删除了新元素。有这样的事件会触发吗?

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

在 IE9 中有 IDOMMutationEvent::initMutationEvent

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

【问题讨论】:

您是否正在使用从 WBc 获取的 MSHTML 对象集? 【参考方案1】:

不,但是如果你通过像 JQuery you can fake the event by yourself 这样的类库来修改 DOM。

【讨论】:

我不想修改 DOM。我试图检测 DOM 何时被修改,而不是通过 javascript。我在应用程序中托管了 MSHTML。 如果您的容器处于设计模式,您可以使用 IMarkupContainer2::CreateChangeLog,否则您可以使用 IDispatchEx 覆盖每个 DOM 更改方法/属性(appendchild、outerhtml、innerhtml、text、style 等)每个元素【参考方案2】:

WebBrowser1.Document.AttachEventHandler()怎么样?

【讨论】:

在IE8上好像没有任何DOM相关的事件【参考方案3】:

是的,现在可以在 IE8 中使用,尽管它不是 MSHTML 事件结构的一部分,而是可访问性。

触发器 (EVENT_OBJECT_REORDER) 是 IE8 中的新功能 - 请参阅 http://blogs.msdn.com/b/ie/archive/2008/12/10/new-accessibility-features-in-ie8.aspx?PageIndex=7

我们在不使用 BHO 的情况下使用它,但如果您愿意,您同样可以在 IE 之外使用。

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 );


以下是您如何看待可访问性并获取文档/浏览器

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);


【讨论】:

这有点晚了,但是有没有办法在 JavaScript 中挂钩这个事件?

以上是关于在 MSHTML IE8 中修改 DOM 时是不是会触发事件?的主要内容,如果未能解决你的问题,请参考以下文章

IE8部分兼容问题及解决方法

为什么说js操作DOM很慢

前端性能优化之DOM

读JS高性能总结——DOM编程

为啥以下创建 DOM 元素的方式不适用于 IE7 和 IE8 中的 jQuery?

js原生dom方法总结