65.9K
CodeProject 正在变化。 阅读更多。
Home

Win32句柄 (HWND) & WPF 对象 - 说明

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.80/5 (3投票s)

2010年12月5日

CPOL

3分钟阅读

viewsIcon

48457

Win32句柄 (HWND) & WPF 对象 - 说明

许多使用WPF对象的人常常会产生一个误解:WPF对象是否真正与Windows环境互操作?更准确地说,它的行为方式与普通的Win32对象是否相同?

问题在于,每个WPF窗口只有一个窗口句柄(`HWND`),而其他控件实际上作为窗口的内容放置,在内核表中没有条目(没有`HWND`),当然WPF中的`Popup`类除外。在这篇文章中,我将尝试介绍`HWND`的基础知识(对于那些不知道的人),然后介绍它在WPF环境中的变化。

如果您知道`HWND`是什么或它是如何工作的,请跳过下一节。

Win32句柄概述

Win32句柄对于任何Win32应用程序都非常重要。对于每个Win32应用程序,内核维护一个表,其中包含用于标识内存地址的条目。`HANDLE`实际上是一个`DWORD`(32位整数),它映射表中的内存地址。因此,如果您获得一个`HANDLE`,您可以轻松地找到它指向的内存地址。您在Windows中拥有的每个对象(如窗口、按钮、鼠标指针、图标、菜单、位图等)在表中都有条目,并且该对象通过Windows内部或使用这些`HANDLE`的程序进行跟踪。即使它只是一个无符号整数值,您也不应该编辑该值,否则`HANDLE`将无法再指向该对象。

基于`HANDLE`的类型,可以将其分为`HWND`、`HINSTANCE`、`HMENU`。

HWND

`HWND`是一个特殊的`HANDLE`,它指向一个窗口对象。`HWND`被称为指向窗口的指针。要获取任何窗口、其子窗口或对话框对象,我们需要使用`HWND`对象。两个窗口之间的通信也是使用`HWND`完成的。

HINSTANCE

`HINSTANCE`是一个特殊的`HANDLE`,它指向一个程序实例。内核保留对程序实例的`HANDLE`,以便以后可以从外部与该程序进行通信。

HMENU

对于每个下拉菜单,都会与之关联一个`HMENU`句柄。`HMENU`句柄用于更改下拉菜单项的内容。

WPF 对象和 HWND

WPF对象不是基于`HWND`的。那么它如何与窗口句柄通信呢?是的,这个问题会出现在每个在Windows环境中积累了相当多经验后开始使用WPF的程序员脑海中。

首先,操作系统如果没有对内核中`HWND`的引用,就无法渲染任何对象。WPF也是如此。因此,WPF窗口实际上保存对一个窗口句柄的引用。您甚至可以为WPF窗口内的任何Visual对象获取窗口句柄。

ListBox lst = new ListBox();
HwndSource source = (HwndSource)HwndSource.FromVisual(lst);
IntPtr hWnd = source.Handle;

所以这是获取任何视觉对象的`HWND`数据的一个非常基本的步骤。类似地,对于窗口,您可以使用以下方法获取窗口句柄:

WindowInteropHelper windowHwnd =new WindowInteropHelper(this); 
IntPtr hWnd = windowHwnd.Handle;

因此,基本上,`WindowInteropHelper`将为您提供外部窗口的`HANDLE`。

那么,这是否意味着每个WPF对象都与一个`HANDLE`相关联呢?实际上,情况与看起来的有所不同。WPF窗口由两部分组成。

  1. 窗口区域,由操作系统窗口组成
  2. 非窗口区域,位于WPF窗口内部

现在,WPF窗口作为一个`ContentControl`,将所有内容作为其内容。所以可以说,`Window`类内部内容的每个像素都由外部窗口持有。WPF的每个Visual对象都没有与其关联的自己的`HANDLE`,而它只是外部窗口元素的内容。要检查

ListBox lst = new ListBox();
HwndSource lstHwnd = HwndSource.FromVisual(lst) as HwndSource;
WindowInteropHelper windowHwnd =new WindowInteropHelper(this);

Debug.Assert(lstHwnd.Handle == windowHwnd.Handle);

断言输出`true`。因此可以说,每个WPF控件都由其父窗口拥有。

除了`popup`类之外,每个控件都是使用矢量图形绘制在屏幕上的,因此无论如何都不会对应于它自己的句柄。

感谢您的阅读。

© . All rights reserved.