深圳品牌做网站,手机上编写html的软件,自贡跨省特大虚假广告案,爱战网关键词挖掘WPF Hwnd窗口互操作系列
第一章 嵌入Hwnd窗口 第二章 嵌入WinForm控件 第三章 嵌入WPF控件 第四章 嵌入外部程序#xff08;本章#xff09; 第五章 底部嵌入HwndHost 文章目录 WPF Hwnd窗口互操作系列前言一、如何实现#xff1f;1、定义属性2、进程嵌入#xff08;1本章 第五章 底部嵌入HwndHost 文章目录 WPF Hwnd窗口互操作系列前言一、如何实现1、定义属性2、进程嵌入1启动进程2、进程加入作业对象3、获取主窗口句柄 3、销毁进程 二、完整代码三、使用示例1、嵌入ffplay.exe 总结 前言
实现嵌入各种窗口控件后其实还会有一种需求嵌入外部程序我们有时可能需要嵌入一个浏览器或者或者播放器等一些已有的程序其嵌入原理也和前面差不多只要能获取进程的主窗口句柄然后将窗口嵌入。 一、如何实现
1、定义属性
定义一个依赖属性提供给xaml设置进程运行的命令行
public class AppHost : HwndHost
{/// summary/// 进程运行的命令行/// /summarypublic string Cmdline{get { return (string)GetValue(CmdlineProperty); }set { SetValue(CmdlineProperty, value); }}// Using a DependencyProperty as the backing store for Cmdline. This enables animation, styling, binding, etc...public static readonly DependencyProperty CmdlineProperty DependencyProperty.Register(Cmdline, typeof(string), typeof(AppHost), new PropertyMetadata());
} 2、进程嵌入
在下列方法中进行进程嵌入具体操作如下列步骤。
protected override HandleRef BuildWindowCore(HandleRef hwndParent)1启动进程
var cmds Cmdline.Split( , 2);
Process? _process;
_process.StartInfo.FileName cmds.First();
_process.StartInfo.Arguments cmds.Last();
_process.StartInfo.UseShellExecute false;
_process.StartInfo.CreateNoWindow true;
_process.StartInfo.WindowStyle ProcessWindowStyle.Minimized;
_process.Start();2、进程加入作业对象
这个步骤是用于管理进程确保《子进程跟随主进程关闭》。
static Job _job new Job();_job.AddProcess(_process.Handle);3、获取主窗口句柄
下列提供的是简单获取主窗口句柄的方法。通过延时等待的方式获取。需要精确时间获取主窗口句柄则可以使用钩子在子进程窗口创建事件中获取句柄。
for (int i 0; i 200 _process.MainWindowHandle 0; i) Thread.Sleep(5);
if (_process.MainWindowHandle 0)
{throw new Exception(process no window);
}
return new HandleRef(this, Handle);3、销毁进程
protected override void DestroyWindowCore(HandleRef hwnd)
{_process?.Kill();_process?.Dispose();_process null;
}二、完整代码
其中Job对象在《子进程跟随主进程关闭》中。 AppHost.cs
using JobManagement;
using System.ComponentModel;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Windows;
using System.Windows.Interop;
using Process System.Diagnostics.Process;
using TextBox System.Windows.Controls.TextBox;
using Thread System.Threading.Thread;namespace WpfHwndElement
{/// summary/// 需要手动dispose此控件。/// /summarypublic class AppHost : HwndHost{static Job _job new Job();Process? _process;/// summary/// 进程运行的命令行/// /summarypublic string Cmdline{get { return (string)GetValue(CmdlineProperty); }set { SetValue(CmdlineProperty, value); }}// Using a DependencyProperty as the backing store for Cmdline. This enables animation, styling, binding, etc...public static readonly DependencyProperty CmdlineProperty DependencyProperty.Register(Cmdline, typeof(string), typeof(AppHost), new PropertyMetadata());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(NativeHost), new PropertyMetadata(IntPtr.Zero));protected override HandleRef BuildWindowCore(HandleRef hwndParent){try{if (DesignerProperties.GetIsInDesignMode(this)) throw new Exception(design mode wont show app);var cmds Cmdline.Split( , 2);_process new Process();_process.StartInfo.FileName cmds.First();_process.StartInfo.Arguments cmds.Length 1 ? cmds.Last() : ;_process.StartInfo.UseShellExecute false;_process.StartInfo.CreateNoWindow true;_process.StartInfo.WindowStyle ProcessWindowStyle.Minimized;_process.Start();_job.AddProcess(_process.Handle);for (int i 0; i 200 _process.MainWindowHandle 0; i) Thread.Sleep(5);if (_process.MainWindowHandle 0){throw new Exception(process no window);}Handle _process.MainWindowHandle;var wndStyle GetWindowLong(Handle, GWL_STYLE);wndStyle ~WS_THICKFRAME;wndStyle ~WS_CAPTION;SetWindowLong(Handle, GWL_STYLE, wndStyle | WS_CHILD);SetParent(Handle, hwndParent.Handle);}catch (Exception ex){var window new Window() { Width 0, Height 0, ResizeMode ResizeMode.NoResize, WindowStyle WindowStyle.None, Content new TextBox() { IsReadOnly true, Text ex.Message ex.StackTrace, TextWrapping TextWrapping.Wrap } };var hwnd new WindowInteropHelper(window).EnsureHandle();window.Show();SetWindowLong(hwnd, GWL_STYLE, GetWindowLong(hwnd, GWL_STYLE) | WS_CHILD);SetParent(hwnd, hwndParent.Handle);Handle hwnd;}return new HandleRef(this, Handle);}protected override void DestroyWindowCore(HandleRef hwnd){var window HwndSource.FromHwnd(hwnd.Handle)?.RootVisual as Window;window?.Close();_process?.Kill();_process?.Dispose();_process null;}const int WS_CAPTION 0x00C00000;const int WS_THICKFRAME 0x00040000;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);}
}三、使用示例
1、嵌入ffplay.exe
MainWindow.xaml
Window x:ClassWpfHwndElement.MainWindowxmlnshttp://schemas.microsoft.com/winfx/2006/xaml/presentationxmlns:xhttp://schemas.microsoft.com/winfx/2006/xamlxmlns:dhttp://schemas.microsoft.com/expression/blend/2008xmlns:mchttp://schemas.openxmlformats.org/markup-compatibility/2006xmlns:localclr-namespace:WpfHwndElementmc:IgnorabledTitleMainWindow Height360 Width640 Gridlocal:AppHost Cmdlineffplay Width200 Height200/local:AppHost/Grid
/Window效果预览 总结
以上就是今天要讲的内容嵌入外部程序还是相对比较容易实现的而且也有一定的使用场景。创建进程并能获取到进程的主窗口句柄即可。另外要注意的是管理子进程的退出其他都问题不大。