如果“浮动”文档处于活动状态,并且选择了某些菜单(例如“编辑” – >“粘贴”),则“浮动”文档仍具有“对焦”,并且将针对“浮动”窗口执行命令.此外,请注意在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>
这是关于这个问题的信息,听起来像你的情况:
他们对新的“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”事件.
>在这些事件中,检测应用程序是否具有应该是事件目标的“其他窗口”.
>对“其他窗口”手动调用原始命令.
希望对你有效.如果没有,让我知道.