System.InvalidOperationException:“寄宿 HWND 必须是子窗口。”
原文:System.InvalidOperationException:“寄宿 HWND 必须是子窗口。”
当试图在 WPF 窗口中嵌套显示 Win32 子窗口的时候,你有可能出现错误:“System.InvalidOperationException:“寄宿 HWND 必须是子窗口。””。
这是很典型的 Win32 错误,本文介绍如何修复此错误。
一个最简的嵌入其他窗口的例子
我们在 MainWindow 中嵌入一个其他的窗口来承载新的 WPF 控件。一般情况下我们当然不会这么去做,但是如果我们要跨越进程边界来完成 WPF 渲染内容的融合的时候,就需要嵌入一个新的窗口了。
WPF 中可以使用 HwndSource 来包装一个 WPF 控件到 Win32 窗口,使用自定义的继承自 HwndHost 的类可以把 Win32 窗口包装成 WPF 控件。由于窗口句柄是可以跨越进程边界传递的,所以这样的方式可以完成跨进程的 WPF 控件显示。
下面是最简单的一个例子,为了简单,没有跨进程传递 Win32 窗口句柄,而是直接创建出来。
using System.Runtime.InteropServices;
using System.Windows;
using System.Windows.Interop;
namespace Walterlv.Demo.HwndWrapping
{
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
Loaded += OnLoaded;
}
private void OnLoaded(object sender, RoutedEventArgs e)
{
Content = new HwndWrapper();
}
}
public class HwndWrapper : HwndHost
{
private HwndSource _source;
protected override HandleRef BuildWindowCore(HandleRef hwndParent)
{
var parameters = new HwndSourceParameters("walterlv");
_source = new HwndSource(parameters);
// 这里的 ChildPage 是一个继承自 UseControl 的 WPF 控件,你可以自己创建自己的 WPF 控件。
_source.RootVisual = new ChildPage();
return new HandleRef(this, _source.Handle);
}
protected override void DestroyWindowCore(HandleRef hwnd)
{
_source?.Dispose();
}
}
}
- 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
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
寄宿 HWND 必须是子窗口
当运行此代码的时候,会提示错误:
System.InvalidOperationException:“寄宿 HWND 必须是子窗口。”
或者英文版:
System.InvalidOperationException:“Hosted HWND must be a child window.”
这是一个 Win32 错误,因为我们试图将一个普通的窗口嵌入到另一个窗口中,而实际上要完成嵌入需要子窗口才行。
那么如何设置一个 Win32 窗口为子窗口呢?使用 SetWindowLong 来设置 Win32 窗口的样式是可以的。不过我们因为使用了 HwndSource,所以可以通过 HwndSourceParameters 来更方便地设置窗口样式。
我们需要将 HwndSourceParameters 那一行改成这样:
++ const int WS_CHILD = 0x40000000;
-- var parameters = new HwndSourceParameters("walterlv");
++ var parameters = new HwndSourceParameters("walterlv")
++ {
++ ParentWindow = hwndParent.Handle,
++ WindowStyle = WS_CHILD,
++ };
- 1
- 2
- 3
- 4
- 5
- 6
- 7
最关键的是两点:
- 需要设置此窗口为子窗口,也就是设置
WindowStyle为WS_CHILD; - 需要设置此窗口的父窗口,也就是设置
ParentWindow为hwndParent.Handle(我们使用参数中传入的hwndParent作为父窗口)。
现在再运行,即可正常显示此嵌套窗口:
另外,WindowStyle 属性最好加上 WS_CLIPCHILDREN,详情请阅读:
参考资料
我的博客会首发于 https://blog.walterlv.com/,而 CSDN 会从其中精选发布,但是一旦发布了就很少更新。
如果在博客看到有任何不懂的内容,欢迎交流。我搭建了 dotnet 职业技术学院 欢迎大家加入。

本作品采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可。欢迎转载、使用、重新发布,但务必保留文章署名吕毅(包含链接:https://walterlv.blog.csdn.net/),不得用于商业目的,基于本文修改后的作品务必以相同的许可发布。如有任何疑问,请与我联系。
System.InvalidOperationException:“寄宿 HWND 必须是子窗口。”的更多相关文章
- 零基础逆向工程29_Win32_03_ESP寻址_定位回调函数_子窗口_消息处理函数
1 Win32应用程序入口识别 思路:根据WinMain的四个参数,由调用顺序,知道最后压栈的是hInstance句柄(也就是WinMain函数的第一个参数,其值等于ImageBase),根据反汇编, ...
- C#在父窗口中调用子窗口的过程(无法访问已释放的对象)异常,不存在从对象类型System.Windows.Forms.DateTimePicker到已知的托管提供程序本机类型的映射。
一:C#在父窗口中调用子窗口的过程(无法访问已释放的对象)异常 其实,这个问题与C#的垃圾回收有关.垃圾回收器管 理所有的托管对象,所有需要托管数据的.NET语言(包括 C#)都受运行库的 垃圾回收器 ...
- windows窗口分析,父窗口,子窗口,所有者窗口
(本文尝试通过一些简单的实验,来分析Windows的窗口机制,并对微软的设计理由进行一定的猜测,需要读者具备C++.Windows编程及MFC经验,还得有一定动手能力.文中可能出现一些术语不统一的现象 ...
- WPF 不要给 Window 类设置变换矩阵(分析篇):System.InvalidOperationException: 转换不可逆。
原文:WPF 不要给 Window 类设置变换矩阵(分析篇):System.InvalidOperationException: 转换不可逆. 最近总是收到一个异常 "System.Inva ...
- 第十三篇:在SOUI中使用有窗口句柄的子窗口
前言: 无论一个DirectUI系统提供的DUI控件多么丰富,总会有些情况下用户需要在DUI窗口上放置有窗口句柄的子窗口. 为了和无窗口句柄的子窗口相区别,这里将有窗口句柄的子窗口称之为真窗口. 每一 ...
- ZK 父窗口与子窗口消息交互
父窗口代码: 前台(test.zul) <?page title="" contentType="text/html;charset=UTF-8"?> ...
- MFC子窗口和父窗口
转载声明: 本文转载自:http://www.cnblogs.com/BeyondTechnology/archive/2011/03/25/1995934.html 感谢BeyondTechnolo ...
- windows 编程 —— 子窗口类别化(Window Subclassing)
对于子窗口控件,有时我们可能会想要获取子窗口的某些消息,比如在一个主窗口下有三个按钮,如果想要实现使用键盘Tab或者Shift-Tab键来使焦点切换于不同按钮之间,这时就可以使用子窗口类别化(Wind ...
- windows 编程 —— 子窗口 与 子窗口控件
目录: 子窗口与主窗口的交互 子窗口控件 按钮类别 button 滚动条类别 scrollbar 静态类别 static 编辑框类别 edit 清单方块 listbox 子窗口与主窗口的交互 创建窗 ...
随机推荐
- R 语言输入输出 读取命令函参数
输入数据 使用键盘输入数据 只能处理小样本,很少使用 在创建 data.txt 字符串之后,用函数 read.table() 创建数据框 data.1.这种方法可以让我们把数据嵌入到R代码中,此处切记 ...
- Debian系Linux 发行版 源配置说明
概述: 本文是在逛论坛是的发现,借鉴过来,以便学习.源列表主文件 /etc/apt/sources.list同时也可创建独立的源配置文件到 /etc/apt/sources.list.d/* 下 so ...
- Spring Transaction 使用入门
一.开篇陈述 1.1 写文缘由 最近在系统学习spring框架IoC.AOP.Transaction相关的知识点,准备写三篇随笔记录学习过程中的感悟.这是第一篇,记录spring Transactio ...
- [Gamma阶段]第五次Scrum Meeting
Scrum Meeting博客目录 [Gamma阶段]第五次Scrum Meeting 基本信息 名称 时间 地点 时长 第五次Scrum Meeting 19/05/31 大运村寝室6楼 30min ...
- git rebase命令
使用git rebase合并多次commit. 当年提交代码后,管理员发现,你的代码不能提交到服务器上,注意原因在于,你的commit中的commit和服务器中的有些commit不在同一时间轴上,即: ...
- 运维笔记--Debian/Ubuntu系统离线安装pymssql,连接SqlServer
场景描述: 开始之前,先对Debian和Ubuntu操作系统做个了解,两者都是Linux阵营中很有影响力的发行版本,可以简单理解成“Ubuntu源自Debian,两者系统操作命令基本相同,相比Ubun ...
- 几个简单易用的IDEA快捷键
常见的几个Idea的代码快捷键 格式化代码: Ctrl + Alt + L Optimize Imports(优化包引用): Ctrl-Alt-O 单行注释(//): Ctrl-/ 块注释(/*... ...
- Consider defining a bean of type 'com.*.*.feign.*FeignClient' in your configuration.
Description: Field *FeignClient in com.*.*.service.* required a bean of type '***********' that coul ...
- python 使用 elasticsearch 常用方法(索引)
#记录管理索引等方法 from elasticsearch import Elasticsearch es = Elasticsearch(['xx.xx.xx.xx:9200']) #获取文档内容r ...
- ["Visual Studio快捷键" ,"Vs","IDEA快捷键"]
描述说明 描述 说明 ↑ 方向键.上 ↓ 方向键.下 ← 方向键.左 → 方向键.右 快捷键大比拼 描述 Visual Studio 快捷键 IDEA快捷键 VisualStudio学名 IDEA学名 ...
