news 2026/4/18 11:23:45

WPF如何页面内嵌窗口

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
WPF如何页面内嵌窗口

简介

  • 什么是XAML

  • 什么是句柄(IntPtr)

  • HwndHost是什么

  • 什么是空域

什么是XAML

XAML 是 eXtensible Application Markup Language 的缩写,中文常称为可扩展应用程序标记语言。它是微软为 .NET 平台(特别是 WPF、UWP、WinUI、Xamarin.Forms/Maui 等)创建的一种声明式标记语言

什么是句柄(IntPtr)

句柄 是 Handle 的中文翻译,是 Windows 操作系统中一个极其重要的核心概念。你可以把它理解为操作系统资源的"身份证号"或"引用凭证",简单的理解你可以理解为每个窗口都是一个句柄,开发者不需要知道资源在内存中的具体位置,只需要通过句柄操作即可。

HwndHost是什么

HwndHost是 WPF 中用于托管 Win32 控件的基类。它本质上是一个 "窗口包装器",让传统的 Win32 控件能够在 WPF 应用程序中运行。

什么是空域

空域问题是 WPF 中嵌入 Win32 控件时的核心限制。简单说就是 "WPF 和 Win32 控件不能在同一区域共存"。用人话说就是目标控件与HwndHost在同一层级,用户控件位于HwndHost之上,理论上是控件会覆盖HwndHost,但是实际上不是,HwndHost会悬浮在控件之上,这种问题简称空域,造成这种问题的根本原因是技术实现不同。

  • WPF:使用 DirectX,支持 GPU 加速、矢量图形、透明度、3D 变换

  • Win32:使用 GDI/GDI+,基于像素、无硬件加速、不支持透明度

具体表现现象

  • 遮挡问题

<Grid> <!-- Win32 控件 --> <local:HwndHostControl Width="200" Height="200"/> <!-- 这个按钮会被挖掉一半! --> <Button Content="我在上面" Width="100" Height="30" Canvas.Left="150" Canvas.Top="150"/></Grid>
  • 透明无效

<Grid> <!-- 设置透明背景没用! --> <local:HwndHostControl Background="Transparent"> <!-- Win32 控件不支持 WPF 透明度 --> </local:HwndHostControl> <!-- 这个控件显示不出来 --> <Border Background="Red"/></Grid>

实现逻辑

  • 创建自定义控件,继承HwndHost,实现BuildWindowCore、DestroyWindowCore

public class HwndHostControl : HwndHost{ protected override HandleRef BuildWindowCore(HandleRef hwndParent) { throw new NotImplementedException(); } protected override void DestroyWindowCore(HandleRef hwnd) { throw new NotImplementedException(); }}
  • 创建Win32API控制句柄

[DllImport("user32.dll", CharSet = CharSet.Unicode, SetLastError = true)] private static extern IntPtr CreateWindowExW( uint dwExStyle, [MarshalAs(UnmanagedType.LPWStr)] string lpClassName, [MarshalAs(UnmanagedType.LPWStr)] string lpWindowName, uint dwStyle, int x, int y, int nWidth, int nHeight, IntPtr hWndParent, IntPtr hMenu, IntPtr hInstance, [MarshalAs(UnmanagedType.AsAny)] object pvParam); /// <summary> /// 设置窗口的父窗口(改变所有权与 Z 序关系)。返回旧父窗口句柄。 /// </summary> [DllImport("user32.dll", SetLastError = true)] private static extern IntPtr SetParent(IntPtr hWndChild, IntPtr hWndNewParent); /// <summary> /// 销毁窗口,释放系统资源。销毁后句柄变为无效。 /// </summary> [DllImport("user32.dll", SetLastError = true)] [return: MarshalAs(UnmanagedType.Bool)] private static extern bool DestroyWindow(IntPtr hwnd); /// <summary> /// 移动并调整窗口大小,可选是否重绘(bRepaint)。 /// </summary> [DllImport("user32.dll", SetLastError = true)] private static extern bool MoveWindow(IntPtr hWnd, int X, int Y, int nWidth, int nHeight, bool bRepaint);
  • 获取窗口句柄(本教程以记事本为例子)

Process.GetProcessesByName("notepad").First().MainWindowHandle
  • 创建子窗口句柄

var _parentHwnd = CreateWindowExW(0x00000020u, "static", null, 0x40000000u | 0x10000000u, 0, 0, 0, 0, hwndParent.Handle, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero);
  • 将获取的目标句柄填充到子窗口句柄上

SetParent(_childHwnd, _parentHwnd);
  • 动态绘制句柄窗口大小

protected override void OnRender(DrawingContext drawingContext){ base.OnRender(drawingContext); UpdateWindowPos(); MoveWindow(_childHwnd, 0, (int)(0), (int)ActualWidth, (int)ActualHeight, true);}
  • 释放句柄

protected override void DestroyWindowCore(HandleRef hwnd) { DestroyWindow(hwnd.Handle); }

效果图

注意

本文章目的是给初步了解学习WPF相关人员参考,并未涉及到非常底层的句柄以及内存相关的原理讲解,为快速集成窗体项目做准备。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/18 3:48:27

AMD Infinity Fabric互连技术全面讲解

AMD Infinity Fabric&#xff1a;如何用“芯片乐高”重塑高性能计算的底层逻辑 你有没有想过&#xff0c;为什么今天的服务器CPU能轻松做到96核、128线程&#xff0c;而性能不崩、延迟可控&#xff1f;更关键的是&#xff0c;这些庞然大物居然还能塞进主流主板和通用数据中心机…

作者头像 李华
网站建设 2026/4/18 3:46:34

Windows系统快速访问Linux RAID磁盘阵列的终极方案

Windows系统快速访问Linux RAID磁盘阵列的终极方案 【免费下载链接】winmd WinMD 项目地址: https://gitcode.com/gh_mirrors/wi/winmd 在当今跨平台数据管理日益重要的时代&#xff0c;Windows用户经常面临无法直接读取Linux mdadm创建的RAID磁盘阵列的困扰。现在&…

作者头像 李华
网站建设 2026/4/18 3:47:34

Tsukimi终极指南:打造你的专属Emby媒体中心

你是否厌倦了传统媒体客户端的卡顿和复杂操作&#xff1f;是否渴望一个既能流畅播放高清视频&#xff0c;又能优雅管理音乐库的全能工具&#xff1f;今天我要向你介绍Tsukimi——这款基于Rust语言开发的第三方Emby客户端&#xff0c;将彻底改变你的媒体娱乐体验。 【免费下载链…

作者头像 李华
网站建设 2026/4/15 12:19:14

Jasminum:革命性Zotero中文文献管理插件,告别手动整理的烦恼

还在为繁琐的中文文献整理工作而头疼吗&#xff1f;Jasminum插件为Zotero用户带来突破性的智能化体验&#xff01;这款专为中文文献场景优化的插件&#xff0c;通过自动化技术彻底改变了传统的文献管理方式&#xff0c;让学术写作效率实现质的飞跃。 【免费下载链接】jasminum …

作者头像 李华
网站建设 2026/4/18 5:28:18

OpenCore Configurator 终极使用指南:5步掌握黑苹果配置技巧

OpenCore Configurator 终极使用指南&#xff1a;5步掌握黑苹果配置技巧 【免费下载链接】OpenCore-Configurator A configurator for the OpenCore Bootloader 项目地址: https://gitcode.com/gh_mirrors/op/OpenCore-Configurator OpenCore Configurator&#xff08;简…

作者头像 李华
网站建设 2026/4/17 17:49:52

番茄小说批量下载器:5种格式随心转换的终极解决方案

番茄小说批量下载器&#xff1a;5种格式随心转换的终极解决方案 【免费下载链接】fanqienovel-downloader 下载番茄小说 项目地址: https://gitcode.com/gh_mirrors/fa/fanqienovel-downloader 想要随时随地畅读番茄小说&#xff0c;却苦于网络限制&#xff1f;番茄小说…

作者头像 李华