【问题标题】:How is it possible that a WPF context menu is displayed outside the window?WPF 上下文菜单怎么可能显示在窗口外?
【发布时间】:2014-02-02 11:57:08
【问题描述】:

据我了解,与旧的 Windows 窗体应用程序不同,WPF 应用程序中的控件不绑定到系统“窗口”资源(例如,您无法使用 Spy++ 找到它们的句柄)。

那么,这些菜单的一部分怎么可能显示在在父窗口之外为什么不一到达窗口边框就剪掉?

当然,一种可能性是它们不是真正的 WPF 菜单,而是标准的 Windows 资源。然而,这与我可以像任何其他 WPF 控件一样设置其中一个菜单的样式这一事实相冲突,并且快速查看系统消息日志似乎可以确认,据 Windows 所知 它们实际上是,具有相同句柄的完全相同的资源

然后,我走得更远。我对菜单应用了旋转:

<Style TargetType="{x:Type ContextMenu}">
    <Setter Property="RenderTransformOrigin" Value="0.5,0.5" />
    <Setter Property="RenderTransform">
        <Setter.Value>
            <TransformGroup>
                <ScaleTransform/>
                <SkewTransform/>
                <RotateTransform Angle="-18.435"/>
                <TranslateTransform/>
            </TransformGroup>
        </Setter.Value>
    </Setter>
</Style>

这是一个相当有趣的结果:

那么,发生了什么事?

【问题讨论】:

  • 仅供参考:这也适用于展开时的组合框。

标签: wpf windows


【解决方案1】:

如果你在网上搜索 WPF 上下文菜单,你会发现很多文章说 ContextMenu 与其父级不属于同一可视树

它们不是实际窗口的一部分,它们托管在单独的窗口中。就像您可以在 WPF 中拥有多个窗口一样。 ContextMenu 和 Popup 也是如此。

ContextMenu 只是一个弹出窗口。如果您有兴趣查看负责处理它的实际类是PresentationFramework.dll 中的System.Windows.Controls.Primitives.Popup 类。每当打开上下文菜单时,都会调用方法 CreateWindow

然后在关闭时调用DestroyWindow 方法来销毁为托管 ContextMenu 内容而创建的弹出窗口。

因此,无论何时打开/关闭上下文菜单,都会创建和销毁一个窗口,该窗口显然不是主窗口的一部分,而是一个完全可以超出主窗口边界的单独窗口。

【讨论】:

    【解决方案2】:

    但是,标准的 Windows 资源

    这确实是一个标准的 Windows 窗口。就像你的主窗口一样。一个顶层窗口,可以任意重叠其他窗口。

    但是您可以看到后果,空域问题,无法旋转原生 Windows 窗口。它是一个基本的矩形,充其量只能被赋予一个形状。这可能是通过旋转矩形计算的形状,但 WPF 并没有那么远。只有 content 可以旋转。这在 WPF 中很容易做到,内容只是绘画层,而不是像 Winforms 中那样的本机窗口,因此旋转它只需要旋转变换。但是当然不能超出原生窗口的范围。

    【讨论】:

      【解决方案3】:

      Popup 对象是普通Window 之上的任何“浮动”上下文的基础,例如上下文菜单、下拉列表等。

      事实上,Popup 实例创建了一个辅助 Win32 窗口,该窗口旨在承载所需的 WPF 内容。事实上,Popup 类利用了 HwndSource 互操作:

      MSDN: HwndSource Class

      这也很有用:

      Win32 Handle (HWND) & WPF Objects

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多