当前位置: 首页 > backend >正文

WPF内嵌其他进程的窗口

WPF内嵌其他进程窗口的常见方法有 HwndHost + SetParentWindowsFormsHost + WinForms Panel + SetParent

推荐使用自定义HwndHost

两者的对比区别
在这里插入图片描述
示例代码

public class MyWndHost : HwndHost
{const int WS_CHILD = 0x40000000;const int WS_VISIBLE = 0x10000000;const int WS_CLIPCHILDREN = 0x02000000;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, IntPtr pvParam);[DllImport("user32.dll")]internal static extern bool DestroyWindow(IntPtr hwnd);public static readonly DependencyProperty HandleProperty = DependencyProperty.Register("Handle", typeof(IntPtr), typeof(MyWndHost), new PropertyMetadata(IntPtr.Zero));public new IntPtr Handle{get => (IntPtr)GetValue(HandleProperty);set => SetValue(HandleProperty, value);}protected override HandleRef BuildWindowCore(HandleRef hwndParent){Handle = CreateWindowEx(0, "static", "",WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS,0, 0,(int)Width, (int)Height,hwndParent.Handle,IntPtr.Zero,IntPtr.Zero,IntPtr.Zero);return new HandleRef(this, Handle);}protected override void DestroyWindowCore(HandleRef hwnd){DestroyWindow(hwnd.Handle);}
}
<Grid><!--WindowsFormsHost--><Grid Margin="12,0,0,0" x:Name="web2Layout" Background="Black"><wfi:WindowsFormsHost Name="windowsFormsHost" ><wf:Panel x:Name="hostPanel"/></wfi:WindowsFormsHost></Grid><!--自定义HwndHost--><ui:MyWndHost x:Name="MyWnd"/>
</Grid>
 public partial class WebView : System.Windows.Controls.UserControl{private IntPtr m_hWndChild = IntPtr.Zero;private Process _electronProcess;[DllImport("user32.dll", SetLastError = true)]private static extern IntPtr SetParent(IntPtr hWndChild, IntPtr hWndNewParent);[DllImport("user32.dll")]private static extern int SetWindowLong(IntPtr hWnd, int nIndex, uint dwNewLong);[DllImport("user32.dll")]private static extern uint GetWindowLong(IntPtr hWnd, int nIndex);[DllImport("user32.dll")]private static extern bool MoveWindow(IntPtr hWnd, int X, int Y, int nWidth, int nHeight, bool bRepaint);private const int GWL_STYLE = -16;private const uint WS_CHILD = 0x40000000;private const uint WS_BORDER = 0x00800000;public WebView(){InitializeComponent();Loaded += Web2Container_Loaded;SizeChanged += Web2Container_SizeChanged;}private void Web2Container_Loaded(object sender, RoutedEventArgs e){StartElectronApp();}private void StartElectronApp(){var path = AppDomain.CurrentDomain.BaseDirectory + @"Exteral\MyElectronApp.exe";_electronProcess = new Process{StartInfo ={FileName = path,UseShellExecute = false}};_electronProcess.Start();Task.Run(() =>{while (_electronProcess.MainWindowHandle == IntPtr.Zero && !_electronProcess.HasExited){Thread.Sleep(100);_electronProcess.Refresh();}if (!_electronProcess.HasExited) ToSetWndParent(_electronProcess.MainWindowHandle);});}private async void ToSetWndParent(IntPtr wnd){await Dispatcher.InvokeAsync(() =>{if (this.FindName("MyWnd") is MyWndHost wfh && wfh.Handle != IntPtr.Zero){m_hWndChild = wnd;SetParent(m_hWndChild, wfh.Handle);uint style = GetWindowLong(m_hWndChild, GWL_STYLE);style = (style & ~WS_BORDER) | WS_CHILD;SetWindowLong(m_hWndChild, GWL_STYLE, style);AdjustChildWindowSize();}});}private void Web2Container_SizeChanged(object sender, SizeChangedEventArgs e){AdjustChildWindowSize();}private void AdjustChildWindowSize(){if (m_hWndChild != IntPtr.Zero){var dpiScale = GetDpiFromVisual(this);MoveWindow(m_hWndChild,0,0,(int)(ActualWidth * dpiScale),(int)(ActualHeight * dpiScale),true);}}private double GetDpiFromVisual(System.Windows.Media.Visual visual){var source = PresentationSource.FromVisual(visual);double dpiX = 96.0;if (source?.CompositionTarget != null){dpiX = 96.0 * source.CompositionTarget.TransformToDevice.M11;}return dpiX / 96.0;}}

效果示例
在这里插入图片描述

http://www.xdnf.cn/news/4927.html

相关文章:

  • 鸿蒙NEXT开发动画案例5
  • tomcat6性能优化
  • MySQL 数据库操作
  • uniapp小程序轮播图高度自适应优化详解
  • 使用Python 打造多格式文件预览工具 — 图、PDF、Word、Excel 一站式查看
  • Java SE(10)——抽象类接口
  • 高效C/C++之十:Coverity修复问题:尽量多使用 c++强制类型转化
  • 人工智能之数学基础:二次型
  • 内网渗透——红日靶场三
  • HOT 100 | 【子串】76.最小覆盖子串、【普通数组】53.最大子数组和、【普通数组】56.合并区间
  • AI与计算机视觉(CV):目标检测与图像分割的最新进展
  • 行业 |四大痛点待破:“拆解”DeepSeek一体机
  • 英伟达Blackwell架构重构未来:AI算力革命背后的技术逻辑与产业变革
  • 【强化学习】动态规划(Dynamic Programming, DP)算法
  • Jenkins集成Maven
  • 如何构建容器镜像并将其推送到极狐GitLab容器镜像库?
  • 【亲测有效】如何清空但不删除GitHub仓库中的所有文件(main分支)
  • 单例模式的两种设计
  • [论文阅读]Deeply-Supervised Nets
  • Idea Code Templates配置
  • K8S - Harbor 镜像仓库部署与 GitLab CI 集成实战
  • 工业与协议融合篇:如何将多个协议集成进一个系统?
  • OpenCV中适用华为昇腾(Ascend)后端的逐元素操作(Per-element Operations)
  • MCU存储系统架构解析
  • 面试问题(连载。。。。)
  • 【Bootstrap V4系列】学习入门教程之 组件-下拉菜单(Dropdowns)
  • k8s术语之secret
  • 数据库——关系代数之扩展操作
  • Java—— 集合 Collection
  • SNMP 协议介绍、开发方法及示例