WPF WebBrowser 不可見問題的解析[轉]


問題概述:

1.在Xaml中加入WebBrowser(不論是WPF中的控件,還是Winform中的控件)

2.設置Window Background="Transparent" AllowsTransparency="True"

結果:WebBroser中的內容將不可見。 

問題分析: 

本人當時一WPF菜鳥,根本無從下手。實乃WPF已廣為人知的問題。原因很簡單: 

1.所謂WPF中的WebBrowser控件實為利用MS WebBrowser 經過WPF封裝,其實質和Winform中的WebBrowser一樣無非是加入了一些簡單DependencyProperty,使其能夠在Xaml中進行配置,其使用看起來和其他WPF控件一致。其內核仍是基於Win32。

2.明白了WPF/Winform 中WebBrowser控件的實質,我們進入主題,眾所周知WPF所推崇的乃其划時代的圖形渲染技術,這里不做展開。大家明白WPF采用矢量技術,消除了頁面縮放過程中鋸齒現象。因此WPF實現了於分辨率無關。但是Win32的渲染技術卻非基於矢量技術。故WebBrowser的內在渲染和WPF有本質區別。

3.當我們設置Window Background="Transparent" AllowsTransparency="True" 以期實現玻璃窗口時WebBrowser不能完成WPF的渲染,因此出現如上所述WebBrowser內容不可見的問題。

 結論:

不能將非WPF元素(例如基於Win32的控件)放入WPF中進行渲染,否則,基於Win32的控件將渲染失敗,例如縮放失敗,顏色渲染失敗等等與矢量技術相關的屬性設置。對於本章問題,若要混合使用基於Win32的控件和WPF控件,並且要設置

Window Background="Transparent" AllowsTransparency="True" 以實現多主體支持,應該將Win32元素放入Win32窗口,達到分開渲染的目的。

 

解決方案:

1.不要將WebBrowser直接在在Xaml中使用, 用以簡單元素代替,如Canvas Grid Border等等Container皆可。用於定位

2.將WebBrowser,加為Form的child,自己封裝,實現例如縮放等自定義功能。

3.在Window,初始化的時候,實例化經過Form封裝的WebBrowser,並定位到步驟一中所述的Container。

 Sample Code:

Xaml:  

<Grid Name="IEcontainer" Grid.Column="0" Width="1006" Height="577"/>

 

 WebBrowser封裝:

 static class Win32

{

    [StructLayout(LayoutKind.Sequential)]

    public struct POINT

    {

       .......

    [DllImport("user32.dll")]

     internal static extern bool ClientToScreen(IntPtr hWnd, ref POINT lpPoint);

     [DllImport("user32.dll")]

    internal static extern bool MoveWindow(IntPtr hWnd, int X, int Y, int nWidth,int nHeight, bool bRepaint);

 };

 class WebBrowserOverlayWF

    {

        Window _owner;

        FrameworkElement _placementTarget;

        Form _form; // the top-level window holding the WebBrowser control

        WebBrowser _wb = new WebBrowser();

         .......................      

       public WebBrowserOverlayWF(FrameworkElement placementTarget)

        {

            _placementTarget = placementTarget;

            Window owner = Window.GetWindow(placementTarget);

            _owner = owner;

 

            _form = new Form();

            _form.ShowInTaskbar = false;

            _form.FormBorderStyle = FormBorderStyle.None;           

            _wb.Dock = DockStyle.Fill;

            _form.Controls.Add(_wb);

            _wb.ScrollBarsEnabled = false;

 

            owner.SizeChanged += delegate { OnSizeLocationChanged(); };

            owner.LocationChanged += delegate { OnSizeLocationChanged(); };

            _placementTarget.SizeChanged += delegate { OnSizeLocationChanged(); };

 

            if (owner.IsVisible)

                InitialShow();

            else

                owner.SourceInitialized += delegate{InitialShow(););

             ..........

        }

         void InitialShow()

        {

            NativeWindow owner = new NativeWindow();

            owner.AssignHandle(

                    ((HwndSource)HwndSource.FromVisual(_owner)).Handle);

            _form.Show(owner);

            owner.ReleaseHandle();

        }

    ...............       

    }

  Window Loaded:

   WebBrowserOverlayWF wbo = new WebBrowserOverlayWF(IEcontainer);

 拓展:

上例中演示了如何將基於Win32的控件封裝到WPF中,實現了縮放,和重定位的功能(篇幅限制,如需具體代碼,請聯系本人)。其實我們無意中已經涉及到了控件的封裝和重寫。今后將陸續和大家分享更多WPF控件封裝和重寫的技術。

原文: http://hi.baidu.com/leo_han/item/cd1debbf4dfbb3462bebe30a

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM