wpf – 可停放的Windows.浮动窗口和MainWindow菜单集成

前端之家收集整理的这篇文章主要介绍了wpf – 可停放的Windows.浮动窗口和MainWindow菜单集成前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
在Visual Studio 2010中,可停靠的 Windows似乎在每种情况下都像预期的那样工作.
如果“浮动”文档处于活动状态,并且选择了某些菜单(例如“编辑” – >“粘贴”),则“浮动”文档仍具有“对焦”,并且将针对“浮动”窗口执行命令.此外,请注意在UI中如何清晰地显示. MainWindow.xaml仍然处于活动状态,即使选择了Team菜单,Visual Studio中的Main窗口也处于非活动状态.

我一直在尝试使用许多不同的第三方对接组件获得相同的行为,但它们都有同样的问题:一旦我选择了菜单,MainWindow就会被重点关注,我的浮动窗口不再有焦点了.有没有人知道在Visual Studio中如何获得相同的行为?

目前我正在使用Infragistics xamDockManager,问题可以用以下示例代码进行复制.

>右键单击“标题1”并选择“浮动”
>点击“文件菜单
>注意MainWindow如何接收焦点.

的xmlns:igDock = “http://infragistics.com/DockManager”

<DockPanel LastChildFill="True">
    <Menu DockPanel.Dock="Top">
        <MenuItem Header="_File">
            <MenuItem Header="_New"/>
        </MenuItem>
    </Menu>
    <Grid>
        <igDock:XamDockManager x:Name="dockManager" Theme="Aero">
            <igDock:DocumentContentHost>
                <igDock:SplitPane>
                    <igDock:TabGroupPane>
                        <igDock:ContentPane Header="Header 1">
                            <TextBox Text="Some Text"/>
                        </igDock:ContentPane>
                        <igDock:ContentPane Header="Header 2">
                            <TextBox Text="Some Other Text"/>
                        </igDock:ContentPane>
                    </igDock:TabGroupPane>
                </igDock:SplitPane>
            </igDock:DocumentContentHost>
        </igDock:XamDockManager>
    </Grid>
</DockPanel>
视觉工作室团队有一些很好的信息,他们在WPF中进行VS时所学到的经验教训.他们遇到的一个问题是与焦点管理有关.因此,WPF 4有一些新功能可以帮助.

这是关于这个问题的信息,听起来像你的情况:

http://blogs.msdn.com/b/visualstudio/archive/2010/03/09/wpf-in-visual-studio-2010-part-3-focus-and-activation.aspx

他们对新的“HwndSource.DefaultAcquireHwndFocusInMenuMode”属性的讨论听起来和您正在运行的内容非常相似.

编辑

经过进一步调查,看起来Visual Studio可能正在钩住Windows消息循环并返回特定的值,使浮动窗口工作.

我不是一个win32程序员,但是当用户在非活动窗口中单击菜单时,窗口会在处理鼠标事件之前发送WM_MOUSEACTIVATE消息.这允许主窗口确定是否应该被激活.

在我未经修改的WPF测试应用程序中,非活动窗口返回MA_ACTIVATE.然而,VS返回MA_NOACTIVATE.文档表示这将告诉窗口不要在处理其他输入之前激活主窗口.我猜想,视觉工作室钩住Windows消息循环,并在用户单击菜单/工具栏时返回MA_NOACTIVATE.

我可以在一个简单的两个窗口WPF应用程序中添加这个代码到顶级窗口.

protected override void OnSourceInitialized(EventArgs e)
    {
        base.OnSourceInitialized(e);

        var hook = new HwndSourceHook(this.FilterMessage);
        var source2 = HwndSource.FromVisual(this) as HwndSource;
        source2.AddHook(hook);
    }

    private IntPtr FilterMessage(IntPtr hwnd,int msg,IntPtr wParam,IntPtr lParam,ref bool handled)
    {
        const int WM_MOUSEACTIVATE = 0x0021;
        const int MA_NOACTIVATE = 3;

        switch (msg)
        {
            case WM_MOUSEACTIVATE:
                handled = true;
                return new IntPtr(MA_NOACTIVATE);
        }
        return IntPtr.Zero;
    }

在您的情况下,您可能需要添加更多的逻辑,以便检查用户点击的内容,并根据是否拦截消息并返回MA_NOACTIVATE来确定.

编辑2

我附上了一个sample WPF application,显示了如何使用简单的WPF应用程序.这应该与对接工具包的浮动窗口几乎相同,但是我还没有测试这个具体的场景.

样品可在:http://blog.alner.net/downloads/floatingWindowTest.zip

该示例有代码注释来解释它是如何工作的.要查看它的操作,运行示例,点击“打开另一个窗口”按钮.这应该把焦点放在新窗口的文本框中.现在,单击主窗口的编辑菜单,使用“全选”命令.这些应该在另一个窗口上操作,而不必将“主窗口”放在前台.

您也可以点击“退出菜单项,看看如果需要,它仍然可以将命令路由到主窗口.

要点(激活/焦点):

>使用HwndSource.DefaultAcquireHwndFocusInMenuMode使菜单停止抓取焦点.
钩住消息循环,并在用户单击菜单时返回“MA_NOACTIVATE”.
>向菜单的PreviewGotKeyboardFocus添加事件处理程序,并将e.Handled设置为true,以使菜单不会尝试抓取焦点.

要点(命令):

挂钩主窗口的“CommandManager.PreviewCanExecute”和“CommandManager.PreviewExecuted”事件.
>在这些事件中,检测应用程序是否具有应该是事件目标的“其他窗口”.
>对“其他窗口”手动调用原始命令.

希望对你有效.如果没有,让我知道.

猜你在找的Windows相关文章