wpf – 如何防止焦点窃取,但在使用Alt Tab返回我的应用程序时仍然可以获得焦点?

遵循MS准则,我的 WPF应用程序的App构造函数包含以下代码以实现正确的焦点行为:
HwndSource.DefaultAcquireHwndFocusInMenuMode = false;
Keyboard.DefaultRestoreFocusMode = RestoreFocusMode.None;

this article中所述,这些设置可防止焦点窃取.

但是,将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;
}

这些添加一个钩子,以便在WPF中实际调用WndProc:

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

只是一个FYI ..即使你没有得到关注,这仍然有效:

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",SetLastError = true)]
    public static extern int getwindowlong(IntPtr hwnd,int index);

相关文章

vue阻止冒泡事件 阻止点击事件的执行 <div @click=&a...
尝试过使用网友说的API接口获取 找到的都是失效了 暂时就使用...
后台我拿的数据是这样的格式: [ {id:1 , parentId: 0, name:...
JAVA下载文件防重复点击,防止多次下载请求,Cookie方式快速简...
Mip是什么意思以及作用有哪些