1. 程式人生 > WINDOWS開發 >WPF 使用Win32API 讓控制元件置於WebBrowser上方

WPF 使用Win32API 讓控制元件置於WebBrowser上方

原文:WPF 使用Win32API 讓控制元件置於WebBrowser上方

WPF中Webbrowser控制元件使用HwndHost所以webbrowser會在所有控制元件的前方。所以webbrowser會覆蓋所有同級的控制元件。

技術分享圖片

現在通過使用Win32API 可以避免這個情況。

最主要的就是這幾個Win32API:

技術分享圖片
 [DllImport("user32.dll")]
        public static extern bool SetWindowRgn(IntPtr hWnd,IntPtr hRgn,bool redraw);
[DllImport("gdi32.dll
")] public static extern IntPtr CreateRectRgn(int Left,int Top,int RectRightBottom_X,int RectRightBottom_Y); [DllImport("gdi32.dll")] public static extern int CombineRgn(IntPtr hrgnDst,IntPtr hrgnSrc1,IntPtr hrgnSrc2,int iMode);
[DllImport("GDI32.dll")]
public static extern bool DeleteObject(IntPtr objectHandle);
技術分享圖片

適當說一下:

setwindowrgn就是設定有效繪圖區域。

createrectrgn是建立矩形

combinergn這個就是融合兩個矩形,可以並集,交集以及Src1中不包括Src2的部分,最終結果會在hrgnDst中。

總的來說就是利用webbrowser的父級控制元件的sizechanged事件來不斷的設定有效繪圖區域。

我就直接上程式碼了,

Win32API類

技術分享圖片
 [DllImport("user32.dll")]
        public static extern bool SetWindowRgn(IntPtr hWnd,bool redraw);
        
/// <summary> /// 建立一個矩形,本來四個引數均為x1 y1 x2 y2 意思為左上角X1,Y1座標,右下角X2,Y2座標,但是為了方便WPF使用我則是改了 /// left意味矩形和左邊的距離 /// top意味著矩形和頂邊距離 /// rectrightbottom_x意味著矩形右下角的X座標 /// rectrightbottom_y意味著矩形右下角的Y座標 /// </summary> /// <param name="Left"></param> /// <param name="Top"></param> /// <param name="RectRightBottom_X"></param> /// <param name="RectRightBottom_Y"></param> /// <returns></returns> [DllImport("gdi32.dll")] public static extern IntPtr CreateRectRgn(int Left,int RectRightBottom_Y);
[DllImport("GDI32.dll")]
public static extern bool DeleteObject(IntPtr objectHandle);
[DllImport(
"gdi32.dll")] public static extern int CombineRgn(IntPtr hrgnDst,int iMode); //合併選項: //RGN_AND = 1; //RGN_OR = 2; //RGN_XOR = 3; //RGN_DIFF = 4; //RGN_COPY = 5; {複製第一個區域}
技術分享圖片

附加屬性類:

技術分享圖片
class ATCH
    {
        public static readonly DependencyProperty PanelProperty = DependencyProperty.RegisterAttached("Panel",typeof(Panel),typeof(ATCH),new PropertyMetadata(null));

        public static void SetPanel(DependencyObject d,Panel value) => d.SetValue(PanelProperty,value);

        public static Panel GetPanel(DependencyObject d) => (Panel)d.GetValue(PanelProperty);


        public static readonly DependencyProperty NameProperty = DependencyProperty.RegisterAttached("Name",typeof(FrameworkElement),new PropertyMetadata(null,new PropertyChangedCallback(OnNamePropertyChanged)));

        public static void SetName(DependencyObject d,FrameworkElement value) => d.SetValue(NameProperty,value);

        public static FrameworkElement GetName(DependencyObject d) => (FrameworkElement)d.GetValue(NameProperty);


        private static void OnNamePropertyChanged(DependencyObject d,DependencyPropertyChangedEventArgs e)
        {
            var b = d.GetValue(PanelProperty);
            if (b is null||! (b is Panel)||e.NewValue is null)
                return;
            var panel = b as Panel;
            var web   =  d as WebBrowser;
            var ui = e.NewValue as FrameworkElement;
            SetRect(panel,web,ui);
            panel.SizeChanged += (sender,args) =>
            {
                SetRect(panel,ui);
            };

        }
       private static IntPtr C1;
        private static void SetRect(Panel panel,WebBrowser web,FrameworkElement ui)
        {
            IntPtr handle = web.Handle;
            Win32API.DeleteObject(C1);
            Win32API.SetWindowRgn(handle,IntPtr.Zero,true);

            Rect PanelRect = new Rect(new Size(panel.ActualWidth,panel.ActualHeight));

             C1 = Win32API.CreateRectRgn((int)0,(int)0,(int)PanelRect.BottomRight.X,(int)PanelRect.BottomRight.Y);

            Rect UIRect = new Rect(new Size(ui.ActualWidth,ui.ActualHeight));

            var D1 = (int)ui.TransformToAncestor(panel).Transform(new Point(0,0)).X;

            var D2 = (int)ui.TransformToAncestor(panel).Transform(new Point(0,0)).Y;

            var D3 = (int)(D1 + UIRect.Width);

            var D4 = (int)(D2 + UIRect.Height);

            var C2 = Win32API.CreateRectRgn(D1,D2,D3,D4);

            Win32API.CombineRgn(C1,C1,C2,4);

            Win32API.SetWindowRgn(handle,true);
        }
    }
技術分享圖片

xaml程式碼

 <Grid>
        <WebBrowser   Source="http://www.baidu.com"  local:ATCH.Panel="{Binding RelativeSource={RelativeSource Mode=FindAncestor,AncestorLevel=1,AncestorType=Grid}}" local:ATCH.Name="{Binding ElementName=btn}"/>
        <Button  x:Name="btn" Height="50" Width="100" Content="覆蓋測試"  />
    </Grid>

截圖1:

技術分享圖片

截圖2:

技術分享圖片