如何在WPF中嵌入其它程序
在WPF中嵌入其它程序,这里提供两种方案
一、使用WindowsFormHost
使用步骤如下
1、添加WindowsFormsIntegration和System.Windows.Forms引用
2、在界面上放置WindowsFormHost和System.Windows.Forms.Panel
1 <Grid> 2 <WindowsFormsHost> 3 <winform:Panel x:Name="panel"></winform:Panel> 4 </WindowsFormsHost> 5 </Grid>
3、运行被嵌入的程序,获取主窗口句柄,然后调用WinAPI SetParent函数设置被嵌入的程序的父级为panel
Winform控件是有句柄的,直接调用SetParent函数即可。
1 var process = System.Diagnostics.Process.Start("xxx.exe");
2
3 SetParent(process.MainWindowHandle, this.panel.Handle);
这种方案理论可行,但我没有具体尝试。
二、手动控制被嵌入程序的位置和状态
这里我们以WPF嵌入WPF来进行演示,其它程序也可以嵌入,但是要注意:被嵌入的窗口必须是无边框且置顶的。
像一般的窗口程序都可以设置窗口类型,如果是嵌入Unity这种无法控制窗口类型的,可以调用SetWindowsLong函数去除边框,参考代码如下:
1 SetWindowLong(m_hWnd, GWL_EXSTYLE, GetWindowLong(m_hWnd, GWL_EXSTYLE) & ~(WS_EX_WINDOWEDGE | WS_EX_DLGMODALFRAME));
ChildWindow.xaml
1 <Window x:Class="ChildWindow.MainWindow"2 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"3 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"4 xmlns:d="http://schemas.microsoft.com/expression/blend/2008"5 xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"6 xmlns:local="clr-namespace:ChildWindow"7 mc:Ignorable="d"8 Title="MainWindow" Height="450" Width="800" WindowStyle="None" AllowsTransparency="True" Topmost="True">9 <Grid Background="LightGray"> 10 <Label Content="Child Window" HorizontalAlignment="Center" VerticalAlignment="Center"></Label> 11 </Grid> 12 </Window>
HostWindow.xaml
1 <Window x:Class="WPFHostDemoShell.MainWindow"2 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"3 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"4 xmlns:d="http://schemas.microsoft.com/expression/blend/2008"5 xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"6 xmlns:local="clr-namespace:WPFHostDemoShell"7 mc:Ignorable="d"8 Title="MainWindow" Height="450" Width="800" Loaded="Window_Loaded">9 <Grid x:Name="Host"> 10 11 </Grid> 12 </Window>
在窗口的Loaded事件中创建其它程序进程,并嵌入 。
在此之前我们需要要入一些WinAPI函数签名。
User32.cs
1 public class User322 {3 public const uint SWP_SHOWWINDOW = 0x0040;4 public const uint WM_USER = 0x0400;5 public const uint WM_Normal = WM_USER + 1; //正常显示消息6 public const uint WM_Minimal = WM_USER + 2; //最小化消息7 public const uint WM_Exit = WM_USER + 3; //退出消息8 9 [DllImport("User32.dll")]
10 public static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int X, int Y, int cx, int cy, uint uFlags);
11
12 [DllImport("User32.dll")]
13 public static extern uint SendMessage(IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam);
14 }
窗口的Loaded事件中处理如下:
1 IntPtr childWindowHandle = IntPtr.Zero;2 3 private async void Window_Loaded(object sender, RoutedEventArgs e)4 {5 var childExePath = Environment.CurrentDirectory + "\\ChildWindow.exe";6 if (System.IO.File.Exists(childExePath) == false)7 return;8 9 var process = System.Diagnostics.Process.Start(childExePath);
10 process.WaitForInputIdle();
11
12 await Task.Delay(200);
13
14 var point = this.Host.PointToScreen(new Point(0, 0));
15
16 User32.SetWindowPos(process.MainWindowHandle, IntPtr.Zero, (int)point.X, (int)point.Y, (int)this.Host.ActualWidth, (int)this.Host.ActualHeight, User32.SWP_SHOWWINDOW);
17 childWindowHandle = process.MainWindowHandle;
18 }
此时我们运行后,就可以看到窗口已经被嵌入

此时我们还需要处理一些窗口的事件,比如最大化,最小化,移动和大小改变等。
这里我们可以借助WinAPI SendMessage函数来对进程进行简单通信。
我们在ChildWindow增加Win32消息的处理
1 protected override void OnSourceInitialized(EventArgs e)2 {3 base.OnSourceInitialized(e);4 5 HwndSource.FromHwnd(new WindowInteropHelper(this).Handle).AddHook(HwndSourceHook);6 }7 8 protected IntPtr HwndSourceHook(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)9 {
10 switch(msg)
11 {
12 case User32.WM_Minimal:
13 this.WindowState = WindowState.Minimized;
14 break;
15 case User32.WM_Normal:
16 this.WindowState = WindowState.Normal;
17 break;
18 case User32.WM_Exit:
19 this.Close();
20 break;
21 }
22
23 return IntPtr.Zero;
24 }
在父窗口中,窗口关闭时,发送消息到子窗口即可
1 private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e)
2 {
3 User32.SendMessage(childWindowHandle, User32.WM_Exit, IntPtr.Zero, IntPtr.Zero);
4 }
其它的操作可以参考示例代码,这里不做详细介绍。
最终运行效果如下:
示例代码
相关文章:
如何在WPF中嵌入其它程序
在WPF中嵌入其它程序,这里提供两种方案 一、使用WindowsFormHost 使用步骤如下 1、添加WindowsFormsIntegration和System.Windows.Forms引用 2、在界面上放置WindowsFormHost和System.Windows.Forms.Panel 1 <Grid> 2 <WindowsFormsHost> 3…...
大模型呼入系统是什么?
大模型呼入系统是什么? 作者:开源呼叫中心系统 FreeIPCC,Github地址:https://github.com/lihaiya/freeipcc 在呼叫中心领域,大模型呼入是指利用大型语言模型(如GPT等)处理客户呼入的电话请求&a…...
Flutter:SlideTransition位移动画,Interval动画延迟
配置vsync,需要实现一下with SingleTickerProviderStateMixinclass _MyHomePageState extends State<MyHomePage> with SingleTickerProviderStateMixin{// 定义 AnimationControllerlate AnimationController _controller;overridevoid initState() {super.…...
【Elasticsearch入门到落地】2、正向索引和倒排索引
接上篇《1、初识Elasticsearch》 上一篇我们学习了什么是Elasticsearch,以及Elastic stack(ELK)技术栈介绍。本篇我们来什么是正向索引和倒排索引,这是了解Elasticsearch底层架构的核心。 上一篇我们学习到,Elasticsearch的底层是由Lucene实…...
网络安全概论
一、 网络安全是一个综合性的技术。在Internet这样的环境中,其本身的目的就是为了提供一种开放式的交互环境,但是为了保护一些秘密信息,网络安全成为了在开放网络环境中必要的技术之一。网络安全技术是随着网络技术的进步逐步发展的。 网络安…...
后端开发如何高效使用 Apifox?
对于后端开发者来说,日常工作中少不了接口的设计、调试和文档编写。你是否也曾因接口文档更新不及时、测试工具分散而头疼不已?Apifox,这款全能型工具,或许能成为你的效率神器! Apifox究竟有哪些功能能帮助后端开发者…...
实现List接口的三类-ArrayList -Vector -LinkedList
一、ArrayList 数据结构与存储原理 ArrayList是基于动态数组实现的。它在内存中是一块连续的存储空间。当创建一个ArrayList时,会初始化一个默认大小(通常为10)的数组。随着元素的不断添加,如果数组容量不够,会进行扩…...
LeetCode 904.水果成篮
LeetCode 904.水果成篮 思路🧐: 求水果的最大数目,也就是求最大长度,我们是单调的向前求解,则能够想到使用滑动窗口进行解答,可以用hash表统计每个种类的个数,kinds变量统计当前种类,…...
GitHub 开源项目 Puter :云端互联操作系统
每天面对着各种云盘和在线应用,我们常常会遇到这样的困扰。 文件分散在不同平台很难统一管理,付费订阅的软件越来越多,更不用说那些烦人的存储空间限制了。 最近在 GitHub 上发现的一个开源项目 Puter 彻底改变了我的在线办公方式。 让人惊…...
美创科技入选2024数字政府解决方案提供商TOP100!
11月19日,国内专业咨询机构DBC德本咨询发布“2024数字政府解决方案提供商TOP100”榜单。美创科技凭借在政府数据安全领域多年的项目经验、技术优势与创新能力,入选收录。 作为专业数据安全产品与服务提供商,美创科技一直致力于为政府、金融、…...
七天掌握SQL--->第五天:数据库安全与权限管理
1.1 用户权限管理 用户权限管理是指控制用户对数据库的访问和操作权限。在MySQL中,可以使用GRANT和REVOKE命令来管理用户权限。 GRANT命令用于授予用户权限。语法如下: GRANT privileges ON database.table TO userhost IDENTIFIED BY password;其中&…...
数学建模学习(138):基于 Python 的 AdaBoost 分类模型
1. AdaBoost算法简介 AdaBoost(Adaptive Boosting)是一种经典的集成学习算法,由Yoav Freund和Robert Schapire提出。它通过迭代训练一系列的弱分类器,并将这些弱分类器组合成一个强分类器。算法的核心思想是:对于被错误分类的样本,在下一轮训练中增加其权重;对于正确分类…...
丹摩|丹摩智算平台深度评测
1. 丹摩智算平台介绍 随着人工智能和大数据技术的快速发展,越来越多的智能计算平台涌现,为科研工作者和开发者提供高性能计算资源。丹摩智算平台作为其中的一员,定位于智能计算服务的提供者,支持从数据处理到模型训练的全流程操作…...
『VUE』34. 异步组件(详细图文注释)
目录 加载速度的优化示例代码总结 欢迎关注 『VUE』 专栏,持续更新中 欢迎关注 『VUE』 专栏,持续更新中 加载速度的优化 实际项目中你可能会有几十个组件,如果一开始就加载了全部组件(哪怕其中有些组件你暂时用不到)这无疑大大增加了响应时间,用户体验…...
深入解析自校正控制(STC)算法及python实现
目录 深入解析自校正控制(STC)算法第一部分:自校正控制算法概述1.1 什么是自校正控制1.2 自校正控制的核心思想1.3 STC 的应用场景1.4 STC 的分类第二部分:自校正控制算法的数学基础2.1 动态系统模型2.2 参数辨识方法2.3 控制器设计2.4 稳定性分析第三部分:Python 实现自校…...
《macOS 开发环境配置与应用开发》
一、引言 macOS 作为一款强大而流行的操作系统,为开发者提供了丰富的开发机会和优秀的开发环境。无论是开发原生的 macOS 应用,还是进行跨平台开发,了解和掌握 macOS 开发环境的配置以及应用开发的方法至关重要。本文将详细介绍 macOS 开发环…...
WebSocket 常见问题及解决方案
什么是 WebSocket? WebSocket 是一种在单个 TCP 连接上进行全双工通信的协议。它允许客户端和服务器之间进行双向通信,而不需要像传统 HTTP 那样每次请求都需要建立新的连接。WebSocket 协议在 2011 年被 IETF 定义为 RFC 6455 标准。 特点 双向通信&…...
如何在 .gitignore 中仅保留特定文件:以忽略文件夹中的所有文件为例
在日常的开发工作中,使用 Git 来管理项目是不可或缺的一部分。项目中的某些文件夹可能包含大量的临时文件、生成文件或不需要版本控制的文件。在这种情况下,我们通常会使用 .gitignore 文件来忽略这些文件夹。然而,有时我们可能希望在忽略整个…...
详解八大排序(一)------(插入排序,选择排序,冒泡排序,希尔排序)
文章目录 前言1.插入排序(InsertSort)1.1 核心思路1.2 实现代码 2.选择排序(SelectSort)2.1 核心思路2.2 实现代码 3.冒泡排序(BubbleSort)3.1 核心思路3.2 实现代码 4.希尔排序(ShellSort&…...
Linux虚拟机空间扩容(新增磁盘并分区挂载)
1、命令shutdown -h now关闭虚拟机(要关机后再进行新增磁盘操作) 云平台进入虚拟机管理,新增磁盘 成功添加一块100G的磁盘 3、在Linux终端下执行该命令:lsblk 发现有新添加的磁盘。 也新增了/dev/vdb 3、分区 输入命令࿱…...
基于距离变化能量开销动态调整的WSN低功耗拓扑控制开销算法matlab仿真
目录 1.程序功能描述 2.测试软件版本以及运行结果展示 3.核心程序 4.算法仿真参数 5.算法理论概述 6.参考文献 7.完整程序 1.程序功能描述 通过动态调整节点通信的能量开销,平衡网络负载,延长WSN生命周期。具体通过建立基于距离的能量消耗模型&am…...
K8S认证|CKS题库+答案| 11. AppArmor
目录 11. AppArmor 免费获取并激活 CKA_v1.31_模拟系统 题目 开始操作: 1)、切换集群 2)、切换节点 3)、切换到 apparmor 的目录 4)、执行 apparmor 策略模块 5)、修改 pod 文件 6)、…...
深入浅出:JavaScript 中的 `window.crypto.getRandomValues()` 方法
深入浅出:JavaScript 中的 window.crypto.getRandomValues() 方法 在现代 Web 开发中,随机数的生成看似简单,却隐藏着许多玄机。无论是生成密码、加密密钥,还是创建安全令牌,随机数的质量直接关系到系统的安全性。Jav…...
AtCoder 第409场初级竞赛 A~E题解
A Conflict 【题目链接】 原题链接:A - Conflict 【考点】 枚举 【题目大意】 找到是否有两人都想要的物品。 【解析】 遍历两端字符串,只有在同时为 o 时输出 Yes 并结束程序,否则输出 No。 【难度】 GESP三级 【代码参考】 #i…...
python如何将word的doc另存为docx
将 DOCX 文件另存为 DOCX 格式(Python 实现) 在 Python 中,你可以使用 python-docx 库来操作 Word 文档。不过需要注意的是,.doc 是旧的 Word 格式,而 .docx 是新的基于 XML 的格式。python-docx 只能处理 .docx 格式…...
【单片机期末】单片机系统设计
主要内容:系统状态机,系统时基,系统需求分析,系统构建,系统状态流图 一、题目要求 二、绘制系统状态流图 题目:根据上述描述绘制系统状态流图,注明状态转移条件及方向。 三、利用定时器产生时…...
论文浅尝 | 基于判别指令微调生成式大语言模型的知识图谱补全方法(ISWC2024)
笔记整理:刘治强,浙江大学硕士生,研究方向为知识图谱表示学习,大语言模型 论文链接:http://arxiv.org/abs/2407.16127 发表会议:ISWC 2024 1. 动机 传统的知识图谱补全(KGC)模型通过…...
leetcodeSQL解题:3564. 季节性销售分析
leetcodeSQL解题:3564. 季节性销售分析 题目: 表:sales ---------------------- | Column Name | Type | ---------------------- | sale_id | int | | product_id | int | | sale_date | date | | quantity | int | | price | decimal | -…...
自然语言处理——Transformer
自然语言处理——Transformer 自注意力机制多头注意力机制Transformer 虽然循环神经网络可以对具有序列特性的数据非常有效,它能挖掘数据中的时序信息以及语义信息,但是它有一个很大的缺陷——很难并行化。 我们可以考虑用CNN来替代RNN,但是…...
MySQL中【正则表达式】用法
MySQL 中正则表达式通过 REGEXP 或 RLIKE 操作符实现(两者等价),用于在 WHERE 子句中进行复杂的字符串模式匹配。以下是核心用法和示例: 一、基础语法 SELECT column_name FROM table_name WHERE column_name REGEXP pattern; …...
