关于WPF空域的问题

简介: WPF开发时常会遇到空域问题,这个是神烦的一种现象

一、什么是空域

  1. 在顶层窗口中,您可以将每个包含互操作应用程序的技术之一的HWND概念化为有自己的“空间”。窗口内的每个像素恰好属于一个HWND,这构成了该HWND的空域。(严格来说,如果有一个以上的WPF高速公路,将会有一个以上的WPF空域,但是为了解释这个概念,假设在本主题给出的例子中只有一个)。空域概念意味着,在应用程序生命周期内,所有试图在该像素之上进行渲染的图层或其他窗口都必须属于同一互操作技术。试图在Win32上呈现WPF像素会导致不希望的结果,并且通过互操作API尽可能不被允许(这段话是抄的啦)这里有介绍,简单的来说就是不同的渲染技术导致了空域的产生,最常见现象,wpf 上放一个winform控件,你会发现winform控件悬浮于wpf 控件上方,或者设置AllowsTransparency = true 你使用的winform控件会透明 很蛋疼

二、我遇到空域问题

  1. 之前有个客户要做视频解决方案,要求是要在多个视频窗口上贴上标签,比如人员名称等,但是由于空域问题,导致贴图没有显示,贼烦人

三、我尝试解决办法

1.Microsoft.DwayneNeed https://microsoftdwayneneed.codeplex.com/ 怎么说呢 ,这个库我个人没觉得有多好用,因为视频小窗口特别多,用这个巨卡无比

2.尝试使用winform来包含wpf控件贴上去,这种也是可以,但是及不稳定,性能也极差无比,卡顿 拖影出现频率很高

3.尝试用popup来解决,但是单个视频窗口还行,如果多个视频窗口加载界面,不知为何总有个别popup弹不出来(未找到原因)

4.某视频软件sdk提供的demo,用window弹出界面show到指定位置,然后实时计算位置,这个方法可以实现,但是因为视频界面最多有十一个视频画面,每个画面有标题和控制面板两个部分,就是需要弹出20个windows,控制起来非常繁琐

5.方法4虽然没有完全解决我的问题,但是至少给我很大启发,仔细研究demo以及查阅资料,想到有没有一种办法,我把wpf window 作为一个usercontrol嵌入到wpf中,查阅官方文档发现一个HwndHost类,查阅官方文档这个类描述为将 Win32 window 托管为 Windows Presentation Foundation (WPF) 内容中的一个元素。这就很开心了,故开心采用此方法

四、解决方法的过程

HwndHost 是一个抽象类,如果要实现窗口托管,需要自己实现一个子类,如下:

public class THost : HwndHost

   {

       public const int GWL_STYLE = (-16);

       public const int WS_CHILD = 0x40000000;

       [DllImport("user32.dll")]

       public static extern int SetWindowLong(IntPtr hWnd, int nIndex, int dwNewLong);

       [DllImport("user32.dll")]

       static extern IntPtr SetParent(IntPtr hWndChild, IntPtr hWndNewParent);

       [DllImport("user32.dll", CharSet = CharSet.Auto)]

       private static extern int SetWindowPos(IntPtr hWnd, int hWndInsertAfter, int x, int y, int Width, int Height, int flags);

       private IntPtr ChildHandle = IntPtr.Zero;

       private IntPtr ParentHandle = IntPtr.Zero;

       private Window _window;

       public THost(Window window, IntPtr parentPtr)

       {

           _window = window;

           this.ChildHandle = (new WindowInteropHelper(_window)).Handle;

           //LogHelper.Write($"生成窗体------------{_window.Title}");

           ParentHandle = parentPtr;

       }

       [HandleProcessCorruptedStateExceptions]

       protected override HandleRef BuildWindowCore(HandleRef hwndParent)

       {

           HandleRef href = new HandleRef();

           if (ChildHandle != IntPtr.Zero)

           {

               SetWindowLong(this.ChildHandle, GWL_STYLE, WS_CHILD);

               SetParent(this.ChildHandle, hwndParent.Handle);

               href = new HandleRef(Application.Current.MainWindow, this.ChildHandle);

           }

           return href;

       }

       protected override void DestroyWindowCore(HandleRef hwnd)

       {

           _window = null;

           this.Dispose();

       }

   }

主要重写方法BuildWindowCore 和方法DestroyWindowCore 传入参数即为父类窗口handle ,wpf 传入mainwindow的handle即可,然后还有你弹出的window 的handle,这样基本可以完美解决,

五、总结

你以为这样就完事儿?微软的尿性告诉我没有这么简单,当我开开心心,去用户机器上尝试,发现卧槽 居然不行,,仔细一看win7,这可要了我老命,win10下完美运行拖动跟随都没有问题,win7不可以,经过漫长的解决方案查找,突然想起win7和win10区别,areo特效。。。,司马当做活马医,将用户桌面改成basic主题,可是还是不行,直到有一天,我想看看我拖动窗口他位置什么情况,因为之前弹出窗口一直设置了AllowsTransparency = true,这次我去掉它,卧槽 居然可以拖动跟随并且跟win10下基本一样,区别必须给你要传入的窗口设置一个颜色,

六、最后

win10情况下使用此方法基本没有问题

win7下需要特殊处理,首先不能应用areo效果,其次需要给嵌入的窗口设置一个背景色

这是我目前遇到的情况,希望可以给大家一些帮助,或者大家有更好的解决方案,也可以通过公众号发给我哦

转载注明https://dicgo.com/41.html

目录
相关文章
|
C# Windows
WPF设计の不规则窗体
原文:WPF设计の不规则窗体   我们在工作中,经常会需要画一些不规则的窗体,现在总结如下。 一、利用VisualBrush实现。这依赖于VisualBrush的特性,任何控件可以作为画刷,而画刷又可以作为背景。
944 0
|
C#
WPF窗体の投影效果
原文:WPF窗体の投影效果 有时候我们需要给WPF窗体加上一个毛边(投影效果) 我们可以在窗体下加上如下代码 然后需要给窗体设置一个border BorderThickness="20"  这时候阴影的效果也是方形的,我们可以在grid外边再加一个Border,并设置成圆角,颜色可以设置为透明。
1042 0
|
C#
WPF中的3D变换PlaneProjection
原文:WPF中的3D变换PlaneProjection 在UWP中有一个比较好用的伪3D变换PlaneProjection,可以以一种轻量级和非常简单的方式实现3D的效果。这种效果在Silverlight中也有这种变换,但在WPF中确一直没有提供。
861 0
|
C#
WPF 3D 模型旋转
原文:WPF 3D 模型旋转     WPF 是 Microsoft 在 Framework3.0 中支持的一种技术,它能作出很绚丽的界面,同时它也支持3D的操作。在3D操作主要包括平移(Translate)、旋转(Rotation)、缩放(Scale)。
1305 0
|
C#
【WPF】三维模型中的“照相机”
原文:【WPF】三维模型中的“照相机” WPF 部分支持三维模型,为啥说是部分支持?毕竟 WPF 的侧重点还是在应用开发上,虽然也有些游戏是用 WPF 开发的,不过,老周想啊,如果真要开发游戏,最好用专门的框架,WPF 应当用于开发应用功能的。
922 0
|
C# vr&ar
WPF 碰撞检测
原文:WPF 碰撞检测 have tested this, it worked, at least for me var x1 = Canvas.GetLeft(e1); var y1 = Canvas.
1202 0
WPF-WPF BitmapEffect (按钮凹凸效果)
原文:WPF-WPF BitmapEffect (按钮凹凸效果) BitmapEffect位图效果是简单的像素处理操作。它可以呈现下面几种特殊效果。              BevelBitmapEffect        凹凸效果             BlurBitmapEffect...
1706 0
|
C# 小程序
WPF 3D变换应用
原文:WPF 3D变换应用  WPF可以提供的3D模型使我们可以轻松地创建3D实体,虽然目前来看还很有一些性能上的问题,不过对于一些简单的3D应用应该是可取的,毕竟其开发效率高,而且也容易上手。         下面给大家演示的是使用在WPF 3D上实现视角变换,通过鼠标拖动来变换观察视角,通过滚轮来放缩视距。
703 0
|
C# 前端开发
WPF中获取形状范围
原文:WPF中获取形状范围 在没加入到Canvas时,也能获取形状的方法:   var polygon = new Polygon(); polygon.Points.
764 0
|
C#
WPF 2D 碰撞检测
原文:WPF 2D 碰撞检测     var intersectionDetail = path1.Data.FillContainsWithDetail(path2.Data); if (intersectionDetail != IntersectionDetail.
883 0