WindowsFormsHost 元素的布局注意事项

本主题介绍 WindowsFormsHost 元素如何与 WPF 布局系统交互。

WPF 和 Windows 窗体支持在窗体或页面上调整和定位元素的不同但相似的逻辑。 在 WPF 中创建托管 Windows 窗体控件的混合用户界面 (UI) 时,WindowsFormsHost 元素集成了两种布局方案。

WPF 与 Windows 窗体之间的布局差异

WPF 使用与分辨率无关的布局。 所有 WPF 布局尺寸均使用与设备无关的像素指定。 设备独立像素大小为 96 英寸且与分辨率无关,因此无论是渲染到 72 dpi 的显示器还是渲染到 19,200 dpi 的打印机,你都可以获得类似的结果。

WPF 也基于动态布局。 这意味着 UI 元素根据其内容、其父布局容器和可用的屏幕大小在窗体或页面上自行排列。 动态布局通过在它们包含的字符串更改长度时自动调整 UI 元素的大小和位置来促进本地化。

Windows 窗体中的布局依赖于设备并且更有可能是静态的。 通常,Windows 窗体控件使用以硬件像素指定的尺寸绝对定位在窗体上。 但是,Windows 窗体确实支持一些动态布局功能,如下表所述。

布局功能 说明
自动调整大小 某些 Windows 窗体控件会调整自身大小以正确显示其内容。 有关详细信息,请参阅 AutoSize 属性概述
定位和停靠 Windows 窗体控件支持基于父容器的定位和大小调整。 有关详细信息,请参阅 Control.AnchorControl.Dock
自动缩放 容器控件根据输出设备的分辨率或默认容器字体的大小(以像素为单位)调整自身及其子项的大小。 有关详细信息,请参阅 Windows 窗体中的自动缩放
布局容器 FlowLayoutPanelTableLayoutPanel 控件根据其内容排列其子控件并调整大小。

布局限制

通常,Windows 窗体控件无法在 WPF 中做到最大程度的缩放和转换。 下面列出了当 WindowsFormsHost 元素尝试将其承载的 Windows 窗体控件集成到 WPF 布局系统时的已知限制。

  • 某些情况下,不能调整 Windows 窗体控件的大小,或者大小只能调整为特定尺寸。 例如,Windows 窗体 ComboBox 控件仅支持由控件的字号定义的单一高度。 在 WPF 动态布局中,如果元素可以垂直拉伸,则托管的 ComboBox 控件不会按预期拉伸。

  • 不能旋转或倾斜 Windows 窗体控件。 如果应用倾斜或旋转转换,WindowsFormsHost 元素将引发 LayoutError 事件。 如果不处理 LayoutError 事件,将引发一个 InvalidOperationException 事件。

  • 大多数情况下,Windows 窗体控件不支持按比例缩放。 尽管该控件的整体尺寸将会缩放,但其子控件和组件元素可能不会按预期调整大小。 此限制取决于每个 Windows 窗体控件支持缩放的程度。 此外,不能将 Windows 窗体控件缩放到 0 像素的大小。

  • Windows 窗体控件支持自动缩放,在这种情况下,窗体将根据字号自动调整自身及其控件的大小。 在 WPF 用户界面中,更改字号不会改变整个布局的大小,但是可动态调整单个元素的大小。

Z 顺序

在 WPF 用户界面中,可以更改元素的 z 顺序以控制重叠行为。 由于承载的 Windows 窗体控件是在单独的 HWND 中绘制的,所以始终在 WPF 元素之上绘制它。

托管 Windows 窗体控件也可在任何 Adorner 元素之上进行绘制。

布局行为

以下部分描述了在 WPF 中托管 Windows 窗体控件时布局行为的特定方面。

缩放、单位转换和设备独立

每当 WindowsFormsHost 元素执行涉及 WPF 和 Windows 窗体尺寸的操作时,都会涉及两个坐标系:WPF 的设备独立像素和 Windows 窗体的硬件像素。 因此,必须应用适当的单位和缩放转换才能实现一致的布局。

坐标系之间的转换取决于当前设备分辨率以及应用于 WindowsFormsHost 元素或其上级的任何布局或呈现转换。

如果输出设备为 96 dpi 且未将缩放应用于 WindowsFormsHost 元素,则一个设备独立像素等于一个硬件像素。

所有其他情况都需要坐标系缩放。 不调整托管控件的大小。 相反,WindowsFormsHost 元素会尝试缩放托管控件及其所有子控件。 由于 Windows 窗体只是部分支持缩放,因此 WindowsFormsHost 元素只能缩放到特定控件支持的程度。

替代 ScaleChild 方法以提供托管 Windows 窗体控件的自定义缩放行为。

除缩放之外,WindowsFormsHost 元素还处理舍入和溢出情况,如下表所述。

转换问题 说明
舍入 WPF 设备独立像素尺寸指定为 double,Windows 窗体硬件像素尺寸指定为 int。 如果基于 double 的尺寸转换为基于 int 的尺寸,则 WindowsFormsHost 元素会使用标准舍入,因此小于 0.5 的小数值会向下舍入为 0。
溢出 WindowsFormsHost 元素从 double 值转换为 int 值时,可能会发生溢出。 大于 MaxValue 的值设置为 MaxValue

控制 Windows 窗体控件和 WPF 元素中的布局行为的属性由 WindowsFormsHost 元素适当地映射。 有关详细信息,请参阅 Windows 窗体和 WPF 属性映射

托管控件中的布局更改

托管 Windows 窗体控件中的布局更改将传播到 WPF 以触发布局更新。 WindowsFormsHost 上的 InvalidateMeasure 方法确保托管控件中的布局更改促使 WPF 布局引擎运行。

连续调整大小的 Windows 窗体控件

支持连续缩放的 Windows 窗体控件与 WPF 布局系统完全交互。 WindowsFormsHost 元素像照常使用 MeasureOverrideArrangeOverride 方法来调整和排列托管的 Windows 窗体控件。

大小调整算法

WindowsFormsHost 元素使用以下过程调整托管控件的大小:

  1. WindowsFormsHost 元素替代 MeasureOverrideArrangeOverride 方法。

  2. 为了确定托管控件的大小,MeasureOverride 方法调用托管控件的 GetPreferredSize 方法,其中包含从传递给 MeasureOverride 方法的约束转换而来的约束。

  3. ArrangeOverride 方法尝试将托管控件设置为给定大小约束。

  4. 如果托管控件的 Size 属性与指定的约束匹配,则托管控件的大小就是约束大小。

如果 Size 属性与指定的约束不匹配,则托管控件不支持连续大小调整。 例如,MonthCalendar 控件仅允许离散大小。 此控件的允许大小由高度和宽度的整数(表示月数)组成。 在这种情况下,WindowsFormsHost 元素的行为如下所示:

  • 如果 Size 属性返回的大小大于指定的约束,则 WindowsFormsHost 元素会剪切托管控件。 高度和宽度是分开处理的,因此可以从任意方向剪裁托管控件。

  • 如果 Size 属性返回的大小小于指定的约束,则 WindowsFormsHost 接受此大小值并将该值返回给 WPF 布局系统。

另请参阅