我有一个 WPF 窗口,仅当您通过 Visibility.Hidden 和 Visibility.Visible 按住 tab 键时才会显示。但是,按住该键会将焦点从活动应用程序转移到 WPF 窗口。我可以禁用此行为吗?更进一步:即使单击控件,是否可以完全防止窗口获得焦点,但仍注册控件的单击操作?
5 回答
在别处找到答案:
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;
参考:
- MSDN WM_MOUSEACTIVATE:https ://msdn.microsoft.com/en-us/library/windows/desktop/ms645612(v=vs.85).aspx
- 如何在 WPF 中处理 WndProc 消息:如何在 WPF 中处理 WndProc 消息?
- 通知窗口 - 防止窗口获得焦点:通知窗口 - 防止窗口获得焦点
防止某些顶级窗口在 WPF 中被激活:
我尝试了这里给出的 Win32 解决方案,但它对我不起作用。虽然它似乎确实阻止了窗口“激活”,但Focus
之后它仍处于不确定状态,不会恢复到您应用程序中另一个符合条件的窗口。相反,以下内容对我有用:
首先,确保所有非主窗口的Owner
属性都设置为 main 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)。