WPF内嵌其他进程的窗口

news2025/7/18 1:03:44

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.coloradmin.cn/o/2375723.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

CVPR2025 | Prompt-CAM: 让视觉 Transformer 可解释以进行细粒度分析

Prompt-CAM: Making Vision Transformers Interpretable for Fine-Grained Analysis 摘要-Abstract引言-Introduction方法-Approach预备知识-PreliminariesPrompt-CAM: Prompt Class Attention Map特征识别与定位-Trait Identification and Localization变体与扩展-Variants an…

解锁 DevOps 新境界 :使用 Flux 进行 GitOps 现场演示 – 自动化您的 Kubernetes 部署

前言 GitOps 是实现持续部署的云原生方式。它的名字来源于标准且占主导地位的版本控制系统 Git。GitOps 的 Git 在某种程度上类似于 Kubernetes 的 etcd&#xff0c;但更进一步&#xff0c;因为 etcd 本身不保存版本历史记录。毋庸置疑&#xff0c;任何源代码管理服务&#xf…

LLM大模型中的基础数学工具—— 信号处理与傅里叶分析

Q51: 推导傅里叶变换 的 Parseval 定理 傅里叶变换的 Parseval 定理揭示了啥关系&#xff1f; Parseval 定理揭示了傅里叶变换中时域与频域的能量守恒关系&#xff0c;即信号在时域的总能量等于其在频域的总能量。这就好比一个物体无论从哪个角度称重&#xff0c;重量始终不…

橡胶制品行业质检管理的痛点 质检LIMS如何重构橡胶制品质检价值链

橡胶制品广泛应用于汽车、医疗、航空等领域&#xff0c;其性能稳定性直接关联终端产品的安全性。从轮胎耐磨性测试到密封件耐腐蚀性验证&#xff0c;每一项检测数据都是企业参与市场竞争的核心筹码。然而&#xff0c;传统实验室管理模式普遍面临设备调度混乱、检测流程追溯断层…

CAElinux系统详解

CAElinux 系统详解&#xff1a;从系统层面到专业应用 一、CAElinux 的定位与核心目标 CAElinux 是一款专门为 计算机辅助工程&#xff08;CAE&#xff09; 设计的定制化 Linux 发行版&#xff0c;目标用户为从事工程仿真、数值模拟、高性能计算&#xff08;HPC&#xff09;的…

计算机系统----软考中级软件设计师(自用学习笔记)

目录 1、计算机的基本硬件系统 2、CPU的功能 3、运算器的组成 4、控制器 5、计算机的基本单位 6、进制转换问题 7、原码、反码、补码、移码 8、浮点数 9、寻址方式 10、奇偶校验码 11、海明码 12、循环冗余校验码 13、RISC和CISC 14、指令的处理方式 15、存储器…

django的权限角色管理(RBAC)

在 Django 中&#xff0c;User、Group 和 Permission 是权限系统的核心组件。下面通过代码示例演示它们的 CRUD&#xff08;创建、读取、更新、删除&#xff09; 操作&#xff1a; 一、User 模型 CRUD from django.contrib.auth.models import User# 创建用户 user User.obje…

线性表-顺序表(Sequential List)

1 线性表 1.1 顺序表&#xff08;Sequential List&#xff09; 顺序表并不难理解&#xff0c;主要是知道顺序表是在内存中连续存储的一段数据&#xff0c;知道这个后&#xff0c;相应的算法也就非常简单了。 线性表的顺序表示指的是用一组地址连续的存储单元依次存储线性表的…

【阿里云免费领取域名以及ssl证书,通过Nginx反向代理web服务】

文章目录 前言一、申请域名1.1 访问阿里云官网1.2 输入自定义域名1.3 创建个人模板1.4 支付1元可以使用域名1年1.5 按照提示实名认证1.6 实名认证成功 二、域名解析2.1 选择域名解析2.2 解析设置2.3 快速添加解析2.4 选择对应类型2.5 解析成功 三、申请免费ssl证书3.1 访问阿里…

数据分析2

五、文件 CSV Comma-Separated Value&#xff0c;逗号分割值。CSV文件以纯文本形式存储表格数据&#xff08;数字和文本&#xff09;。 CSV记录间以某种换行符分隔&#xff0c;每条记录由字段组成&#xff0c;字段间以其他字符或字符串分割&#xff0c;最常用逗号或制表符。…

实战项目5(08)

目录 任务场景一 【r1配置】 【r2配置】 【r3配置】 ​​​​​​​任务场景二 【r1配置】 【r2配置】 ​​​​​​​任务场景一 按照下图完成网络拓扑搭建和配置 任务要求&#xff1a; 通过在路由器R1、R2和R3上配置静态路由&#xff0c;实现网络中各终端PC能够正常…

.NET MAUI 基础知识

文章目录 什么是 .NET MAUI&#xff1f;MAUI的核心特点与Xamarin.Forms的区别 开发环境搭建安装Visual Studio 2022安装必要组件配置Android开发环境配置iOS开发环境验证安装 创建第一个MAUI应用创建新项目MAUI项目结构解析理解关键文件运行应用程序简单修改示例使用热重载 MAU…

佰力博科技与您探讨表面电阻的测试方法及应用领域

表面电阻测试是一种用于测量材料表面电阻值的技术&#xff0c;广泛应用于评估材料的导电性能、静电防护性能以及绝缘性能。 1、表面电阻的测试测试方法&#xff1a; 表面电阻测试通常采用平行电极法、同心圆电极法和四探针法等方法进行。其中&#xff0c;平行电极法通过在试样…

鹅厂面试数学题

题目 一个圆上随机取三个点&#xff0c;求这三个点构成锐角三角形的概率。 解答 根据圆周角定理&#xff0c;此题目等价为&#xff1a;一条线段长度为1的线段随机取两个点分成三段&#xff0c;任意一段长度均不大于1/2的概率。记前两段的长度为&#xff0c;则第三段的长度为…

java基础-package关键字、MVC、import关键字

1.package关键字&#xff1a; &#xff08;1&#xff09;为了更好管理类&#xff0c;提供包的概念 &#xff08;2&#xff09;声明类或接口所属的包&#xff0c;声明在源文件首行 &#xff08;3&#xff09;包&#xff0c;属于标识符&#xff0c;用小写字母表示 &#xff0…

[6-2] 定时器定时中断定时器外部时钟 江协科技学习笔记(41个知识点)

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 V 30 31 32 33 34 35 36 37 38 39 40 41

【PmHub后端篇】PmHub中基于自定义注解和AOP的服务接口鉴权与内部认证实现

1 引言 在现代软件开发中&#xff0c;尤其是在微服务架构下&#xff0c;服务接口的鉴权和内部认证是保障系统安全的重要环节。本文将详细介绍PmHub中如何利用自定义注解和AOP&#xff08;面向切面编程&#xff09;实现服务接口的鉴权和内部认证&#xff0c;所涉及的技术知识点…

多模态AI新纪元:Vertex AI Gemini与Spring AI深度集成实践

企业级AI集成进阶&#xff1a;Spring AI与Vertex AI Gemini的配置与调优实战 一、前沿技术&#xff1a;多模态模型的企业级配置范式 在生成式AI技术快速迭代的当下&#xff0c;企业级应用对模型配置的精细化需求日益增长。Vertex AI Gemini作为Google推出的多模态大模型&…

开源AI数字人分身克隆小程序源码系统深度剖析:从搭建到应用

在人工智能与小程序生态深度融合的当下&#xff0c;开源 AI 数字人分身克隆小程序源码成为开发者的热门工具。从搭建基础环境到实现实际应用&#xff0c;这一过程涉及多项技术与复杂流程。本文将带您深入剖析开源 AI 数字人分身克隆小程序源码&#xff0c;揭开其从搭建到应用的…

ETL背景介绍_1:数据孤岛仓库的介绍

1 ETL介绍 1.1 数据孤岛 随着企业内客户数据大量的涌现&#xff0c;单个数据库已不再足够。为了储存这些数据&#xff0c;公司通常会建立多个业务部门组织的数据库来保存数据。比如&#xff0c;随着数据量的增长&#xff0c;公司通常可能会构建数十个独立运行的业务数据库&am…