如何在WPF中嵌入其它程序

news/2024/11/23 22:25:54/

在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         }

其它的操作可以参考示例代码,这里不做详细介绍。

最终运行效果如下:

 示例代码


http://www.ppmy.cn/news/1549381.html

相关文章

2411rust,1.81,1.82

1.81.0稳定版 core::error::错误 1.81稳定了核心中的Error特征,允许在#![no_std]库中使用特征.这样在相同错误特征上,可标准化更广泛的Rust生态系统,而不管库的环境. 新的排序实现 都已按新算法更新了标准库中的稳定和不稳定排序实现,从而改进了它们的运行时性能和编译时间…

Tomcat 任意写入文件漏洞(CVE-2017-12615)

1. Tomcat 任意写入文件漏洞&#xff08;CVE-2017-12615&#xff09; 首先进入该漏洞的文件目录下&#xff0c;并使用docker启动靶场环境 查看靶场的端口开放情况 访问靶场&#xff1a;192.168.187.135:8080 刷新页面&#xff0c;使用burp进行抓取数据包&#xff0c;将其发…

C# mysql there can be only one auto column and it must be defined as a key问题解决

在做项目的时候&#xff0c;使用mysql创建表时&#xff0c;报错Incorrect table definition&#xff1b; there can be only one auto column and it must be defined as a key&#xff08;mysql报错表定义不正确只能有一个自动列&#xff0c;并且必须将其定义为键&#xff09;…

自动驾驶系列—探索自动驾驶数据管理的核心技术与平台

&#x1f31f;&#x1f31f; 欢迎来到我的技术小筑&#xff0c;一个专为技术探索者打造的交流空间。在这里&#xff0c;我们不仅分享代码的智慧&#xff0c;还探讨技术的深度与广度。无论您是资深开发者还是技术新手&#xff0c;这里都有一片属于您的天空。让我们在知识的海洋中…

如何用AI写小说(二):Gradio 超简单的网页前端交互

上一篇写了基本的生成小说的脚本&#xff0c;但脚本终归是很丑的代码&#xff0c;不符合优雅的调性&#xff0c;在 huggingface 大家经常用一个叫 gradio 的东西来写交互&#xff0c;虽然我没有什么前端基础&#xff0c;但是这个gradio最大的特点就是简单&#xff01;简单&…

display: none和visibility: hidden的区别

display: none和visibility: hidden的区别 三种隐藏的对比 display: none; DOM 结构&#xff1a;浏览器不会渲染 display 属性为 none 的元素&#xff0c;不占据空间&#xff1b;事件监听&#xff1a;无法进行 DOM 事件监听&#xff1b;性能&#xff1a;动态改变此属性时会引…

深入实践 Shell 脚本编程:高效自动化操作指南

一、什么是 Shell 脚本&#xff1f; Shell 脚本是一种用 Shell 编写的脚本程序&#xff0c;用于执行一系列的命令。它是 Linux/Unix 系统中自动化管理任务的利器&#xff0c;能够显著提升工作效率&#xff0c;特别适合批量处理文件、监控系统状态、自动部署等任务。 二、Shell…

泷羽sec-星河飞雪-shell-2

免责声明 学习视频来自 B 站up主泷羽sec&#xff0c;如涉及侵权马上删除文章。 笔记的只是方便各位师傅学习知识&#xff0c;以下代码、网站只涉及学习内容&#xff0c;其他的都与本人无关&#xff0c;切莫逾越法律红线&#xff0c;否则后果自负。 泷羽sec官网&#xff1a;http…