C# wpf 嵌入wpf控件

WPF Hwnd窗口互操作系列

第一章 嵌入Hwnd窗口
第二章 嵌入WinForm控件
第三章 嵌入WPF控件(本章)


文章目录

  • WPF Hwnd窗口互操作系列
  • 前言
  • 一、如何实现?
    • 1、继承HwndHost
    • 2、添加Content属性
    • 3、创建wpf窗口并设置Content
    • 4、关闭wpf窗口
  • 二、完整代码
  • 三、使用示例
    • 1、嵌入控件
    • 2、嵌入Window
      • (1)xaml中定义Window
      • (2)嵌入已有的Window
    • 3、显示在WinForm控件上面
  • 总结


前言

通过前面的章节我们了解到了如何嵌入Hwnd窗口以及WinForm控件,但是嵌入的控件存在覆盖wpf控件的情况,嵌入控件上面无法显示王鹏飞控件,对UI的布局有一定的影响。本文提供一种解决方法,
将wpf控件通过HwndHost的方式嵌入到wpf界面中,以实现HwndHost控件上显示wpf控件的功能。


一、如何实现?

1、继承HwndHost

和其他嵌入方式一样,需要先继承HwndHost。

public class WpfElementHost : HwndHost

2、添加Content属性

添加一个Content属性,提供给xaml使用。这个Content属性就是需要嵌入的wpf控件。

[ContentProperty("Content")]
public class WpfElementHost : HwndHost
{
    public UIElement Content
    {
        get { return (UIElement)GetValue(ContentProperty); }
        set { SetValue(ContentProperty, value); }
    }
    public static readonly DependencyProperty ContentProperty =
        DependencyProperty.RegisterAttached("Content", typeof(UIElement), typeof(WpfElementHost), new PropertyMetadata(null));
}

3、创建wpf窗口并设置Content

实现抽象方法窗口wpf窗口,这里参考第一章的嵌入wpf窗口,以及给窗口设置Content属性。

protected override HandleRef BuildWindowCore(HandleRef hwndParent)
{
    var window = Content is Window ? Content as Window : new Window { WindowStyle = WindowStyle.None, ResizeMode = ResizeMode.NoResize, Focusable = false, Width = 0, Height = 0, ShowInTaskbar = false, ShowActivated = false, Background = Brushes.Transparent, Content = Content, AllowsTransparency = true };
    var hwnd = new WindowInteropHelper(window).EnsureHandle();
    SetWindowLong(hwnd, GWL_STYLE, GetWindowLong(hwnd, GWL_STYLE) | WS_CHILD);
    User32.SetParent(hwnd, hwndParent.Handle);
    window!.Show();
    return new HandleRef(this, hwnd);
}

4、关闭wpf窗口

实现抽象方法,关闭窗口

protected override void DestroyWindowCore(HandleRef hwnd)
{
    var window = HwndSource.FromHwnd(hwnd.Handle)?.RootVisual as Window;
    window?.Close();
}

二、完整代码

WpfElementHost.cs

using System.Runtime.InteropServices;
using System.Windows;
using System.Windows.Interop;
using System.Windows.Markup;
using Brushes = System.Windows.Media.Brushes;
namespace WpfHwndElement
{
    [ContentProperty("Content")]
    public class WpfElementHost : HwndHost
    {
        public UIElement Content
        {
            get { return (UIElement)GetValue(ContentProperty); }
            set { SetValue(ContentProperty, value); }
        }
        public static readonly DependencyProperty ContentProperty =
            DependencyProperty.RegisterAttached("Content", typeof(UIElement), typeof(WpfElementHost), new PropertyMetadata(null));
        const int GWL_STYLE = (-16);
        const int WS_CHILD = 0x40000000;
        [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);
        protected override HandleRef BuildWindowCore(HandleRef hwndParent)
        {
            var window = Content is Window ? Content as Window : new Window { WindowStyle = WindowStyle.None, ResizeMode = ResizeMode.NoResize, Focusable = false, Width = 0, Height = 0, ShowInTaskbar = false, ShowActivated = false, Background = Brushes.Transparent, Content = Content, AllowsTransparency = true };
            var hwnd = new WindowInteropHelper(window).EnsureHandle();
            SetWindowLong(hwnd, GWL_STYLE, GetWindowLong(hwnd, GWL_STYLE) | WS_CHILD);
            SetParent(hwnd, hwndParent.Handle);
            window!.Show();
            return new HandleRef(this, hwnd);
        }
        protected override void DestroyWindowCore(HandleRef hwnd)
        {
            var window = HwndSource.FromHwnd(hwnd.Handle)?.RootVisual as Window;
            window?.Close();
        }
    }
}

三、使用示例

1、嵌入控件

<Window x:Class="WpfApp6.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WpfApp6"
        mc:Ignorable="d"
        Title="MainWindow" Height="360" Width="640">
    <Grid>
        <local:WpfElementHost Width="400" Height="200">
            <TextBox Background="RoyalBlue" Foreground="White" FontSize="24" ></TextBox>
        </local:WpfElementHost>
    </Grid>
</Window>

效果预览
在这里插入图片描述

2、嵌入Window

(1)xaml中定义Window

因为默认嵌入控件的承载Window使用了AllowsTransparency,如果需要自己定制窗口属性则可以直接使用Window

<Window x:Class="WpfApp6.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WpfApp6"
        mc:Ignorable="d"
        Title="MainWindow" Height="360" Width="640">
    <Grid>
        <local:WpfElementHost Width="400" Height="200">
            <Window Title="WPF窗口">
                <TextBox Background="RoyalBlue" Foreground="White" FontSize="24" ></TextBox>
            </Window>
        </local:WpfElementHost>
    </Grid>
</Window>

效果预览
在这里插入图片描述

(2)嵌入已有的Window

创建一个新的Window1
在这里插入图片描述

<Window x:Class="WpfApp6.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WpfApp6"
        mc:Ignorable="d"
        Title="MainWindow" Height="360" Width="640"
        >
    <Grid>
        <local:WpfElementHost Width="400" Height="200">
            <local:Window1 >
            </local:Window1>
        </local:WpfElementHost>
    </Grid>
</Window>

效果预览
在这里插入图片描述

3、显示在WinForm控件上面

<Window x:Class="WpfApp6.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WpfApp6"
        xmlns:wf="clr-namespace:System.Windows.Forms;assembly=System.Windows.Forms"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <Grid>
        <WindowsFormsHost Width="300" Height="80" >
            <wf:TextBox  Text="WinForm TextBox" BackColor="255,192,192,192" />
        </WindowsFormsHost>
        <local:WpfElementHost Width="200" Height="100">
            <TextBox Opacity="0.6" Background="RoyalBlue" Foreground="White" FontSize="24" Text="WPF TextBox" ></TextBox>
        </local:WpfElementHost>
    </Grid>
</Window>

效果预览
在这里插入图片描述


总结

以上就是今天要讲的内容,整体的代码实现是比较简单的,关键是在win32 api设置窗口属性。这个功能的作用还是不小的,比如在嵌入网页上显示wpf控件,或者hwnd播放控件上放一些按钮。这种实现方式也不会有性能问题,绘制都是以窗口为单位的,其实和WinForm有点类似了,每个控件都是一个窗口。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/494030.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Flutter 常用插件Plugin整理并附带实例

最近有点空闲时间&#xff0c;正好写一篇文章&#xff0c;整理一下我们在Flutter开发中常用的插件Plugin使用并附带上实例。 在日常开发中&#xff0c;整个demo目前应该满足大家所有的开发需求&#xff0c;例如&#xff1a;http请求、列表刷新及加载、列表分组、轮播图、视频播…

ASP.Net添加Swagger注释

文章目录 Swagger添加Swagger注释 Swagger 添加Swagger注释 1、右击项目->选择属性->点击生成->输出&#xff0c;选中文档文件 2、配置服务 在program.cs 文件里配置SwaggerUI //增加项一 builder.Services.AddSwaggerGen(c> {c.SwaggerDoc("v1", ne…

新能源汽车充电桩主板的常见故障及解决办法

电桩主板作为充电桩的核心组件&#xff0c;直接影响着充电桩运行的安全性与稳定性。然而&#xff0c;在使用过程中&#xff0c;充电桩主板会因多种原因而出现一些故障情况&#xff0c;了解这些原因并采取相应的应对方法对维护充电桩的正常运行起着至关重要的作用。接下来&#…

【自我提升】一、Hyperledger Fabric 概念梳理

写在前面&#xff1a;最近因为业务需要&#xff0c;开始学习Hyperledger Fabric了&#xff0c;做java全栈工程师可真难搞。现在算是啥类型的都在涉及了&#xff0c;现在这个技术啥都不懂&#xff0c;就先开个学习专栏&#xff0c;记录记录。顺带也给各位道友参考参考。 目录 …

文献阅读工具-->Adobe pdf + 有道词典

Adobe pdf 有道词典 最近一直在考虑用什么文献阅读工具&#xff0c;痛点无非就是想用翻译功能&#xff0c;Adobe pdf的添加注释已经很好用了&#xff0c;使用了zotero&#xff0c;感觉不行&#xff08;不能直接对原文件修改&#xff0c;有副本&#xff0c;麻烦&#xff09;。…

vue + LogicFlow 实现流程图展示

vue LogicFlow 实现流程图展示 1.背景 部门主要负责低代码平台&#xff0c;配置端负责配置流程图&#xff0c;引擎端负责流程执行&#xff0c;原引擎端只负责流程执行控制以及流程历史列表展示。现在提出个新的要求&#xff0c;认为仅历史记录不直观&#xff0c;需要在展示完…

Unity学习日记 11.单词识别游戏

目录 1.返回鼠标单击对象的名字 2.鼠标拖动移动对象 3.实现鼠标跟随 4.场景准备工作 5.判断图片与框配对 6.根据配对结果放置图片 1.返回鼠标单击对象的名字 步骤&#xff1a; 创建一个ShowName的脚本&#xff0c;并挂载在摄像机上 RaycastHit2D hitInfo;void Update(){…

Tensorflow2.0笔记 - 使用compile,fit,evaluate,predict简化流程

本笔记主要用compile, fit, evalutate和predict来简化整体代码&#xff0c;使用这些高层API可以减少很多重复代码。具体内容请自行百度&#xff0c;本笔记基于FashionMnist的训练笔记&#xff0c;原始笔记如下&#xff1a; Tensorflow2.0笔记 - FashionMnist数据集训练-CSDN博…

【旅游景点项目日记 | 第一篇】项目服务架构、数据库表设计

Gitee仓库地址&#xff1a;travel-server&#xff1a;景点旅游项目服务端 文章目录 1.项目服务架构2.数据库设计2.1用户服务—travel_ums2.1.1 ums_user—用户表 2.2景点服务—travel_ams2.2.1 ams_attraction—景点表1.2.2 ams_resource_type—资源类型表 2.3票务服务—trabel…

前端框架的简单介绍

html html-结构 盖房子之前先划三室二厅 &#xff08;超文本标记语言&#xff09;(可以实现一切的文本) css css-样式 在房里添家具 &#xff08;层叠样式单&#xff09;(化妆在脸上叠加) javascript(js) javascript(js)-交互(行为) 我点击你打开 供显示信息的元…

持续集成与版本控制的相关概念

目录 一、持续集成 1.1 持续集成基本概念 1.1.1 持续集成的含义 1.1.1.1 持续集成流程是依赖产品版本迭代和版本分支而产生的 1.1.1.2 持续集成流程中包含的内容 1.1.2 传统打包模式说明 1.1.2.1 传统打包模式概述 1.1.2.2 传统打包模式问题 1.1.3 持续集成模式 1.1.…

GIt的原理和使用(五)

目录 多人协作 多人协作一 准备工作 协作开发 多人协作二 准备工作 额外场景 申请单合并分支 更推荐写法 远程分支删除后&#xff0c;本地git branch -a依然能看到的解决办法 多人协作 多人协作一 目标&#xff1a;在远程master分支下的file.txt文件新增代码“aaa”…

Adobe推出20多个,企业版生成式AI定制、微调服务

3月27日&#xff0c;全球多媒体领导者Adobe在拉斯维加斯召开“Summit 2024”大会&#xff0c;重磅推出了Firefly Services。 Firefly Services提供了20 多个生成式AI和创意API服务&#xff0c;支持企业自有数据对模型进行定制、微调&#xff0c;同时可以与PS、Illustrator、Ex…

压测k8s服务资源不足怎么处理

副本 在Kubernetes&#xff08;简称K8s&#xff09;中&#xff0c;Pod是最小的调度单元&#xff0c;而Pod的副本则是指同一个Pod的多个实例。在实际应用中&#xff0c;经常需要创建多个Pod的副本来增加应用的容错性和可伸缩性。 k8s的pod副本的负载均衡 Kubernetes中的Pod副本…

区块链食品溯源案例实现(二)

引言 随着前端界面的完成&#xff0c;我们接下来需要编写后端代码来与区块链网络进行交互。后端将负责处理前端发送的请求&#xff0c;调用智能合约的方法获取食品溯源信息&#xff0c;并将结果返回给前端。 通过前后端的整合&#xff0c;我们可以构建一个食品溯源系统&#xf…

Tensorflow CUPTI could not be loaded 解决

使用conda在指定环境安装cudatoolkit和cudnn后出现 CUPTI could not be loaded问题 conda install cudatoolkit11.0.3 conda install cudnn8.0.5.39 将本机C:\Program Files\NVIDIA Corporation\Nsight Systems xxxx\target-windows-x64 包含cupti的文件均复制到 D:\xxx\cond…

mysql高阶之(视图)

目录 视图概念 视图概念 视图是基于一个或多个表的SQL查询结果的虚拟表。视图并不实际存储数据&#xff0c;而是保存了查询的定义。当你查询视图时&#xff0c;数据库引擎会按照视图的定义执行底层的SQL查询。 &#xff08;一&#xff09;视图作用 视图的主要作用时一张表或多…

如何用Flask中的Blueprints构建大型Web应用

本文分享自华为云社区《构建大型Web应用Flask中的Blueprints指南》&#xff0c;作者&#xff1a; 柠檬味拥抱。 什么是Blueprints&#xff1f; 什么是Blueprints&#xff1f; Blueprints是Flask中的一种模式&#xff0c;用于将应用程序分解为可重用的模块。每个蓝图实际上是…

AES加密解密算法

一&#xff0c;AES算法概述 AES属于分组加密&#xff0c;算法明文长度固定为128位&#xff08;单位是比特bit&#xff0c;1bit就是1位&#xff0c;128位等于16字节&#xff09; 而密钥长度可以是128、192、256位 当密钥为128位时&#xff0c;需要循环10轮完成加密&#xff0…

鸿蒙雄起!风口就在当下,你如何抉择?

近年来&#xff0c;华为自主研发的鸿蒙操作系统&#xff08;HarmonyOS&#xff09;引起了广泛的关注和讨论。鸿蒙系统不仅标志着华为在软件领域的一次重大突破&#xff0c;也预示着全球智能设备市场格局的潜在变化。本文将深入探讨鸿蒙系统的兴起、其在市场上的表现以及对程序员…