ActiViz集成到WPF中的空域问题

文章目录

  • 一、场景
    • 1、WPF控件
    • 2、集成ActiViz或者VTK
  • 二、问题
    • 1、需求
    • 2、空域问题
  • 三、解决方案
    • 1、用WindowsFormsHost包裹住ElementHost,然后将WPF的控件放在ElementHost职中:
    • 2、用Window或者Popup去悬浮
    • 3、使用第三方库Microsoft.DwayneNeed(这也是网上出现较多的答案)
  • 四、最新解决方案
    • 1、步骤
    • 2、需要用到的库
    • 3、关键代码如下:
    • 4、运行结果预览:
    • 5、源码链接
  • 五、总结


一、场景

1、WPF控件

众所周知,由于WPF的底层绘制原理不同,WPF的大多数控件都不具备句柄,具备句柄的也就只有那么几种:Window、Popup、ContextMenu等。

2、集成ActiViz或者VTK

在集成VTK时: 一般选择WindowsFormsHost作为载体,将WinForm具备句柄的控件:如Panel,嵌入WPF布局中。然后将Panel的句柄传给C++。

在集成ActiViz时: 需要以RenderWindowControl来承接三维渲染内容,同样一般选择WindowsFormsHost作为载体,将RenderWindowControl放入其中,然后渲染三维内容。

二、问题

1、需求

如果需求是在三维布局界面,悬浮一些控件,且控件的背景色可以设置成透明。

2、空域问题

你会发现悬浮的WPF控件,始终在WindowsFormsHost之下,也就是说WindowsFormsHost所承载的内容始终置顶。这就是WPF由来已久的空域问题。

三、解决方案

1、用WindowsFormsHost包裹住ElementHost,然后将WPF的控件放在ElementHost职中:

<wf:WindowsFormsHost>
<wf:ElementHost>
<Grid>
</Grid>
</wf:ElementHost>
</wf:WindowsFormsHost>

如此,WPF的控件可置顶。但是会产生一下问题:
①WPF的控件绑定需要重新指定数据源
②较多的WindowsFormsHost会增加界面刷新的负担
③较多的WindowsFormsHost处理不慎的话,会出现严重的内存泄漏问题
④WindowsFormsHost所包裹的WPF控件无法透明背景,影响界面美观

2、用Window或者Popup去悬浮

优点:可悬浮于WindowsFormsHost之上、可透明背景
缺点:
①会产生其他显示问题,处理复杂:Popup永远置顶,在锁屏或者弹窗时,Popup始终在最上方。当然用Windows的API重写Popup,可取消置顶,但任然在不同环境可能有取消置顶失败的情况出现。
②Popup和Window作为单独的窗口,已经不再和主页面为一个整体,在页面切换和页面移动时,需要手动更新Popup,Window的显隐和位置,处理较为麻烦。
③Popup的使用在窗口关闭时,存在内存泄漏问题。

3、使用第三方库Microsoft.DwayneNeed(这也是网上出现较多的答案)

<xmlns:interop=clr-namespace:Microsoft.DwayneNeed.Interop;assembly=Microsoft.DwayneNeed></xmlns><airspace:AirspaceDecorator AirspaceMode="Redirect" IsInputRedirectionEnabled="True" IsOutputRedirectionEnabled="True">    
<WindowsFormsHost Name="FormsHost">        
<winform:WebBrowser>    
</WindowsFormsHost></airspace:AirspaceDecorator>

以上方式,的确可以实现控件悬浮置顶,且控件背景透明。但经过本人实测,会出现以下不可控问题:
①在切换界面布局,或者刷新界面时会产生不可控的BUG,难以解决
②刷新界面时,存在严重的性能问题
③占用资源过多,三维界面的鼠标交互异常卡顿

四、最新解决方案

基于最新的ActiViz 9.3的版本,可以自己实现一个RenderWindowControl来解决空域问题。

1、步骤

①将D3D11Image控件封装到控件,通过DirectX 纹理映射来绘制图像
②将D3D11Image控件DirectN获取到系统能支持的控件句柄
③将该句柄设置上下文方式,设置到vtkWin32OpenGLDXRenderWindow中:
RenderWindow.SetD3DDeviceContext§;
④重写鼠标交互

2、需要用到的库

DirectNCore
Kitware.mummy.Runtime
Kitware.VTK
Microsoft.Wpf.Interop.DirectX

3、关键代码如下:

using System;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Interop;
using System.Windows.Media;
using DirectN;
using Kitware.VTK;
using Microsoft.Wpf.Interop.DirectX;namespace WpfD3D11Interop_Net6._0
{internal class MyRenderWindowControl : Image{public vtkWin32OpenGLDXRenderWindow RenderWindow;public vtkRenderWindowInteractor Interactor;private bool _readyForRendering;private IComObject<ID3D11Device> _device;private IComObject<ID3D11Texture2D>? _d3d11Texture;private D3D11Image _d3d11ImageSource;public MyRenderWindowControl(){_d3d11ImageSource = new D3D11Image();base.Source = (ImageSource)(object)_d3d11ImageSource;_d3d11ImageSource.OnRender = new Action<nint, bool>(Render);D3D11_CREATE_DEVICE_FLAG val = (D3D11_CREATE_DEVICE_FLAG)32;          RenderWindow = vtkWin32OpenGLDXRenderWindow.New();RenderWindow.ShowWindowOff();RenderWindow.SetColorTextureFormat(87u);Extensions.WithComPointer<ID3D11DeviceContext>(ID3D11DeviceExtensions.GetImmediateContext(_device), (Action<IntPtr>)delegate (nint p){RenderWindow.SetD3DDeviceContext(p);});RenderWindow.Initialize();RenderWindow.Render();RenderWindow.RegisterSharedTexture();Interactor = vtkRenderWindowInteractor.New();Interactor.EnableRenderOff();RenderWindow.SetInteractor(Interactor);Interactor.RenderEvt += Interactor_RenderEvt;vtkInteractorStyleTrackballCamera interactorStyle = vtkInteractorStyleTrackballCamera.New();Interactor.SetInteractorStyle(interactorStyle);base.MouseMove += RenderWindowControl_MouseMove;base.MouseDown += RenderWindowControl_MouseDown;base.MouseUp += RenderWindowControl_MouseUp;base.MouseWheel += RenderWindowControl_MouseWheel;base.KeyDown += RenderWindowControl_KeyDown;base.KeyUp += RenderWindowControl_KeyUp;base.Focusable = true;base.IsHitTestVisible = true;base.Loaded += RenderWindowControl_Loaded;base.SizeChanged += RenderWindowControl_SizeChanged;CompositionTarget.Rendering += CompositionTarget_Rendering;}private void RenderWindowControl_MouseWheel(object sender, MouseWheelEventArgs e){if (!base.IsFocused){Focus();}if (e.Delta < 0){Interactor.MouseWheelBackwardEvent();}else if (e.Delta > 0){Interactor.MouseWheelForwardEvent();}}private void RenderWindowControl_MouseDown(object sender, MouseButtonEventArgs e){Point position = e.GetPosition(this);Interactor.SetEventPosition((int)position.X, (int)position.Y);CaptureMouse();if (!base.IsFocused){Focus();}if (e.ChangedButton == MouseButton.Left){Interactor.LeftButtonPressEvent();}if (e.ChangedButton == MouseButton.Right){Interactor.RightButtonPressEvent();}if (e.ChangedButton == MouseButton.Middle){Interactor.MiddleButtonPressEvent();}}private void RenderWindowControl_MouseUp(object sender, MouseButtonEventArgs e){Point position = e.GetPosition(this);Interactor.SetEventPosition((int)position.X, (int)position.Y);ReleaseMouseCapture();if (e.ChangedButton == MouseButton.Left){Interactor.LeftButtonReleaseEvent();}if (e.ChangedButton == MouseButton.Right){Interactor.RightButtonReleaseEvent();}if (e.ChangedButton == MouseButton.Middle){Interactor.MiddleButtonReleaseEvent();}}private void RenderWindowControl_MouseMove(object sender, MouseEventArgs e){Point position = e.GetPosition(this);Interactor.SetEventPosition((int)position.X, (int)position.Y);Interactor.MouseMoveEvent();}private void RenderWindowControl_KeyUp(object sender, KeyEventArgs e){SetInteractorKeyEventInformation(e);Interactor.KeyReleaseEvent();e.Handled = true;}private void RenderWindowControl_KeyDown(object sender, KeyEventArgs e){SetInteractorKeyEventInformation(e);Interactor.KeyPressEvent();string text = e.Key.ToString();if (text.Length == 1 && text.All(char.IsLetter)){Interactor.CharEvent();}e.Handled = true;}protected void SetInteractorKeyEventInformation(KeyEventArgs e){bool flag = (Keyboard.GetKeyStates(Key.Capital) & KeyStates.Toggled) == KeyStates.Toggled;int ctrl = (((Keyboard.Modifiers & ModifierKeys.Control) == ModifierKeys.Control) ? 1 : 0);int num = (((Keyboard.Modifiers & ModifierKeys.Shift) == ModifierKeys.Shift) ? 1 : 0);int altKey = (((Keyboard.Modifiers & ModifierKeys.Alt) == ModifierKeys.Alt) ? 1 : 0);int repeatcount = (e.IsRepeat ? 1 : 0);string text = e.Key.ToString();sbyte keycode = 0;if (text.Length == 1){if (text.All(char.IsLetter) && num == 0 && !flag){text = text.ToLower();}keycode = (sbyte)text[0];}Interactor.SetKeyEventInformation(ctrl, num, keycode, repeatcount, text);Interactor.SetAltKey(altKey);}private void Interactor_RenderEvt(vtkObject sender, vtkObjectEventArgs e){_readyForRendering = true;}private void Render(nint surface, bool isNewSurface){//IL_001d: Unknown result type (might be due to invalid IL or missing references)//IL_0040: Unknown result type (might be due to invalid IL or missing references)if (isNewSurface){nint num = default(nint);ComObject.From<IDXGIResource>(ComObject.QueryObjectInterface<ID3D11Texture2D>((object)ComObject.From<ID3D11Texture2D>((IntPtr)surface, true), true), true).Object.GetSharedHandle(out num);object obj = default(object);_device.Object.OpenSharedResource((IntPtr)num, typeof(ID3D11Resource).GUID, out obj);nint num2 = ComObject.QueryObjectInterface(obj, typeof(ID3D11Texture2D).GUID, true);_d3d11Texture = (IComObject<ID3D11Texture2D>?)(object)ComObject.From<ID3D11Texture2D>((IntPtr)num2, true);_readyForRendering = true;}if (_readyForRendering){RenderWindow.Lock();RenderWindow.Render();RenderWindow.Unlock();Extensions.WithComPointer<ID3D11Texture2D>(_d3d11Texture, (Action<IntPtr>)delegate (nint p){RenderWindow.BlitToTexture(p, IntPtr.Zero);});}}private void CompositionTarget_Rendering(object? sender, EventArgs e){_d3d11ImageSource.RequestRender();_readyForRendering = false;}private void RenderWindowControl_SizeChanged(object sender, SizeChangedEventArgs e){_readyForRendering = true;RenderWindow.SetSize((int)base.ActualWidth, (int)base.ActualHeight);_d3d11ImageSource.SetPixelSize((int)base.ActualWidth, (int)base.ActualHeight);}private void RenderWindowControl_Loaded(object sender, RoutedEventArgs e){if (PresentationSource.FromVisual(this) is HwndSource hwndSource){_d3d11ImageSource.WindowOwner = hwndSource.Handle;}RenderWindow.SetSize((int)base.DesiredSize.Width, (int)base.DesiredSize.Height);_d3d11ImageSource.SetPixelSize((int)base.DesiredSize.Width, (int)base.DesiredSize.Height);}}
}

4、运行结果预览:

在这里插入图片描述

5、源码链接

踩坑创作不易,白嫖党勿扰:
https://download.csdn.net/download/weixin_48083386/89480594

五、总结

困扰了C#集成VTK很久的空域问题,终于在ActiViz9.3推出了vtkWin32OpenGLDXRenderWindow类之后,得到解决。其解决原理与QT集成VTK的原理一致,都用到了DirectX绘制,并重写交互。本人亲测,目前无任何负面影响。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/360394.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

光泽正在褪去,所以我们又回到了人工智能领域。

光泽正在褪去&#xff0c;所以我们又回到了人工智能领域。 人工智能冬天将被私有化 自从“人工智能”这个流行词在20世纪50年代被创造出来以来&#xff0c;人工智能经历了几次繁荣和萧条周期。 一种新的技术方法看起来很有趣&#xff0c;并取得了一些成果。它被荒谬地炒作并获…

解锁小红书新玩法:中小企业出海营销的集成策略

随着全球数字化浪潮的推进&#xff0c;小红书作为生活方式分享平台的崛起&#xff0c;为中小企业提供了一个全新的营销舞台。NetFarmer&#xff0c;作为专注于企业数字化出海的服务商&#xff0c;深谙小红书的营销策略&#xff0c;并致力于通过HubSpot产品销售与实施&#xff0…

表单(forms)

自学python如何成为大佬(目录):https://blog.csdn.net/weixin_67859959/article/details/139049996?spm1001.2014.3001.5501 在app1文件夹下创建一个forms.py文件&#xff0c;添加如下类代码&#xff1a; from django import forms class PersonForm(forms.Form): first_na…

uniapp运行到模拟器(联想模拟器)

记录一下uniapp项目运行到联想模拟器的流程 先配置一下模拟器端口 填写对应的adb路径&#xff0c;也就是模拟器安装路径下的adb.exe的路径 然后打开模拟器的设置&#xff0c;搜索版本找到版本号&#xff0c;多次点击打开开发者模式 进入开发者选项&#xff0c;打开USB调试 …

智能合约开发的过程

智能合约是一种运行在区块链上的程序&#xff0c;可以自动执行预先设定的条款和条件。智能合约具有去中心化、透明、不可篡改等特点&#xff0c;因此被广泛应用于金融、供应链、物联网等领域。北京木奇移动技术有限公司&#xff0c;专业的软件外包开发公司&#xff0c;欢迎交流…

如何与ISSI建立EDI连接?

ISSI是一家总部位于美国的半导体公司&#xff0c;主要设计和销售高性能集成电路 (IC)&#xff0c;其产品包括DRAM、SRAM、闪存和模拟电路&#xff0c;广泛应用于汽车、通信、工业和医疗等领域。 和其他半导体行业的企业一样&#xff0c;ISSI通过EDI与其全球合作伙伴传输业务单据…

《C语言》编译和链接

文章目录 一、翻译环境1、预处理2、编译3、汇编4、链接 二、运行环境 一、翻译环境 在使用编译器编写代码时&#xff0c;编写的代码是高级语言&#xff0c;机器无法直接识别和运行&#xff0c;在编译器内部会翻译成机器可执行的机器语言。 编译环境由编译和链接两大过程组成。 …

【CT】LeetCode手撕—23. 合并 K 个升序链表

目录 题目1- 思路2- 实现⭐23. 合并 K 个升序链表——题解思路 3- ACM 实现 题目 原题连接&#xff1a;23. 合并 K 个升序链表 1- 思路 模式识别&#xff1a;合并 K 个链表 ——> 优先队列 思路 借助优先队列&#xff0c;每次从 k 个链表中&#xff0c;各取一个元素&…

【Docker】存储数据卷

目录 1、挂载数据卷到容器里 2、查询挂载文件 3、容器与主机之间映射共享卷 4、三个容器之间使用共享卷 5、卷数据的备份与恢复 5.1 备份 5.2 恢复 1、挂载数据卷到容器里 docker run -itd --name test02 -v /data nginx docker exec -it test02 bashls / docker inspe…

MySQL MVCC详解

目录 前言 MVCC实现原理 UndoLog版本链 ReadView MVCC是否可以解决不可重复读与幻读 隔离级别 READ UNCOMMITTED - 读未提交与脏读 READ COMMITTED - 读已提交与不可重复读 REPEATABLE READ - 可重复读与幻读 SERIALIZABLE - 串行化 小结 前言 为了提高数据库并发能力…

JVM虚拟机的组成

一、为什么要学习 JVM &#xff1f; 1. “ ⾯试造⽕箭&#xff0c;⼯作拧螺丝” &#xff0c; JVM 属于⾯试官特别喜欢提问的知识点&#xff1b; 2. 未来在⼯作场景中&#xff0c;也许你会遇到以下场景&#xff1a; 线上系统突然宕机&#xff0c;系统⽆法访问&#xff0c;甚⾄直…

前后端交互的弯弯绕绕

前后端交互&#xff1a; &#x1f197;&#xff0c;收拾一下心情让我们来聊一聊AJax吧&#xff0c;随着前端的飞速发展&#xff0c;前后的交互也发生了天翻地覆的变化&#xff1a; 前后端交互的方式有很多&#xff1a; AJAX、表单提交、WebSocket、RESTful API、... 这对新入…

查看es p12证书文件过期方法

查看证书过期时间: openssl pkcs12 -in elastic-certificates.p12 -nokeys -out elastic-certificates.crt (需要输入证书生成时配置密码) openssl x509 -enddate -noout -in elastic-certificates.crt

使用 GitOps 进行防灾 MinIO

想象一下&#xff0c;您已经花费了无数小时来完善 Docker Swarm 设置&#xff0c;精心设计每项服务&#xff0c;并调整 CI/CD 管道以实现无缝自动化。现在&#xff0c;想象一下这个经过微调的系统被重置为原点&#xff0c;不是因为严重的故障或安全漏洞&#xff0c;而是因为数据…

了解SD-WAN与传统WAN的区别

近年来&#xff0c;许多企业选择了SD-WAN作为他们的网络解决方案。云基础架构的SD-WAN不仅具备成本效益&#xff0c;而且提供更安全、更可靠的WAN连接&#xff0c;有助于实现持续盈利。客户能够更好地控制他们的网络&#xff0c;个性化定制且无需额外成本。 那么&#xff0c;为…

基于JSP的列车票务信息管理系统

开头语&#xff1a; 你好&#xff0c;我是专注于计算机科学与技术研究的学长。如果你对列车票务信息管理系统感兴趣或有相关需求&#xff0c;欢迎联系我。 开发语言&#xff1a;Java 数据库&#xff1a;MySQL 技术&#xff1a;JSP技术 工具&#xff1a;IDE、数据库管理工具…

基于SpringBoot小区物业智能卡管理设计和实现(源码+LW+调试文档+讲解等)

&#x1f497;博主介绍&#xff1a;✌全网粉丝10W,CSDN作者、博客专家、全栈领域优质创作者&#xff0c;博客之星、平台优质作者、专注于Java、小程序技术领域和毕业项目实战✌&#x1f497; &#x1f31f;文末获取源码数据库&#x1f31f;感兴趣的可以先收藏起来&#xff0c;还…

【SQL Server数据库】带函数查询和综合查询(1)

目录 1&#xff0e;统计年龄大于30岁的学生的人数。 2&#xff0e;统计数据结构有多少人80分或以上。 3.查询“0203”课程的最高分的学生的学号。 4&#xff0e;统计各系开设班级的数目(系名称、班级数目)&#xff0c;并创建结果表。 5&#xff0e;选修了以“01”开头的课…

Spark SQL 血缘解析方案

背景 项目背景建设数据中台,往往数据开发人员首先需要能够通过有效的途径检索到所需要的数据,然后根据检索的数据模型进行业务加工然后得到一些中间模型,最后再通过数据抽取工具或者OLAP分析工具直接将数据仓库中加工好的公共模型输出到应用层。这里我不在去介绍数据仓库为…

Python 围棋

效果图 完整代码 源码地址&#xff1a;Python 围棋 # 使用Python内置GUI模块tkinter from tkinter import * # ttk覆盖tkinter部分对象&#xff0c;ttk对tkinter进行了优化 from tkinter.ttk import * # 深拷贝时需要用到copy模块 import copy import tkinter.me…