在不失去先前应用程序/窗口的焦点的情况下激活WPF窗口

5

我在应用程序中有一个WPF窗口,在某些特定的情况下通过调用MainView.Activate();MainView.BringIntoView();方法来激活它。它还将焦点设置在这个'MainView'窗口上。

但我的要求是这个窗口不应该获得焦点。也就是说,我的光标应该仍然停留在之前的应用程序(如记事本、Word等)上。

我尝试使用MainView.ShowActivated="False",但它没有起作用。 我需要像这里提到的那样使用HwndSource吗?

在Kent的帮助下我使用的代码(只有当窗口被最小化时才起作用):

IntPtr HWND_TOPMOST = new IntPtr(-1);
            const short SWP_NOMOVE = 0X2;
            const short SWP_NOSIZE = 1;
            const short SWP_NOZORDER = 0X4;
            const int SWP_SHOWWINDOW = 0x0040;

            Process[] processes = Process.GetProcesses(".");

            foreach (var process in processes)
            {
                IntPtr handle = process.MainWindowHandle;
                if (handle != IntPtr.Zero)
                {
                    SetWindowPos(handle, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOZORDER | SWP_NOSIZE | SWP_SHOWWINDOW);
                }
            }
4个回答

7
我有一个Win32助手类,可以应对这种情况。以下是您的示例代码清单。
using System;
using System.Runtime.InteropServices;
using System.Windows;
using System.Windows.Interop;

namespace your.namespace {
    public static class Win32 {
        public static void ShowWindowNoActive( Window window) {
            var hwnd = (HwndSource.FromVisual(window) as HwndSource).Handle;
            ShowWindow(hwnd, ShowWindowCommands.SW_SHOWNOACTIVATE);
        }

        [DllImport("user32.dll")]
        private static extern bool ShowWindow(IntPtr hWnd, ShowWindowCommands nCmdShow);

        private enum ShowWindowCommands : int {
            SW_SHOWNOACTIVATE = 4
        }
    }
}

6

我们把你想要显示但不需要焦点的窗口称为:YourWindow。添加以下代码:

YourWindow.ShowActivated = false;

YourWindow.Owner = 仍将拥有焦点的另一个窗口;

第一行也可以在XAML中设置。


XAML上的ShowActivated属性运行良好。我写这篇文章是因为Eli消息中的名称有一个拼写错误,我的窗口是通知窗口,不属于当前活动窗口,并且该属性仍然可以正常工作。如果设置为true,不会从当前活动窗口中移除焦点。 - Sabrina_cs

5
在我的最近的博客文章中,我使用SetWindowPos将一个窗口置于z顺序的前面,而不让它获得焦点。我认为WPF没有内置的方法来实现同样的功能,除非使用p/invoke。

谢谢,肯特。但是这只在我的窗口最小化时有效,如果窗口处于WindowState.Normal状态并且被某些应用程序(如IE等)隐藏,则无效。 - deathrace
2
博客链接已损坏。 - Nick
2
@KentBoogaart,链接又挂了。 - Boumbles
@Boumbles,更新了链接...显然,尾随斜杠是唯一的问题 :O - Jono

1
我曾经需要解决类似的问题,通过设置Window.ShowActivate=false并使用Window.Show而不是Window.Activate来解决了它。也许这对你有用。因为我的窗口是新创建的,并且默认情况下出现在其他窗口的顶部,所以我还没有需要使用BringIntoView。

Pinvoke(使用“ShowNoActivate”参数的ShowWindow)对我无效。 对我来说,这是一个更好的答案,“Window.Show”简单明了。 - antonio

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接