禁用 WPF 窗口焦点

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/12591896/
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 05:32:52  来源:igfitidea点击:

Disable WPF Window Focus

c#wpffocus

提问by Lunyx

I have a WPF Window that shows up only when you hold down the tab key via Visibility.Hidden and Visibility.Visible. However, holding the key down shifts the focus from the active application to the WPF Window. Can I disable this behavior? Going even further: is it possible to completely prevent the window from getting focus even when a control is clicked, but still registering the click action of the control?

我有一个 WPF 窗口,只有当您通过 Visibility.Hidden 和 Visibility.Visible 按住 Tab 键时才会显示。但是,按住该键会将焦点从活动应用程序转移到 WPF 窗口。我可以禁用此行为吗?更进一步:是否可以完全阻止窗口在单击控件时获得焦点,但仍然注册控件的单击动作?

采纳答案by Lunyx

Found the answer elsewhere:

在别处找到答案:

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

        //Set the window style to noactivate.
        WindowInteropHelper helper = new WindowInteropHelper(this);
        SetWindowLong(helper.Handle, GWL_EXSTYLE,
            GetWindowLong(helper.Handle, GWL_EXSTYLE) | WS_EX_NOACTIVATE);
    }   

    private const int GWL_EXSTYLE = -20;
    private const int WS_EX_NOACTIVATE = 0x08000000;

    [DllImport("user32.dll")]
    public static extern IntPtr SetWindowLong(IntPtr hWnd, int nIndex, int dwNewLong);

    [DllImport("user32.dll")]
    public static extern int GetWindowLong(IntPtr hWnd, int nIndex);

回答by Erre Efe

Since .NET 3.5 SP1 WPF forms have a ShowActivated property. Set this to falseand the form thus marked won't steal no focus no more.

由于 .NET 3.5 SP1 WPF 表单具有 ShowActivated 属性。将此设置为false这样标记的表单将不再窃取焦点。

回答by MRoc

You can prevent a WPF Window from activating on mouse click by adding a custom WndProc and handling WM_MOUSEACTIVATE:

您可以通过添加自定义 WndProc 并处理 WM_MOUSEACTIVATE 来防止 WPF 窗口在鼠标单击时激活:

    protected override void OnSourceInitialized(EventArgs e)
    {
        base.OnSourceInitialized(e);
        var source = PresentationSource.FromVisual(this) as HwndSource;
        source.AddHook(WndProc);
    }
    private IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
    {
        if (msg == WM_MOUSEACTIVATE)
        {
            handled = true;
            return new IntPtr(MA_NOACTIVATE);
        }
        else
        {
            return IntPtr.Zero;
        }
    }
    private const int WM_MOUSEACTIVATE = 0x0021;
    private const int MA_NOACTIVATE = 0x0003;

References:

参考:

回答by Glenn Slayden

Prevent certain top-level windows from getting activated in WPF:

防止在 WPF 中激活某些顶级窗口

I tried the Win32 solution given here but it didn't work for me. While it does seem to prevent window "activation," the Focusis left in limbo afterwards, not restored to another eligible window in your application. Instead, the following worked for me:

我尝试了此处给出的 Win32 解决方案,但对我不起作用。虽然它似乎确实阻止了窗口“激活”,但Focus之后它仍处于不确定状态,不会恢复到应用程序中的另一个符合条件的窗口。相反,以下对我有用:

First, make sure that all the non-primary windows have their Ownerproperty set to the main Window. I do this in the constructor of the sub-window, in which case one must take some steps (not discussed here) to make sure that the main Windowis loaded first.

首先,确保所有非主窗口的Owner属性都设置为 main Window。我在子窗口的构造函数中执行此操作,在这种情况下,必须采取一些步骤(此处未讨论)以确保Window首先加载主窗口。

public MySubWindow()
{
    if ((base.Owner = Application.Current.MainWindow) == null)
        throw new Exception();

    InitializeComponent();
}

Setting the Ownerproperty should also ensure that the sub windows stay on top of the main window. For the sub window(s), set the following properties as indicated (XAML or code):

设置该Owner属性还应确保子窗口位于主窗口的顶部。对于子窗口,按照指示设置以下属性(XAML 或代码):

    ShowActivated="False"
    Focusable="False"
    ShowInTaskbar="False"
    IsEnabled="False"
    FocusManager.IsFocusScope="False"

Finally, add a handler for OnActivatedto the blocked windows. I don't call the base method since it fires the Activatedevent. (Note that you should not switch the activation away from the Visual Studio designer since it makes the window invisible).

最后,为OnActivated被阻止的窗口添加一个处理程序。我不调用基方法,因为它会触发Activated事件。(请注意,您不应将激活从 Visual Studio 设计器切换开,因为它会使窗口不可见)。

protected override void OnActivated(EventArgs e)
{
    if (DesignerProperties.GetIsInDesignMode(this))
        return;

    base.Owner.Activate();
}

回答by MikeKulls

Maybe a PopupWindow instead of Window would be what you want? It has a property of Focusable which you can set to false (it might be false by default I think).

也许你想要一个 PopupWindow 而不是 Window ?它有一个 Focusable 属性,您可以将其设置为 false(我认为默认情况下它可能为 false)。