如何在窗口外显示WPF上下文菜单?

时间:2014-02-02 11:57:09

标签: wpf windows

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

那么,那些菜单的哪一部分可以显示在外面父窗口? 为什么他们一到达窗口边界就不会被切断?

当然,一种可能性是它们不是真正的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>

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

Menu gets clipped in a rectangle

那么,发生了什么?

3 个答案:

答案 0 :(得分:4)

如果你在网上搜索WPF上下文菜单,你会发现很多文章都说明 ContextMenu不属于与其父相同的Visual Tree。

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

ContextMenu只是一个Popup。如果您有兴趣查看负责处理的实际课程,System.Windows.Controls.Primitives.Popup课程中会出现PresentationFramework.dll课程。只要打开上下文菜单,就会调用方法CreateWindow

在关闭DestroyWindow方法中调用以销毁为托管ContextMenu内容而创建的popUp窗口。

因此,无论何时在包装下打开/关闭上下文菜单,都会创建并销毁一个窗口,该窗口显然不是主窗口的一部分,而是一个单独的窗口,它可以在主窗口边界之外。

答案 1 :(得分:3)

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

实际上,Popup实例会创建一个辅助Win32窗口,该窗口的目标是托管所需的WPF内容。实际上,Popup类利用了HwndSource互操作:

MSDN: HwndSource Class

这也很有用:

Win32 Handle (HWND) & WPF Objects

答案 2 :(得分:3)

  

但是,标准的Windows资源

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

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