C# wpf 嵌入hwnd窗口

WPF Hwnd窗口互操作系列

第一章 嵌入Hwnd窗口(本章)
第二章 嵌入WinForm控件
第三章 嵌入WPF控件


文章目录

  • WPF Hwnd窗口互操作系列
  • 前言
  • 一、如何实现
    • 1、继承HwndHost
    • 2、实现抽象方法
    • 3、xaml中使用HwndHost控件
  • 二、具体实现
    • 1、Win32窗口
    • 2、HwndSource窗口
    • 3、Wpf窗口
  • 三、使用示例
  • 总结


前言

wpf是Direct UI,窗口中只有一个hwnd句柄,大部分控件都是直接在上面绘制的。当我们需要使用不同的渲染方式进行绘制时,就会和控件绘制产生冲突。比如使用opengl渲染3d图形或者视频时,直接在窗口绘制就会出现闪烁,与控件相互覆盖。要解决这个问题就需要,添加一个新的hwnd窗口或控件嵌入wpf窗口中,我们可以通过HwndHost就可以实现这样的功能。


一、如何实现

1、继承HwndHost

public class MyWindowHost : HwndHost

2、实现抽象方法

只需实现下列2个方法

protected override HandleRef BuildWindowCore(HandleRef hwndParent)
{Handle =创建的窗口句柄return new HandleRef(this, Handle);
}
protected override void DestroyWindowCore(HandleRef hwnd)
{hwnd.Handle;根据句柄销毁窗口
}

3、xaml中使用HwndHost控件

<local:MyWindowHost Width="100" Height="100" >
</local:MyWindowHost >

二、具体实现

1、Win32窗口

我们可以通过win32 api创建一个窗口,封装成HwndHost对象,提供给xaml使用。
Win32WindowHost.cs

using System.Runtime.InteropServices;
using System.Windows;
using System.Windows.Interop;
namespace WpfHwndElement
{/// <summary>/// 直接通过win32 api创建窗口/// </summary>public class Win32WindowHost : HwndHost{//重新定义Handle为依赖属性,可以用于绑定new public IntPtr Handle{get { return (IntPtr)GetValue(HandleProperty); }private set { SetValue(HandleProperty, value); }}// Using a DependencyProperty as the backing store for Hwnd.  This enables animation, styling, binding, etc...public static readonly DependencyProperty HandleProperty =DependencyProperty.Register("Handle", typeof(IntPtr), typeof(Win32WindowHost), new PropertyMetadata(IntPtr.Zero));protected override HandleRef BuildWindowCore(HandleRef hwndParent){Handle = CreateWindowEx(0, "static", "", WS_CHILD | WS_VISIBLE | LBS_NOTIFY | WS_CLIPSIBLINGS, 0, 0, (int)Width, (int)Height, hwndParent.Handle, IntPtr.Zero, IntPtr.Zero, 0);return new HandleRef(this, Handle);}[DllImport("user32.dll", SetLastError = true)]static extern System.IntPtr DefWindowProcW(IntPtr hWnd, uint msg, IntPtr wParam, IntPtr lParam);protected override void DestroyWindowCore(HandleRef hwnd){DestroyWindow(hwnd.Handle);}const int WS_CHILD = 0x40000000;const int WS_VISIBLE = 0x10000000;const int LBS_NOTIFY = 0x001;const int WS_CLIPSIBLINGS = 0x04000000;[DllImport("user32.dll")]internal static extern IntPtr CreateWindowEx(int exStyle, string className, string windowName, int style, int x, int y, int width, int height, IntPtr hwndParent, IntPtr hMenu, IntPtr hInstance, [MarshalAs(UnmanagedType.AsAny)] object pvParam);[DllImport("user32.dll")]static extern bool DestroyWindow(IntPtr hwnd);}
}

2、HwndSource窗口

如果不想导入win32 api,则可以使用HwndSource对象创建句柄窗口。

using System.Runtime.InteropServices;
using System.Windows;
using System.Windows.Interop;namespace WpfHwndElement
{class HwndSourceHost : HwndHost{//重新定义Handle为依赖属性,可以用于绑定new public IntPtr Handle{get { return (IntPtr)GetValue(HandleProperty); }private set { SetValue(HandleProperty, value); }}// Using a DependencyProperty as the backing store for Hwnd.  This enables animation, styling, binding, etc...public static readonly DependencyProperty HandleProperty =DependencyProperty.Register("Handle", typeof(IntPtr), typeof(HwndSourceHost), new PropertyMetadata(IntPtr.Zero));HwndSource _source;protected override HandleRef BuildWindowCore(HandleRef hwndParent){_source = new HwndSource(0, WS_CHILD | WS_VISIBLE | LBS_NOTIFY| WS_CLIPSIBLINGS, 0, 0, 0, (int)Width, (int)Height, "nativeHost", hwndParent.Handle);Handle = _source.Handle;return new HandleRef(this, Handle);}protected override void DestroyWindowCore(HandleRef hwnd){_source.Dispose();}const int WS_CHILD = 0x40000000;const int WS_VISIBLE = 0x10000000;const int LBS_NOTIFY = 0x001;const int WS_CLIPSIBLINGS = 0x04000000;}
}

3、Wpf窗口

wpf窗口也可以进行嵌入,但需要导入win32对窗口属性进行设置,要设置WS_CHILD 以及父窗口。

using System.Runtime.InteropServices;
using System.Windows;
using System.Windows.Interop;namespace WpfHwndElement
{   //重新定义Handle为依赖属性,可以用于绑定public class WpfWindowHost : HwndHost{new public IntPtr Handle{get { return (IntPtr)GetValue(HandleProperty); }private set { SetValue(HandleProperty, value); }}// Using a DependencyProperty as the backing store for Hwnd.  This enables animation, styling, binding, etc...public static readonly DependencyProperty HandleProperty =DependencyProperty.Register("Handle", typeof(IntPtr), typeof(WpfWindowHost), new PropertyMetadata(IntPtr.Zero));const int WS_CHILD = 0x40000000;const int GWL_STYLE = (-16);[DllImport("user32.dll", EntryPoint = "GetWindowLongW")]static extern int GetWindowLong(IntPtr hwnd, int nIndex);[DllImport("user32.dll", EntryPoint = "SetWindowLongW")]static extern int SetWindowLong(IntPtr hwnd, int nIndex, int dwNewLong);[DllImport("user32.dll")]public static extern IntPtr SetParent(IntPtr hWndChild, IntPtr hWndNewParent);protected override HandleRef BuildWindowCore(HandleRef hwndParent){var window = new Window();   var hwnd = new WindowInteropHelper(window).EnsureHandle();window.Show();SetWindowLong(hwnd, GWL_STYLE, GetWindowLong(hwnd, GWL_STYLE) | WS_CHILD);SetParent(hwnd, hwndParent.Handle);return new HandleRef(this, hwnd);}protected override void DestroyWindowCore(HandleRef hwnd){var window = HwndSource.FromHwnd(hwnd.Handle)?.RootVisual as Window;window?.Close();}}
}

三、使用示例

MainWindow.xaml

<Window x:Class="WpfHwndElement.MainWindow"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"xmlns:d="http://schemas.microsoft.com/expression/blend/2008"xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"xmlns:local="clr-namespace:WpfHwndElement"mc:Ignorable="d"Title="MainWindow" Height="360" Width="640"   ><StackPanel><local:Win32WindowHost Width="100" Height="100"/><local:HwndSourceHost Margin="0,10,0,0" Width="100" Height="100"/><local:WpfWindowHost Margin="0,10,0,0" Width="100" Height="100"/></StackPanel>
</Window>

效果预览
在这里插入图片描述


总结

以上就是今天要讲的内容,通过HwndHost的方式嵌入hwnd窗口是比较简单易用的,而且也为wpf实现的界面效果提供的更多的可能性,当然嵌入的窗口会覆盖wpf控件,虽然有解决的方法,本文主要还是提供基础的HwndHost用法。

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

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

相关文章

思腾合力出席文化和旅游虚拟现实应用推广交流活动并作主题演讲

3月21日&#xff0c;由文化和旅游部产业发展司主办&#xff0c;中国信息通信研究院、北京市石景山区文化和旅游局、中国动漫集团有限公司承办的“数字赋能文旅场景建设行动——文化和旅游虚拟现实应用推广交流活动”在北京首钢一高炉SoReal科幻乐园成功举办。 思腾合力CMO徐莉受…

【第028篇】用IDEA打开并运行Eclipse创建的项目

下图我使用的是2021版本的idea 一、 导入 首先&#xff0c;点击左上方【File】-【New】-【Project from Existing Sources】 在目录中选择自己要导入的eclipse动态项目&#xff1b; 3、这里选择【import project from external model】&#xff0c;再选择【eclipse】&#…

【jenkins+cmake+svn管理c++项目】Windows环境安装以及工具配置

一、目标和环境 目标&#xff1a;搭建一个jenkins环境&#xff0c;实现jenkins调用cmake和svn和VS编译c项目&#xff0c;并将生成的库上传svn。 环境&#xff1a;win10虚拟机&#xff08;练习流程用&#xff0c;正式用的话还是放到服务器&#xff09;&#xff0c;VS2017. 二、…

Flask python :logging日志功能使用

logging日志的使用 一、了解flask日志1.1、Loggers记录器1.2、Handlers 处理器1.3、Formatters 格式化器 二、使用日志2.1、官网上的一个简单的示例2.2、基本配置2.3、具体使用示例2.4、运行 三、写在最后 一、了解flask日志 日志是一种非常重要的工具&#xff0c;可以帮助开发…

pandas 函数

pandas是基于numpy数组构建的&#xff0c;但二者最大的不同是pandas是专门为处理表格和混杂数据设计的&#xff0c;比较契合统计分析中的表结构&#xff0c;而numpy更适合处理统一的数值数组数据。pandas数组结构有一维Series和二维DataFrame。 Series的字符串表现形式为&#…

java Web线上网游商品交易平台用eclipse定制开发mysql数据库BS模式java编程jdbc

一、源码特点 jsp线上网游商品交易平台是一套完善的web设计系统&#xff0c;对理解JSP java SERLVET mvc编程开发语言有帮助&#xff0c;系统具有完整的源代码和数据库&#xff0c;系统主要采用B/S模式开发。开发环境为TOMCAT7.0,eclipse开发&#xff0c;数据库为Mysql5.0…

Spark SizeTrackingAppendOnlyMap 相关源代码分析

SizeTrackingAppendOnlyMap 在 ExternalAppendOnlyMap 中使用&#xff0c;当 map 中对象占用的内存大小超过一定阈值时&#xff0c;把 数据 spill 到磁盘。所以 SizeTrackingAppendOnlyMap extends AppendOnlyMap[K, V] with SizeTracker。 AppendOnlyMap AppendOnlyMap 是只…

ssh免密登陆实现

1. 本地客户端生成公钥和私钥 使用以下命令&#xff0c;然后一路按回车键使用默认值即可。 ssh-keygen -t rsa -C "My-SSH"// -t 表示ssh的密钥类型&#xff0c;常用的有&#xff1a;rsa、ed25519、dss。 // -C 名称标识&#xff0c;此值随意。 会在用户根目录下的…

基于springboot的交通管理在线服务系统的开发

传统办法管理信息首先需要花费的时间比较多&#xff0c;其次数据出错率比较高&#xff0c;而且对错误的数据进行更改也比较困难&#xff0c;最后&#xff0c;检索数据费事费力。因此&#xff0c;在计算机上安装交通管理在线服务系统软件来发挥其高效地信息处理的作用&#xff0…

【LAMMPS学习】四、运行 LAMMPS(4) Windows 运行 LAMMPS

4. 运行 LAMMPS 本部分解释了在安装可执行文件或下载源代码并构建可执行文件后如何运行 LAMMPS。命令文档页面描述了输入脚本的结构以及它们可以包含的命令。 4.1.运行 LAMMPS 的基础知识 4.2.命令行选项 4.3.屏幕和日志文件输出 4.4.在 Windows 上运行 LAMMPS 串行&am…

【数据结构】常见线性结构

1.线性表 线性表 &#xff08; linear list &#xff09; 是n个具有相同特性的数据元素的有限序列。 线性表是一种在实际中广泛使 用的数据结构&#xff0c;常见的线性表&#xff1a;顺序表、链表、栈、队列、字符串... 线性表在逻辑上是线性结构&#xff0c;也就说是连续的一…

结构体-C语言

目录 前言 一、定义结构 结构体变量的创建和初始化 二、结构的特殊声明 特别注意&#xff1a; 结构的⾃引⽤ 三、结构体内存对⻬ 对⻬规则 优化结构体 #pragma 结构体传参 四、结构体实现位段 位段的内存分配 位段的跨平台问题 前言 C 数组允许定义可存储相同类…

Fiddler抓包工具之fiddler的常用快捷键

一、常用三个快捷键 ctrlX :清空所有记录 CtrlF&#xff1a;查找 F12&#xff1a;启动或者停止抓包 使用 QuickExec Fiddler2 成了网页调试必备的工具&#xff0c;抓包看数据。Fiddler2自带命令行控制。 fiddler 命令行快捷键&#xff1a;ctrl q &#xff0c;然后 输入 help…

题目:有1、2、3、4个数字,能组成多少个互不相同且无重复数字的三位数?都是多少?

题目&#xff1a;有1、2、3、4个数字&#xff0c;能组成多少个互不相同且无重复数字的三位数&#xff1f;都是多少&#xff1f; There is no nutrition in the blog content. After reading it, you will not only suffer from malnutrition, but also impotence. The blog con…

约瑟夫环问题(队列,链表实现)- c++

1.关于约瑟夫问题 约瑟夫斯领导犹太人反抗罗马帝国的统治&#xff0c;在与罗马军队的激烈战斗中&#xff0c;与士兵们一同被困在一个山洞里。总共有41人&#xff0c;约瑟夫斯希望向罗马军队投降&#xff0c;但他的士兵们却坚决拒绝&#xff0c;宁愿死也不愿被敌人俘虏。面对这…

如何理解React的state、props、super()和super(props)

state 一个组件需要显示什么&#xff0c;怎么显示内容&#xff0c;都是由数据状态和外部参数决定的。 state就是这个数据状态。 当需要修改状态值的时候&#xff0c;通过调用setState&#xff0c;实现更新组件内部数据的问题。 setState的第一个参数有两种形式&#xff1a;…

电路常识:干接点、湿接点

1、干接点、湿接点的区别&#xff1a; 干接点和湿接点&#xff1a;是对开关量说的&#xff0c;即&#xff1a;通断。 干接点是一种无源开关&#xff0c;具有闭、合&#xff08;导通、断开&#xff09;两种状态&#xff0c;两个接触点之间没有极性可以互换。 常见的干接点&am…

数据分析---SQL基础

目录 什么是关系型数据库其他种类的数据库关系型数据库的基本操作数据库设计ER模型什么是关系型数据库 SQL(Structured Query Language)是用于管理关系型数据库的标准化查询语言。关系型数据库是一种基于关系模型(即表格)的数据库,它使用结构化查询语言(SQL)来管理和操作…

国家中英文名称、国家代码(地区代码)、国家域名、经纬度

因为要做世界地图对世界国家的标点&#xff0c;搜索使用到了世界各个国家的地理位置信息&#xff0c;此处做备份与学习。资源地址&#xff08;免费&#xff09; export default {"阿尔巴尼亚": {"m_longitude": "19.809","m_latitude&quo…

React项目打包优化-包体积分析

1、什么是包体积分析&#xff1f; 通过可视化的方式&#xff0c;直观的看到各种包打包之后的体积大小&#xff0c;方便后续针对体积情况做优化 2、怎么分析包&#xff1f; 借助插件 source-map-explorer&#xff0c; 1、先安装插件 npm install source-map-explorer 2、在p…