浏览器控件的重绘问题

 

 

在有些情况下,窗口内嵌的浏览器控件不能及时重绘。例如,我们建立一个"消息提示窗",采用浏览器控件显示消息的内容。当我们采用AnimateWindow进行动画显示时,浏览器控件会显示一片空白。下面我们探讨浏览器控件的重绘问题。

  1.     重现场景。

    // 生成一个窗口(略)
    HWND hwnd = 窗口handle.

    // 内嵌浏览器控件。
    ::AtlAxCreateControlEx(L“about:blank”,hwnd,NULL,NULL,(IUnknown  ** ) & pUnkControl);

    ...

    // 窗口动画。
    // 为了程序的兼容性,当AnimateWindow失败时,要调用传统的ShowWindow。
    if ( ! ::AnimateWindow(hwnd, 200 ,AW_SLIDE  |  AW_VER_NEGATIVE))
    {
        ::ShowWindow(hwnd,SW_SHOW);
    }

  2. 重绘的目标。

    一个浏览器控件的窗口层次如下:
    --Shell Embedding
    ----Shell DocObject View
    ------Internet Explorer_Server

    我们需要重绘的目标是类名为“Internet Explorer_Server”的窗口句柄。为了支持最新的vista系统,不能简单地通过IWebBrowser2->get_HWND取得窗口句柄。下面,我们通过AtlAxCreateControlEx返回的pUnkControl,取得“Shell Embedding”,再取得“Internet Explorer_Server”。 

    取得“Shell Embedding”:
        HWND hwnd;
        
    if (pUnkControl != NULL)
        
    {
            CComPtr
    <IWebBrowser2> pWebBrowser2;
            pUnkControl
    ->QueryInterface(IID_IWebBrowser2,(void**)&pWebBrowser2);
            
    if(pWebBrowser2!=NULL)
            
    {
                
    ////这句代码在vista下会失败。
                //hr=pWebBrowser2->get_HWND((SHANDLE_PTR*)&hwnd);

                
    ////这一段代码可直接取得HWND,只是没有正式的文档说明,网上也没见相关的讨论。
                //CComPtr pow;
                
    //pWebBrowser2->QueryInterface(IID_IOleWindow,(void**)&pow);
                
    //if(pow!=NULL)
                
    //{
                
    //    pow->GetWindow(&hwnd);
                
    //}

                
    //采用通行的方法。
                CComPtr<IServiceProvider> psp;
                pWebBrowser2
    ->QueryInterface(IID_IServiceProvider,(void**)&psp);
                
    if(psp!=NULL)
                
    {
                    CComPtr
    <IOleWindow> pow;
                    psp
    ->QueryService(SID_SShellBrowser,IID_IOleWindow, (void**)&pow);
                    
    if(pow!=NULL)
                    
    {
                        
    //this is “Shell Embedding”.
                        pow->GetWindow(&hwnd);    
                    }

                }

            }

        }

    取得“Internet Explorer_Server”:
    HWND __getWebBrowserHwnd(HWND hwndShell)
    {
        
    //
        if(hwndShell==NULL)
            
    return NULL;

        
    //loop
        TCHAR szClassName[MAX_PATH];
        HWND hwnd
    =hwndShell;
        
    while(true)
        
    {
            
    //
            ::GetClassName(hwnd,szClassName,MAX_PATH);
            
    if(::_wcsicmp(L"Internet Explorer_Server",szClassName)==0)
            
    {
                
    return hwnd;
            }

            
            
    //
            hwnd=::GetWindow(hwnd,GW_CHILD);
            
    if(hwnd==NULL)
                
    break;
        }


        
    return NULL;
    }

  3. 重绘的时机。
    窗口动画将执行一段指定的时间。用户要看到的是最后的页面内容,因此不必在动画过程中启动重绘,而是在动画完成之后进行。那么怎样才知道AnimateWindow结束了呢?幸运的是,AnimateWindow采用的是同步返回(与AJAX中流行的异步调用思想是不同的。)。也就是说,当动画执行完毕后,AnimateWindow才返回。因此,重绘的时机是在AnimateWindow之后。

             // redraw the web page.
            HWND hwnd = __getWebBrowserHwnd(hwndShell);

            
    //
             if (hwnd != NULL)
            
    {
                ::InvalidateRect(hwnd,NULL,TRUE);
                ::UpdateWindow(hwnd);
            }

 

你可能感兴趣的:(VC++,Internet,Explorer控件)