WPF 中 WindowsFormsHost 之 AirspacePanel

        项目中使用WPF开发客户端,系统需要内嵌C++开发的控件,在WPF中内嵌Winfrom或者Win32K控件都需要 包裹在 WindowsFormsHost 中,很顺利的将控件显示出来。如下:

 

     后续开发中,需要在当前页面,开发一个弹框功能。如下:

      So ! ! !

      弹出框被遮挡了,查了资料在  https://github.com/chris84948/AirspaceFixer 找到其中一种解决方案,该方案是在弹出框之前设置 WindowsFormsHost  显示一张截图替代,关闭弹出框之后替换回来。

     具体实现如下:

                                                                                     

  1  internal class AirspacePanel : System.Windows.Controls.ContentControl
  2     {
  3         public static readonly DependencyProperty FixAirspaceProperty =
  4             DependencyProperty.Register("FixAirspace",
  5                                         typeof(bool),
  6                                         typeof(AirspacePanel),
  7                                         new FrameworkPropertyMetadata(false, new PropertyChangedCallback(OnFixAirspaceChanged)));
  8 
  9         public bool FixAirspace
 10         {
 11             get { return (bool)GetValue(FixAirspaceProperty); }
 12             set { SetValue(FixAirspaceProperty, value); }
 13         }
 14 
 15 
 16         private System.Windows.Controls.Image _airspaceScreenshot;
 17         private System.Windows.Controls.ContentControl _airspaceContent;
 18         private float _scalingFactor;
 19 
 20         static AirspacePanel()
 21         {
 22             DefaultStyleKeyProperty.OverrideMetadata(typeof(AirspacePanel), new FrameworkPropertyMetadata(typeof(AirspacePanel)));
 23         }
 24 
 25         public AirspacePanel()
 26         {
 27             Loaded += (_, __) => GetScalingFactor();
 28         }
 29 
 30         public override void OnApplyTemplate()
 31         {
 32             base.OnApplyTemplate();
 33 
 34             _airspaceContent = GetTemplateChild("PART_AirspaceContent") as ContentControl;
 35             _airspaceScreenshot = GetTemplateChild("PART_AirspaceScreenshot") as System.Windows.Controls.Image;
 36         }
 37 
 38         private static void OnFixAirspaceChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
 39         {
 40             var panel = d as AirspacePanel;
 41             
 42 
 43 
 44             if (panel == null || panel.ActualWidth == 0 || panel.ActualHeight == 0 || PresentationSource.FromVisual(panel) == null)
 45                 return;
 46 
 47             if ((bool)e.NewValue)
 48             {
 49                
 50                 panel._airspaceContent.Visibility = Visibility.Hidden;
 51                 panel._airspaceScreenshot.Visibility = Visibility.Visible;
 52             }
 53             else
 54             {
 55                 panel._airspaceContent.Visibility = Visibility.Visible;
 56                 panel._airspaceScreenshot.Visibility = Visibility.Hidden;
 57                 panel._airspaceScreenshot.Source = null;
 58             }
 59         }
 60 
 61   
 62         private void CreateScreenshotFromContent()
 63         {
 64             System.Windows.Point upperLeftPoint = _airspaceContent.PointToScreen(new System.Windows.Point(0, 0));
 65             var bounds = new System.Drawing.Rectangle((int)(upperLeftPoint.X * _scalingFactor),
 66                                                       (int)(upperLeftPoint.Y * _scalingFactor),
 67                                                       (int)(_airspaceContent.RenderSize.Width * _scalingFactor),
 68                                                       (int)(_airspaceContent.RenderSize.Height * _scalingFactor));
 69 
 70             using (var bitmap = new System.Drawing.Bitmap((int)bounds.Width, (int)bounds.Height))
 71             {
 72                 using (var g = System.Drawing.Graphics.FromImage(bitmap))
 73                 {
 74                     g.CopyFromScreen(new System.Drawing.Point(bounds.Left, bounds.Top),
 75                                      System.Drawing.Point.Empty,
 76                                      new System.Drawing.Size((int)bounds.Width, (int)bounds.Height));
 77                 }
 78 
 79                 _airspaceScreenshot.Source = GetImageSourceFromBitmap(bitmap);
 80             }
 81         }
 82 
 83   
 84         [DllImport("gdi32.dll")]
 85         static extern int GetDeviceCaps(IntPtr hdc, int nIndex);
 86         private void GetScalingFactor()
 87         {
 88             var g = System.Drawing.Graphics.FromHwnd(IntPtr.Zero);
 89             IntPtr desktop = g.GetHdc();
 90             int LogicalScreenHeight = GetDeviceCaps(desktop, 10);
 91             int PhysicalScreenHeight = GetDeviceCaps(desktop, 117);
 92 
 93             float ScreenScalingFactor = (float)PhysicalScreenHeight / (float)LogicalScreenHeight;
 94 
 95             _scalingFactor = ScreenScalingFactor; // 1.25 = 125%
 96         }
 97 
 98         public ImageSource GetImageSourceFromBitmap(System.Drawing.Bitmap bitmap)
 99         {
100             using (var memory = new MemoryStream())
101             {
102                 bitmap.Save(memory,ImageFormat.Png);
103                 memory.Position = 0;
104                 System.Windows.Media.Imaging.BitmapImage bitmapImage = new BitmapImage();
105                 bitmapImage.BeginInit();
106                 bitmapImage.StreamSource = memory;
107                 bitmapImage.CacheOption = BitmapCacheOption.OnLoad;
108                 bitmapImage.EndInit();
109                 return bitmapImage;
110             }
111         }
112     }

 

         

 

 

      设置样式:

 1   <Style TargetType="{x:Type dwayneneed:AirspacePanel}">
 2             <Setter Property="Template">
 3                 <Setter.Value>
 4                     <ControlTemplate TargetType="{x:Type dwayneneed:AirspacePanel}">
 5 
 6                         <Grid HorizontalAlignment="{TemplateBinding HorizontalAlignment}"
 7                           VerticalAlignment="{TemplateBinding VerticalAlignment}">
 8                             <Image x:Name="PART_AirspaceScreenshot"
 9                                Visibility="Hidden" />
10 
11                             <ContentControl x:Name="PART_AirspaceContent"
12                                         Content="{TemplateBinding Content}" />
13                         </Grid>
14 
15                     </ControlTemplate>
16                 </Setter.Value>
17             </Setter>
18         </Style>

 

       包裹 WindowsFormsHost 

       

            <AirspacePanel x:Name="airspacePanel"  FixAirspace="{Binding FixAirspace}">

                  <WindowsFormsHost x:Name="host"  Visibility="Visible" />

             </AirspacePanel>

 

     弹窗之前设置 

  FixAirspace=true;

弹窗之后设置
  FixAirspace=false;

posted @ 2023-08-02 21:32  FranKie_Ming  阅读(132)  评论(0编辑  收藏  举报