news 2026/5/1 11:43:15

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/22 19:39:01

股票行情播报:每日开盘前推送关键数据语音

股票行情播报&#xff1a;每日开盘前推送关键数据语音 在金融信息瞬息万变的今天&#xff0c;投资者每天清晨最关心的问题往往是&#xff1a;“昨晚美股走势如何&#xff1f;”“A股集合竞价释放了什么信号&#xff1f;”“北向资金是流入还是撤离&#xff1f;”传统依赖人工撰…

作者头像 李华
网站建设 2026/5/1 9:06:59

告别迟到烦恼:钉钉自动打卡助手3分钟上手教程

告别迟到烦恼&#xff1a;钉钉自动打卡助手3分钟上手教程 【免费下载链接】AutoDingding 钉钉自动打卡 项目地址: https://gitcode.com/gh_mirrors/au/AutoDingding 还在为早上匆忙赶路却忘记打卡而烦恼吗&#xff1f;钉钉自动打卡助手正是为你量身打造的解决方案。这款…

作者头像 李华
网站建设 2026/5/1 5:46:43

喜马拉雅音频批量下载工具:高效保存VIP付费内容完整指南

还在为喜马拉雅VIP音频无法离线收听而烦恼&#xff1f;这款基于GoQt5技术架构的音频下载工具&#xff0c;为您提供完善的解决方案&#xff01;支持mp3和m4a格式批量下载&#xff0c;便捷获取付费专辑和VIP有声小说&#xff0c;让优质音频内容触手可及。&#x1f3b5; 【免费下载…

作者头像 李华
网站建设 2026/5/1 6:56:38

springboot+vue乡镇村委会居民村民信息办公管理系统

目录系统概述技术架构核心功能应用价值开发技术核心代码参考示例1.建立用户稀疏矩阵&#xff0c;用于用户相似度计算【相似度矩阵】2.计算目标用户与其他用户的相似度总结源码文档获取/同行可拿货,招校园代理 &#xff1a;文章底部获取博主联系方式&#xff01;系统概述 Sprin…

作者头像 李华
网站建设 2026/5/1 6:52:49

springboot+vue青少年编程课程在线考试系统

目录摘要开发技术核心代码参考示例1.建立用户稀疏矩阵&#xff0c;用于用户相似度计算【相似度矩阵】2.计算目标用户与其他用户的相似度总结源码文档获取/同行可拿货,招校园代理 &#xff1a;文章底部获取博主联系方式&#xff01;摘要 该系统基于SpringBoot和Vue.js技术栈&am…

作者头像 李华
网站建设 2026/5/1 8:02:14

B站缓存视频转换终极指南:从m4s到mp4的完整解决方案

还在为B站缓存视频无法在其他设备播放而烦恼吗&#xff1f;m4s-converter开源项目为您提供了一键式解决方案&#xff0c;让珍贵的视频内容重获新生。本指南将详细介绍如何使用这款高效工具&#xff0c;实现B站缓存视频的跨平台自由播放。 【免费下载链接】m4s-converter 将bili…

作者头像 李华