Wpf 如何防止焦点窃取,但在使用Alt+返回应用程序时仍能获得焦点;账单?

Wpf 如何防止焦点窃取,但在使用Alt+返回应用程序时仍能获得焦点;账单?,wpf,Wpf,根据MS指南,我的WPF应用程序的应用程序构造函数包含以下代码以实现正确的焦点行为: HwndSource.DefaultAcquireHwndFocusInMenuMode = false; Keyboard.DefaultRestoreFocusMode = RestoreFocusMode.None; 如中所述,这些设置可防止焦点窃取 但是,将DefaultRestoreFocusMode设置为None会产生不良的副作用。当使用Alt+Tab离开WPF应用程序然后返回到它时,WPF应用程

根据MS指南,我的WPF应用程序的应用程序构造函数包含以下代码以实现正确的焦点行为:

HwndSource.DefaultAcquireHwndFocusInMenuMode = false;
Keyboard.DefaultRestoreFocusMode = RestoreFocusMode.None;
如中所述,这些设置可防止焦点窃取

但是,将DefaultRestoreFocusMode设置为None会产生不良的副作用。当使用Alt+Tab离开WPF应用程序然后返回到它时,WPF应用程序不会获得焦点。但是,如果我没有将DefaultRestoreFocusMode设置为none,它会像预期的那样获得焦点。有没有办法防止焦点窃取,但在通过Alt+Tab返回WPF应用程序时仍设置焦点


-Craig

我通过执行以下操作来防止我的wpf窗口获得焦点,我仍然可以通过使用ALT-TAB或单击任务栏项来激活它

在这里,您可以更改窗口上的窗口样式,使其不被激活

var yourWindow = new YourWindowType();
//set the windowstyle to noactivate so the window doesn't get focus
yourWindow.SourceInitialized += (s, e) =>
{
  var interopHelper = new WindowInteropHelper(yourWindow);
  int exStyle = User32.GetWindowLong(interopHelper.Handle, (int)WindowLongFlags.GWL_EXSTYLE);
  User32.SetWindowLong(interopHelper.Handle, (int)WindowLongFlags.GWL_EXSTYLE, exStyle | (int)WindowStylesEx.WS_EX_NOACTIVATE);

  //If you have trouble typing into your form's textboxes then do this
  ElementHost.EnableModelessKeyboardInterop(yourWindow);
};
这是我作为额外预防措施添加的内容,另外,如果窗口无边界,还可以让您拖动窗口:

private IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
{
  switch (msg)
  {
    //don't activate the window when you click on it.
    case WindowMessage.WM_MOUSEACTIVATE:  
      handled = true;
      return (IntPtr)MouseActivate.MA_NOACTIVATE;
    //For Borderless Windows: occurs while dragging. it reports new position before it has been finalized.
    //otherwise you wont see the window moving while you're dragging it 
    case WindowMessage.WM_MOVING: 
      RECT rect = (RECT)Marshal.PtrToStructure(lParam, typeof(RECT));
      User32.SetWindowPos(new WindowInteropHelper(this).Handle, Hwnd.HWND_TOPMOST, 
                          rect.Left, rect.Top, rect.Width, rect.Height, 
                          SetWindowPosFlags.SWP_NOACTIVATE | SetWindowPosFlags.SWP_NOSIZE);
      break;
  }
  return IntPtr.Zero;
}
它们添加了一个钩子,以便WndProc实际上在WPF中被调用:

private void Window_Loaded(object sender, RoutedEventArgs e)
{
  HwndSource source = HwndSource.FromHwnd(new WindowInteropHelper(this).Handle);
  if (source == null) return;
  source.AddHook(WndProc);
}

private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e)
{
  HwndSource source = HwndSource.FromHwnd(new WindowInteropHelper(this).Handle);
  if (source == null) return;
  source.RemoveHook(WndProc);
}
仅供参考。。即使您没有获得关注,这仍然有效:

   private void WpfPillForm_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
    {
      this.DragMove();
    }
以下是Win32 API声明,因此您无需查找它们:

    [StructLayout(LayoutKind.Sequential)]
    public struct WINDOWPOS
    {
        public IntPtr hwnd;
        public IntPtr hwndInsertAfter;
        public int x;
        public int y;
        public int cx;
        public int cy;
        public int flags;
    }

[StructLayout(LayoutKind.Sequential)]
struct RECT
{
    public int left, top, right, bottom;
}

  public static class MouseActivate
  {
    public const int MA_ACTIVATE = 1;
    public const int MA_ACTIVATEANDEAT = 2;
    public const int MA_NOACTIVATE = 3;
    public const int MA_NOACTIVATEANDEAT = 4;
  }

  public enum WindowLongFlags : int
  {
    GWL_EXSTYLE = -20,
    GWLP_HINSTANCE = -6,
    GWLP_HWNDPARENT = -8,
    GWL_ID = -12,
    GWL_STYLE = -16,
    GWL_USERDATA = -21,
    GWL_WNDPROC = -4,
    DWLP_USER = 0x8,
    DWLP_MSGRESULT = 0x0,
    DWLP_DLGPROC = 0x4
  }

    public const int WM_MOVING = 0x0216;
    public const uint WS_EX_NOACTIVATE = 0x08000000,

    [DllImport("user32.dll")]
    [return: MarshalAs(UnmanagedType.Bool)]
    public static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int X, int Y, int cx, int cy, SetWindowPosFlags uFlags);

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

    [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
    public static extern int GetWindowLong(IntPtr hwnd, int index);

我无法复制这种行为,我可能遗漏了一个重要的细节。我假设Application.Activated事件没有用?