比方说我sink了DOCUMENTCOMPLETE,在页面加载完成后就产生下列错误。
错误:0xC0000005: Access violation reading location 0x00000024.HRESULT Lock() throw()
{
    EnterCriticalSection(&m_sec);    // 这里产生的
    return S_OK;
}应该是临界区域未初始化造成的。但是调用这个应该是ATL内部的事情。如果是BeforeNavigate2事件,那就会在页面加载之前就产生上面的错误。原代码环境是,我只是单创建了一个sink类来响应DISPID_DOCUMENTCOMPLETE事件,
参考http://support.microsoft.com/kb/194179/en-usIWebBrowser2接口创建成功,
DispEventAdvise连接返回成功,
单就是对应事件产生后就报错了。很是想不通……

解决方案 »

  1.   

    InitializeCriticalSection(&m_sec) l了?
      

  2.   


    #include <windows.h>
    #include <atlbase.h>
    #include <atlwin.h>
    #include <ExDispID.h>const UINT ID_WEBBROWSER = 100;//
    //
    //
    class CMainWindow : public CWindowImpl<CMainWindow>,
                        public IDispEventImpl< ID_WEBBROWSER, CMainWindow >
    {
    public:
        CMainWindow()
        {
            CWndClassInfo &wci = GetWndClassInfo();        if( !wci.m_atom )
            {
                // 使用系统光标
                wci.m_bSystemCursor = TRUE;
            }        // 初始化
            m_AxWindow = NULL;
            m_pWebBrowser2 = NULL;
        }    virtual ~CMainWindow(){}
        // 消息映射
        BEGIN_MSG_MAP(CMainWindow)
            MESSAGE_HANDLER( WM_DESTROY, OnDestroy )
            MESSAGE_HANDLER(WM_CREATE, OnCreate)
        END_MSG_MAP()    BEGIN_SINK_MAP(CMainWindow)
         //Make sure the Event Handlers have __stdcall calling convention
         SINK_ENTRY( ID_WEBBROWSER, DISPID_DOCUMENTCOMPLETE, OnDocumentComplete )
        END_SINK_MAP()    // Event handler
     void __stdcall OnDocumentComplete( IDispatch *, VARIANT* )
     {
            
     }private:
        LRESULT OnCreate(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
        {
            RECT rect;
            GetClientRect(&rect);
            // 创建宿主窗口
            HWND hWndContainer = m_AxWindow.Create( m_hWnd, rect, NULL, WS_CHILD | WS_VISIBLE | WS_VSCROLL | WS_HSCROLL, 0, ID_WEBBROWSER );        if( !hWndContainer )
                return -1;        // 创建控件,初始化它,并且依附到宿主窗口
            HRESULT hr;
            hr = m_AxWindow.CreateControl( L"http://www.microsoft.com" );        if( FAILED( hr ) )
                return -1;        // 得到IWebBrowser2接口
            hr = m_AxWindow.QueryControl( IID_IWebBrowser2, (void**)&m_pWebBrowser2 );        if( SUCCEEDED(hr) )
            {
                // 确保COM对象对应的pUnk实现IProvideClassInfo2或是IPersist*
                // 当IDispEventImpl以两个参数形式被继承时,调用这个方法提取关于源类型库的信息
                hr = AtlGetObjectSourceInterface( m_pWebBrowser2, &m_libid, 
                                                  &m_iid, &m_wMajorVerNum, &m_wMinorVerNum );            if( FAILED(hr) )
                    return -1;            // 连接接收器和来源,m_pWebBrowser2是源COM对象
          hr = DispEventAdvise(m_pWebBrowser2, &m_iid);
                if( FAILED(hr) )
                    return -1;            CComBSTR url = L"http://www.microsoft.com";            hr = m_pWebBrowser2->Navigate( url,0,0,0,0 );            if( FAILED(hr) )
                    return -1;
            }        return 0;
        }    LRESULT OnDestroy(UINT , WPARAM , LPARAM , BOOL&)
        {
            // disconnect from source if connected
      if( m_dwEventCookie != 0xFEFEFEFE )
          DispEventUnadvise(m_pWebBrowser2, &m_iid);        // 释放缓存的COM
            m_pWebBrowser2.Release();        PostQuitMessage(0);
            return 0;
        }private:
        //
        CAxWindow m_AxWindow;
        CComPtr<IWebBrowser2> m_pWebBrowser2; // 用于缓存COM接口
    };//
    //
    //
    int APIENTRY _tWinMain(HINSTANCE hInstance,
                         HINSTANCE hPrevInstance,
                         LPTSTR    lpCmdLine,
                         int       nCmdShow)
    {
     UNREFERENCED_PARAMETER(hPrevInstance);
     UNREFERENCED_PARAMETER(lpCmdLine);
     
     CMainWindow wnd;    wnd.Create( NULL, NULL, NULL, WS_OVERLAPPEDWINDOW );    if( !wnd )
            return FALSE;    wnd.CenterWindow();
        wnd.ShowWindow( nCmdShow );
        wnd.UpdateWindow();    MSG msg; // Main message loop:
     while (GetMessage(&msg, NULL, 0, 0))
     {
      TranslateMessage(&msg);
      DispatchMessage(&msg);
     } return (int) msg.wParam;
    }
     “使用ATL”设置成“动态链接到ATL”。以上代码是可以直接编译,我所描述的问题就会出现了。
      

  3.   

    #include <windows.h>
    #include <atlbase.h>
    CComModule _Module;#include <atlcom.h>
    #include <atlwin.h>
    #include <ExDisp.h>
    #include <ExDispId.h>const UINT ID_WEBBROWSER = 100;//
    //
    //
    class CMainWindow : public CWindowImpl<CMainWindow>,
                        public IDispEventImpl< ID_WEBBROWSER, CMainWindow >
    {
    public:
        CMainWindow()
        {
            CWndClassInfo &wci = GetWndClassInfo();        if( !wci.m_atom )
            {
                // 使用系统光标
                wci.m_bSystemCursor = TRUE;
            }        // 初始化
            m_AxWindow = NULL;
            m_pWebBrowser2 = NULL;
        }    virtual ~CMainWindow(){}
        // 消息映射
        BEGIN_MSG_MAP(CMainWindow)
            MESSAGE_HANDLER( WM_DESTROY, OnDestroy )
            MESSAGE_HANDLER(WM_CREATE, OnCreate)
        END_MSG_MAP()    BEGIN_SINK_MAP(CMainWindow)
         //Make sure the Event Handlers have __stdcall calling convention
         SINK_ENTRY( ID_WEBBROWSER, DISPID_DOCUMENTCOMPLETE, OnDocumentComplete )
        END_SINK_MAP()    // Event handler
     void __stdcall OnDocumentComplete( IDispatch *, VARIANT* )
     {
           MessageBox(TEXT("OnDocumentComplete"),TEXT("Message"),MB_ICONINFORMATION);
     }private:
        LRESULT OnCreate(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
        {
            RECT rect;
            GetClientRect(&rect);
    AtlAxWinInit();
            // 创建宿主窗口
            HWND hWndContainer = m_AxWindow.Create( m_hWnd, rect, NULL, WS_CHILD | WS_VISIBLE | WS_VSCROLL | WS_HSCROLL, 0, ID_WEBBROWSER );        if( !hWndContainer )
                return -1;        // 创建控件,初始化它,并且依附到宿主窗口
            HRESULT hr;
            hr = m_AxWindow.CreateControl( L"http://www.sohu.com" );        if( FAILED( hr ) )
                return -1;        // 得到IWebBrowser2接口
            hr = m_AxWindow.QueryControl( IID_IWebBrowser2, (void**)&m_pWebBrowser2 );        if( SUCCEEDED(hr) )
            {
                // 确保COM对象对应的pUnk实现IProvideClassInfo2或是IPersist*
                // 当IDispEventImpl以两个参数形式被继承时,调用这个方法提取关于源类型库的信息
                hr = AtlGetObjectSourceInterface( m_pWebBrowser2, &m_libid, 
                                                  &m_iid, &m_wMajorVerNum, &m_wMinorVerNum );            if( FAILED(hr) )
                    return -1;            // 连接接收器和来源,m_pWebBrowser2是源COM对象
          hr = DispEventAdvise(m_pWebBrowser2, &m_iid);
                if( FAILED(hr) )
                    return -1;            if( FAILED(hr) )
                    return -1;
            }        return 0;
        }    LRESULT OnDestroy(UINT , WPARAM , LPARAM , BOOL&)
        {
            // disconnect from source if connected
      if( m_dwEventCookie != 0xFEFEFEFE )
          DispEventUnadvise(m_pWebBrowser2, &m_iid);        // 释放缓存的COM
            m_pWebBrowser2.Release();        PostQuitMessage(0);
            return 0;
        }private:
        //
        CAxWindow m_AxWindow;
        CComPtr<IWebBrowser2> m_pWebBrowser2; // 用于缓存COM接口
    };//
    //
    //
    int APIENTRY _tWinMain(HINSTANCE hInstance,
                         HINSTANCE hPrevInstance,
                         LPTSTR    lpCmdLine,
                         int       nCmdShow)
    {
     UNREFERENCED_PARAMETER(hPrevInstance);
     UNREFERENCED_PARAMETER(lpCmdLine);
     
     _Module.cbSize = sizeof(_Module);
     AtlModuleInit(&_Module,NULL,hInstance); CMainWindow wnd; RECT rect = {0,0,480,320};
        wnd.Create( NULL, rect, NULL, WS_OVERLAPPEDWINDOW );    if( !wnd )
            return FALSE;    wnd.CenterWindow();
        wnd.ShowWindow( nCmdShow );
        wnd.UpdateWindow();    MSG msg; // Main message loop:
     while (GetMessage(&msg, NULL, 0, 0))
     {
      TranslateMessage(&msg);
      DispatchMessage(&msg);
     } return (int) msg.wParam;
    }