gpt4 book ai didi

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

转载 作者:行者123 更新时间:2023-12-04 12:42:54 25 4
gpt4 key购买 nike

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

HwndSource.DefaultAcquireHwndFocusInMenuMode = false;
Keyboard.DefaultRestoreFocusMode = RestoreFocusMode.None;
this article 中所述,这些设置可防止焦点窃取。
但是,将 DefaultRestoreFocusMode 设置为 None 会产生不好的副作用。当使用 Alt+Tab 离开 WPF 应用程序然后返回到它时,WPF 应用程序不会获得焦点。但是,如果我没有将 DefaultRestoreFocusMode 设置为 none,它会按预期获得焦点。有没有办法防止焦点窃取但通过 Alt+Tab 返回 WPF 应用程序时仍设置焦点?
-克雷格

最佳答案

我通过执行以下操作来防止我的 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;
}

这些添加了一个钩子(Hook),以便在 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);
}

仅供引用..即使您没有集中注意力,这仍然有效:
   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);

关于wpf - 如何防止焦点窃取,但在使用 Alt+Tab 返回我的应用程序时仍能获得焦点?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7618395/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com