激活 WPF 窗口而不会失去对以前的应用程序/窗口的关注

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/14210344/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-13 06:56:44  来源:igfitidea点击:

Activate WPF Window without losing focus on previous application/window

wpfwindowfocus

提问by deathrace

I have a WPF window in application which I Activate on some specific scenarios by calling MainView.Activate();and MainView.BringIntoView();method. it also sets focus on this 'MainView' window.

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

But my requirement is this window should not get Focus. i.e. my cursor should still remain on previous application(notepad,word etc..)

但我的要求是这个窗口不应该获得焦点。即我的光标应该仍然保留在以前的应用程序(记事本、word 等)上

I tried using MainView.ShowActivated="False"but it didn't work. Do I need to use HwndSource as mentioned hereor what?

我尝试使用MainView.ShowActivated="False"但它没有用。我需要使用这里提到的 HwndSource还是什么?

Code I have used after Kent's help (Its working only if Window is minimized):

我在 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);
                }
            }

回答by Kent Boogaart

In my recent blog post, I use SetWindowPosto bring a window to the front of the z-order without giving it focus. I don't believe WPF has an in-built means of achieving the same without p/invoke.

在我最近的博客文章中,我习惯于SetWindowPos将一个窗口放在 z-order 的前面而不给它焦点。我认为 WPF 没有内置的方法可以在没有 p/invoke 的情况下实现相同的目标。

回答by Eli Dagan

Let call the window that you want to show without focus: YourWindow. Add the following code:

让我们调用您想要在没有焦点的情况下显示的窗口:YourWindow。添加以下代码:

YourWindow.ShowActivted = false;

YourWindow.Owner = TheOtherWindowThatWillStilHaveFocus;

YourWindow.ShowActivted = false;

YourWindow.Owner = TheOtherWindowThatWillStilHaveFocus;

First line you can also be set from Xaml.

也可以从 Xaml 设置第一行。

回答by Mikhail

I Have Win32 helper class for such situation here is listing for your case

我有针对这种情况的 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
        }
    }
}

回答by ngm

I needed to solve a similar problem and got it to work by setting Window.ShowActivate=false and then using Window.Show rather than Window.Activate. Perhaps this will work for you. I have not yet needed to use BringIntoView because my window is newly created and appears on top of other windows by default.

我需要解决一个类似的问题,并通过设置 Window.ShowActivate=false 然后使用 Window.Show 而不是 Window.Activate 来让它工作。也许这对你有用。我还不需要使用BringIntoView,因为我的窗口是新创建的,默认情况下显示在其他窗口的顶部。