news 2026/3/14 4:08:18

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/3/13 8:35:00

通俗解释各类消费电子设备上USB接口有几种

一文搞懂USB接口&#xff1a;别再被“Type-C”“快充”忽悠了&#xff01; 你有没有过这样的经历&#xff1f;买根数据线&#xff0c;包装上写着“支持快充、全速传输”&#xff0c;结果给手机充电半天没反应&#xff0c;传个电影比蜗牛还慢。回头一看&#xff0c;线材插头明明…

作者头像 李华
网站建设 2026/3/11 16:18:33

原神圣遗物自动导出革命:智能化管理新体验

原神圣遗物自动导出革命&#xff1a;智能化管理新体验 【免费下载链接】cocogoat-client A toolbox for Genshin Impact to export artifacts automatically. 支持圣遗物全自动导出的原神工具箱&#xff0c;保证每一行代码都是熬夜加班打造。 项目地址: https://gitcode.com/…

作者头像 李华
网站建设 2026/3/12 21:16:16

数字货币行情:加密货币价格波动即时通知

数字货币行情&#xff1a;加密货币价格波动即时通知 在智能设备无处不在的今天&#xff0c;投资者对市场信息的响应速度要求越来越高。尤其是在比特币、以太坊等主流加密货币动辄日内涨跌超5%的剧烈行情中&#xff0c;错过一次关键波动可能意味着错失巨额收益或面临重大风险。…

作者头像 李华
网站建设 2026/3/13 3:40:08

B站缓存视频无损转换技术解析:m4s转MP4完整解决方案

B站缓存视频无损转换技术解析&#xff1a;m4s转MP4完整解决方案 【免费下载链接】m4s-converter 将bilibili缓存的m4s转成mp4(读PC端缓存目录) 项目地址: https://gitcode.com/gh_mirrors/m4/m4s-converter B站视频转换技术解决了m4s格式缓存文件的播放限制问题&#xf…

作者头像 李华
网站建设 2026/3/13 9:25:54

Honey Select 2终极配置手册:HF Patch深度应用指南

Honey Select 2终极配置手册&#xff1a;HF Patch深度应用指南 【免费下载链接】HS2-HF_Patch Automatically translate, uncensor and update HoneySelect2! 项目地址: https://gitcode.com/gh_mirrors/hs/HS2-HF_Patch 还在为Honey Select 2的模组兼容性问题头疼吗&am…

作者头像 李华
网站建设 2026/3/13 8:49:04

Calibre-Web豆瓣插件重构指南:全新配置方案与实战技巧

Calibre-Web豆瓣插件重构指南&#xff1a;全新配置方案与实战技巧 【免费下载链接】calibre-web-douban-api 新版calibre-web已经移除douban-api了&#xff0c;添加一个豆瓣api实现 项目地址: https://gitcode.com/gh_mirrors/ca/calibre-web-douban-api 还在为Calibre-…

作者头像 李华