C# wpf 嵌入wpf控件
WPF Hwnd窗口互操作系列
第一章 嵌入Hwnd窗口
第二章 嵌入WinForm控件
第三章 嵌入WPF控件(本章)
第四章 底部嵌入HwndHost
文章目录
- WPF Hwnd窗口互操作系列
- 前言
- 一、如何实现?
- 1、继承HwndHost
- 2、添加Content属性
- 3、创建wpf窗口并设置Content
- 4、关闭wpf窗口
- 二、完整代码
- 三、使用示例
- 1、嵌入控件
- 2、嵌入Window
- (1)xaml中定义Window
- (2)嵌入已有的Window
- 3、显示在WinForm控件上面
- 总结
前言
通过前面的章节我们了解到了如何嵌入Hwnd窗口以及WinForm控件,但是嵌入的控件存在覆盖wpf控件的情况,嵌入控件上面无法显示王鹏飞控件,对UI的布局有一定的影响。本文提供一种解决方法,
将wpf控件通过HwndHost的方式嵌入到wpf界面中,以实现HwndHost控件上显示wpf控件的功能。
一、如何实现?
1、继承HwndHost
和其他嵌入方式一样,需要先继承HwndHost。
public class WpfElementHost : HwndHost
2、添加Content属性
添加一个Content属性,提供给xaml使用。这个Content属性就是需要嵌入的wpf控件。
[ContentProperty("Content")]
public class WpfElementHost : HwndHost
{public UIElement Content{get { return (UIElement)GetValue(ContentProperty); }set { SetValue(ContentProperty, value); }}public static readonly DependencyProperty ContentProperty =DependencyProperty.RegisterAttached("Content", typeof(UIElement), typeof(WpfElementHost), new PropertyMetadata(null));
}
3、创建wpf窗口并设置Content
实现抽象方法窗口wpf窗口,这里参考第一章的嵌入wpf窗口,以及给窗口设置Content属性。
protected override HandleRef BuildWindowCore(HandleRef hwndParent)
{var window = Content is Window ? Content as Window : new Window { WindowStyle = WindowStyle.None, ResizeMode = ResizeMode.NoResize, Focusable = false, Width = 0, Height = 0, ShowInTaskbar = false, ShowActivated = false, Background = Brushes.Transparent, Content = Content, AllowsTransparency = true };var hwnd = new WindowInteropHelper(window).EnsureHandle();SetWindowLong(hwnd, GWL_STYLE, GetWindowLong(hwnd, GWL_STYLE) | WS_CHILD);User32.SetParent(hwnd, hwndParent.Handle);window!.Show();return new HandleRef(this, hwnd);
}
4、关闭wpf窗口
实现抽象方法,关闭窗口
protected override void DestroyWindowCore(HandleRef hwnd)
{var window = HwndSource.FromHwnd(hwnd.Handle)?.RootVisual as Window;window?.Close();
}
二、完整代码
WpfElementHost.cs
using System.Runtime.InteropServices;
using System.Windows;
using System.Windows.Interop;
using System.Windows.Markup;
using Brushes = System.Windows.Media.Brushes;
namespace WpfHwndElement
{[ContentProperty("Content")]public class WpfElementHost : HwndHost{public UIElement Content{get { return (UIElement)GetValue(ContentProperty); }set { SetValue(ContentProperty, value); }}public static readonly DependencyProperty ContentProperty =DependencyProperty.RegisterAttached("Content", typeof(UIElement), typeof(WpfElementHost), new PropertyMetadata(null));const int GWL_STYLE = (-16);const int WS_CHILD = 0x40000000;[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 = Content is Window ? Content as Window : new Window { WindowStyle = WindowStyle.None, ResizeMode = ResizeMode.NoResize, Focusable = false, Width = 0, Height = 0, ShowInTaskbar = false, ShowActivated = false, Background = Brushes.Transparent, Content = Content, AllowsTransparency = true };var hwnd = new WindowInteropHelper(window).EnsureHandle();SetWindowLong(hwnd, GWL_STYLE, GetWindowLong(hwnd, GWL_STYLE) | WS_CHILD);SetParent(hwnd, hwndParent.Handle);window!.Show();return new HandleRef(this, hwnd);}protected override void DestroyWindowCore(HandleRef hwnd){var window = HwndSource.FromHwnd(hwnd.Handle)?.RootVisual as Window;window?.Close();}}
}
三、使用示例
1、嵌入控件
<Window x:Class="WpfApp6.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:WpfApp6"mc:Ignorable="d"Title="MainWindow" Height="360" Width="640"><Grid><local:WpfElementHost Width="400" Height="200"><TextBox Background="RoyalBlue" Foreground="White" FontSize="24" ></TextBox></local:WpfElementHost></Grid>
</Window>
效果预览

2、嵌入Window
(1)xaml中定义Window
因为默认嵌入控件的承载Window使用了AllowsTransparency,如果需要自己定制窗口属性则可以直接使用Window
<Window x:Class="WpfApp6.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:WpfApp6"mc:Ignorable="d"Title="MainWindow" Height="360" Width="640"><Grid><local:WpfElementHost Width="400" Height="200"><Window Title="WPF窗口"><TextBox Background="RoyalBlue" Foreground="White" FontSize="24" ></TextBox></Window></local:WpfElementHost></Grid>
</Window>
效果预览

(2)嵌入已有的Window
创建一个新的Window1

<Window x:Class="WpfApp6.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:WpfApp6"mc:Ignorable="d"Title="MainWindow" Height="360" Width="640"><Grid><local:WpfElementHost Width="400" Height="200"><local:Window1 ></local:Window1></local:WpfElementHost></Grid>
</Window>
效果预览

3、显示在WinForm控件上面
<Window x:Class="WpfApp6.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:WpfApp6"xmlns:wf="clr-namespace:System.Windows.Forms;assembly=System.Windows.Forms"mc:Ignorable="d"Title="MainWindow" Height="450" Width="800"><Grid><WindowsFormsHost Width="300" Height="80" ><wf:TextBox Text="WinForm TextBox" BackColor="255,192,192,192" /></WindowsFormsHost><local:WpfElementHost Width="200" Height="100"><TextBox Opacity="0.6" Background="RoyalBlue" Foreground="White" FontSize="24" Text="WPF TextBox" ></TextBox></local:WpfElementHost></Grid>
</Window>
效果预览

总结
以上就是今天要讲的内容,整体的代码实现是比较简单的,关键是在win32 api设置窗口属性。这个功能的作用还是不小的,比如在嵌入网页上显示wpf控件,或者hwnd播放控件上放一些按钮。这种实现方式也不会有性能问题,绘制都是以窗口为单位的,其实和WinForm有点类似了,每个控件都是一个窗口。
相关文章:
C# wpf 嵌入wpf控件
WPF Hwnd窗口互操作系列 第一章 嵌入Hwnd窗口 第二章 嵌入WinForm控件 第三章 嵌入WPF控件(本章) 第四章 底部嵌入HwndHost 文章目录 WPF Hwnd窗口互操作系列前言一、如何实现?1、继承HwndHost2、添加Content属性3、创建wpf窗口并设置Conten…...
云原生(六)、CICD - Jenkins快速入门
Jenkuns快速入门 一、CICD概述 CICD是持续集成(Continuous Integration)和持续部署(Continuous Deployment)的缩写。它是软件开发中的一种流程和方法论,旨在通过自动化的方式频繁地将代码集成到共享存储库中…...
基于java+springboot+vue实现的付费自习室管理系统(文末源码+Lw+ppt)23-400
摘 要 付费自习室管理系统采用B/S架构,数据库是MySQL。网站的搭建与开发采用了先进的java进行编写,使用了springboot框架。该系统从两个对象:由管理员和用户来对系统进行设计构建。主要功能包括:个人信息修改,对用户…...
【JavaParser笔记02】JavaParser解析Java源代码中的类字段信息(javadoc注释、字段名称)
这篇文章,主要介绍如何使用JavaParser解析Java源代码中的类字段信息(javadoc注释、字段名称)。 目录 一、JavaParser依赖库 1.1、引入依赖 1.2、获取类成员信息 (1)案例代码 <...
Spring IoCDI(3)
DI详解 接下来学习一下依赖注入DI的细节. 依赖注入是一个过程, 是指IoC容器在创建Bean时, 去提供运行时所依赖的资源, 而资源指的就是对象. 在之前的案例中, 使用了Autowired这个注解, 完成了依赖注入这个操作. 简单来说, 就是把对象取出来放到某个类的属性中. 在一些文章中…...
保研线性代数机器学习基础复习1
1.什么是代数(algebra)? 为了形式化一个概念,构建出有关这个概念的符号以及操作符号的公式。 2.什么是线性代数(linear algebra)? 一项关于向量以及操作向量的公式的研究。 3.举一些向量的例子&#x…...
js绑定事件的方法
在JavaScript中,绑定事件的方法主要有以下几种: HTML属性方式:直接在HTML元素中使用事件属性来绑定事件。 html<button onclick"alert(Hello World!)">Click Me</button> DOM属性方式:通过JavaScript代码…...
是德科技keysight N9000B 信号分析仪
181/2461/8938产品概述: 工程的内涵就是将各种创意有机地联系起来,并解决遇到的问题。 CXA 信号分析仪具有出色的实际性能,它是一款出类拔萃、经济高效的基本信号表征工具。 它的功能十分强大,为一般用途和教育行业的用户执行测试…...
软考 - 系统架构设计师 - 架构风格
软件架构风格是指描述特定软件系统组织方式的惯用模式。组织方式描述了系统的组成构件,以及这些构件的组织方式,惯用模式指众多系统所共有的结构和语义。 目录 架构风格 数据流风格 批处理架构风格 管道 - 过滤器架构风格 调用 / 返回风格 主程序…...
CleanMyMac X2024专业免费的国产Mac笔记本清理软件
非常高兴有机会向大家介绍CleanMyMac X 2024这款专业的Mac清理软件。它以其强大的清理能力、系统优化效果、出色的用户体验以及高度的安全性,在Mac清理软件市场中独树一帜。 CleanMyMac X2024全新版下载如下: https://wm.makeding.com/iclk/?zoneid49983 一、主要…...
ES6 模块化操作
ES6模块化主要有两个操作:import 和 export 如果在html文件的script中引用模块的话,要设置<script type"module"> 一种导入导出方法: a.js//分别暴露 export let num 1 export function compute(a, b){return a b }//统…...
统计XML文件内标签的种类和其数量及将xml格式转换为yolov5所需的txt格式
1、统计XML文件内标签的种类和其数量 对于自己标注的数据集,需在标注完成后需要对标注好的XML文件校验,下面是代码,只需将SrcDir换成需要统计的xml的文件夹即可。 import os from tqdm import tqdm import xml.dom.minidomdef ReadXml(File…...
《操作系统导论》第14章读书笔记:插叙:内存操作API
《操作系统导论》第14章读书笔记:插叙:内存操作API —— 杭州 2024-03-30 夜 文章目录 《操作系统导论》第14章读书笔记:插叙:内存操作API1.内存类型1.1.栈内存:它的申请和释放操作是编译器来隐式管理的,所…...
HAProxy + Vitess负载均衡
一、环境搭建 Vitess环境搭建: 具体vitess安装不再赘述,主要是需要启动3个vtgate(官方推荐vtgate和vtablet数量一致) 操作: 在vitess/examples/common/scripts目录中,修改vtgate-up.sh文件,…...
2024年京东云主机租用价格_京东云服务器优惠价格表
2024年京东云服务器优惠价格表,轻量云主机优惠价格5.8元1个月、轻量云主机2C2G3M价格50元一年、196元三年,2C4G5M轻量云主机165元一年,4核8G5M云主机880元一年,游戏联机服务器4C16G配置26元1个月、4C32G价格65元1个月、8核32G费用…...
qt-C++笔记之QSpinBox控件
qt-C笔记之QSpinBox控件 code review! 文章目录 qt-C笔记之QSpinBox控件1.运行2.main.cpp3.main.pro4.《Qt6 C开发指南》:4.4 QSpinBox 和QDoubleSpinBox 1.运行 2.main.cpp #include <QApplication> #include <QSpinBox> #include <QPushButton&g…...
Linux(CentOS)/Windows-C++ 云备份项目(服务器网络通信模块,业务处理模块设计,断点续传设计)
此模块将网络通信模块和业务处理模块进行了合并 网络通信通过httplib库搭建完成业务处理: 文件上传请求:备份客户端上传的文件,响应上传成功客户端列表请求:客户端请求备份文件的请求页面,服务器响应文件下载请求&…...
【QQ版】QQ群短剧机器人源码 全网短剧机器人插件
内容目录 一、详细介绍二、效果展示2.效果图展示 三、学习资料下载 一、详细介绍 QQ版本可以兼容两个框架(HTQQ,MYQQ这两个的vip版也可以使用) 支持私聊与群聊,命令是 搜剧影视关键词 如果无法搜索到影视资源,请使用下方命令&…...
矩阵间关系的建立
参考文献 2-D Compressive Sensing-Based Visually Secure Multilevel Image Encryption Scheme 加密整体流程如下: 我们关注左上角这一部分: 如何在两个图像之间构建关系,当然是借助第3个矩阵。 A. Establish Relationships Between Different Images 简单说明如下: …...
【C++】C到C++的入门知识
目录 1、C关键字 2、命名空间 2.1 命名空间的定义 2.2 命名空间的使用 2.2.1 加命名空间名称及作用域限定符 2.2.2 使用using将命名空间中某个成员引入 2.2.3 使用using namespace 命名空间名称引入 3、C输入&输出 4、缺省参数 4.1 缺省参数的概念 4.2 缺省参数的…...
在软件开发中正确使用MySQL日期时间类型的深度解析
在日常软件开发场景中,时间信息的存储是底层且核心的需求。从金融交易的精确记账时间、用户操作的行为日志,到供应链系统的物流节点时间戳,时间数据的准确性直接决定业务逻辑的可靠性。MySQL作为主流关系型数据库,其日期时间类型的…...
Qt Http Server模块功能及架构
Qt Http Server 是 Qt 6.0 中引入的一个新模块,它提供了一个轻量级的 HTTP 服务器实现,主要用于构建基于 HTTP 的应用程序和服务。 功能介绍: 主要功能 HTTP服务器功能: 支持 HTTP/1.1 协议 简单的请求/响应处理模型 支持 GET…...
C# 类和继承(抽象类)
抽象类 抽象类是指设计为被继承的类。抽象类只能被用作其他类的基类。 不能创建抽象类的实例。抽象类使用abstract修饰符声明。 抽象类可以包含抽象成员或普通的非抽象成员。抽象类的成员可以是抽象成员和普通带 实现的成员的任意组合。抽象类自己可以派生自另一个抽象类。例…...
JUC笔记(上)-复习 涉及死锁 volatile synchronized CAS 原子操作
一、上下文切换 即使单核CPU也可以进行多线程执行代码,CPU会给每个线程分配CPU时间片来实现这个机制。时间片非常短,所以CPU会不断地切换线程执行,从而让我们感觉多个线程是同时执行的。时间片一般是十几毫秒(ms)。通过时间片分配算法执行。…...
Hive 存储格式深度解析:从 TextFile 到 ORC,如何选对数据存储方案?
在大数据处理领域,Hive 作为 Hadoop 生态中重要的数据仓库工具,其存储格式的选择直接影响数据存储成本、查询效率和计算资源消耗。面对 TextFile、SequenceFile、Parquet、RCFile、ORC 等多种存储格式,很多开发者常常陷入选择困境。本文将从底…...
基于SpringBoot在线拍卖系统的设计和实现
摘 要 随着社会的发展,社会的各行各业都在利用信息化时代的优势。计算机的优势和普及使得各种信息系统的开发成为必需。 在线拍卖系统,主要的模块包括管理员;首页、个人中心、用户管理、商品类型管理、拍卖商品管理、历史竞拍管理、竞拍订单…...
什么是VR全景技术
VR全景技术,全称为虚拟现实全景技术,是通过计算机图像模拟生成三维空间中的虚拟世界,使用户能够在该虚拟世界中进行全方位、无死角的观察和交互的技术。VR全景技术模拟人在真实空间中的视觉体验,结合图文、3D、音视频等多媒体元素…...
解析两阶段提交与三阶段提交的核心差异及MySQL实现方案
引言 在分布式系统的事务处理中,如何保障跨节点数据操作的一致性始终是核心挑战。经典的两阶段提交协议(2PC)通过准备阶段与提交阶段的协调机制,以同步决策模式确保事务原子性。其改进版本三阶段提交协议(3PC…...
《信号与系统》第 6 章 信号与系统的时域和频域特性
目录 6.0 引言 6.1 傅里叶变换的模和相位表示 6.2 线性时不变系统频率响应的模和相位表示 6.2.1 线性与非线性相位 6.2.2 群时延 6.2.3 对数模和相位图 6.3 理想频率选择性滤波器的时域特性 6.4 非理想滤波器的时域和频域特性讨论 6.5 一阶与二阶连续时间系统 6.5.1 …...
CTF show 数学不及格
拿到题目先查一下壳,看一下信息 发现是一个ELF文件,64位的 用IDA Pro 64 打开这个文件 然后点击F5进行伪代码转换 可以看到有五个if判断,第一个argc ! 5这个判断并没有起太大作用,主要是下面四个if判断 根据题目…...
