简体   繁体   English

禁用 WPF 窗口焦点

[英]Disable WPF Window Focus

I have a WPF Window that shows up only when you hold down the tab key via Visibility.Hidden and Visibility.Visible.我有一个 WPF 窗口,只有当您通过 Visibility.Hidden 和 Visibility.Visible 按住 Tab 键时才会显示。 However, holding the key down shifts the focus from the active application to the WPF Window.但是,按住该键会将焦点从活动应用程序转移到 WPF 窗口。 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?更进一步:是否可以完全阻止窗口在单击控件时获得焦点,但仍然注册控件的单击动作?

Found the answer elsewhere:在别处找到答案:

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

    //Set the window style to noactivate.
    var 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);

Since .NET 3.5 SP1 WPF forms have a ShowActivated property.由于 .NET 3.5 SP1 WPF 表单具有 ShowActivated 属性。 Set this to false and the form thus marked won't steal no focus no more.将此设置为false ,这样标记的表单将不再窃取焦点。

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:参考:

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.我尝试了此处给出的 Win32 解决方案,但对我不起作用。 While it does seem to prevent window "activation," the Focus is left in limbo afterwards, not restored to another eligible window in your application.虽然它似乎确实阻止了窗口“激活”,但之后Focus处于不确定状态,不会恢复到应用程序中的另一个符合条件的窗口。 Instead, the following worked for me:相反,以下对我有用:

First, make sure that all the non-primary windows have their Owner property set to the main Window .首先,确保所有非主窗口都将其Owner属性设置为主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 Window is loaded first.我在子窗口的构造函数中执行此操作,在这种情况下,必须采取一些步骤(此处未讨论)以确保首先加载主Window

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

    InitializeComponent();
}

Setting the Owner property should also ensure that the sub windows stay on top of the main window.设置Owner属性还应确保子窗口位于主窗口的顶部。 For the sub window(s), set the following properties as indicated (XAML or code):对于子窗口,按照指示设置以下属性(XAML 或代码):

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

Finally, add a handler for OnActivated to the blocked windows.最后,将OnActivated的处理程序添加到被阻止的窗口。 I don't call the base method since it fires the Activated event.我不调用基本方法,因为它会触发Activated事件。 (Note that you should not switch the activation away from the Visual Studio designer since it makes the window invisible). (请注意,您不应将激活从 Visual Studio 设计器切换开,因为它会使窗口不可见)。

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

    base.Owner.Activate();
}

Maybe a PopupWindow instead of Window would be what you want?也许你想要一个 PopupWindow 而不是 Window ? It has a property of Focusable which you can set to false (it might be false by default I think).它有一个 Focusable 属性,您可以将其设置为 false(我认为默认情况下可能为 false)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM