我有一个WPF窗口,只有在按住Tab键时通过Visibility.Hidden和Visibility.Visible才会显示出来。然而,按住键会将焦点从活动应用程序转移到WPF窗口。我能否禁用此行为?更进一步:即使单击控件,仍然可以注册控件的单击操作,但是否可能完全防止窗口获得焦点?
我有一个WPF窗口,只有在按住Tab键时通过Visibility.Hidden和Visibility.Visible才会显示出来。然而,按住键会将焦点从活动应用程序转移到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);
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();
}