繁体   English   中英

禁用 WPF 窗口焦点

[英]Disable WPF Window Focus

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

在别处找到答案:

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);

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

您可以通过添加自定义 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;

参考:

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

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

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

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

    InitializeComponent();
}

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

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

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

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

    base.Owner.Activate();
}

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

暂无
暂无

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

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