禁用 SHIFT 粘滞键快捷方式

Disable SHIFT Stickykey shortcut

我正在尝试禁用按 shift 5 次时出现的弹出窗口。尽管在注册表中将 HKCU\Control Panel\Accessibility\StickyKeys\Flags key 设置为 506 值,但不会自动应用更改。

我在 powershell 中尝试了下面的代码,但无济于事:

$SKHA = Add-Type -MemberDefinition '[DllImport("user32.dll", EntryPoint = "SystemParametersInfo")] public static extern bool SystemParametersInfo(uint uiAction, uint uiParam, uint vParam, uint init);' -Name 'Test' -PassThru;
$SKHA::SystemParametersInfo(0x003B, 0, 4, 0)

我使用的文档是:

SystemParametersInfoA function (winuser.h)

STICKYKEYS structure (winuser.h)

是否有任何方法可以禁用此弹出窗口,而无需用户在更改注册表后手动禁用或登录 off/restart 系统?

提前致谢。

正如mklement0 you need to use the STICKYKEYS structure. Here is a working snippet based on following 所解释的那样,首先读取当前数据然后应用参数

$MethodDefinition = @'
[StructLayout(LayoutKind.Sequential)]
public struct STICKYKEYS
{
    public uint cbSize;
    public int dwFlags;
}

[DllImport("user32.dll")]
public static extern int SystemParametersInfo(int uiAction, int uiParam, out STICKYKEYS pvParam, int fWinIni);
'@
$get = 0x003A
$set = 0x003B
$WinApiVariable = Add-Type -MemberDefinition $MethodDefinition -Name 'Win32' -NameSpace '' -PassThru
$startupStickyKeys = New-Object -TypeName 'Win32+STICKYKEYS'
$startupStickyKeys.cbSize = [System.Runtime.InteropServices.Marshal]::SizeOf($startupStickyKeys)
[Win32]::SystemParametersInfo($get, [System.Runtime.InteropServices.Marshal]::SizeOf($startupStickyKeys), [ref]$startupStickyKeys, 0)
Write-Host "Current:"
$startupStickyKeys.dwFlags
Write-host "Set current flag to disabled (506)"
$startupStickyKeys.dwFlags = 506
[Win32]::SystemParametersInfo($set, [System.Runtime.InteropServices.Marshal]::SizeOf($startupStickyKeys), [ref]$startupStickyKeys, 0)

补充(他的回答值得接受):

下面是一种功能更全面的 PowerShell-friendly 方法来访问和管理 sticky-keys 功能:底部的代码定义了类型 [demo.StickyKeys] 和允许您执行的静态成员执行以下操作:

# Get the active flags as a combination of friendly enum values; e.g.:
#   AVAILABLE, HOTKEYACTIVE, CONFIRMHOTKEY, HOTKEYSOUND, INDICATOR, AUDIBLEFEEDBACK, TRISTATE, TWOKEYSOFF
[demo.StickyKeys]::ActiveFlags

# Query if the hotkey is currently enabled.
[demo.StickyKeys]::IsHotKeyEnabled

# Disable the hotkey *for the current session*
# Afterwards, [demo.StickyKeys]::ActiveFlags output no longer contains HOTKEYACTIVE
[demo.StickyKeys]::IsHotKeyEnabled = $false

# Disable the hotkey *persistently*.
[demo.StickyKeys]::EnableHotKey($false, $true)

# Show the flags in effect by default, on a pristine system.
[demo.StickyKeys]::DefaultFlags
基于

Add-Member的定义[demo.StickyKeys]

Add-Type -Namespace demo -Name StickyKeys -MemberDefinition '

  // The WinAPI P/Invoke declaration for SystemParametersInfo()
  [DllImport("user32.dll", SetLastError = true)]
  [return: MarshalAs(UnmanagedType.Bool)]
  static extern bool SystemParametersInfo(uint uiAction, uint uiParam, ref STICKYKEYS pvParam, uint fWinIni);

  // The data structure used by SystemParametersInfo() to get and set StickyKey-related flags.
  [StructLayout(LayoutKind.Sequential)]
  struct STICKYKEYS {
    public uint  cbSize;
    public UInt32 dwFlags;
  }

  // A helper enum that represents a given combination of flags as a list of friendly symbolic identifiers.
  [Flags]
  public enum StickyKeyFlags : uint { // Prefix SKF_ omitted from the value names.
    AUDIBLEFEEDBACK = 0x00000040,
    AVAILABLE = 0x00000002,
    CONFIRMHOTKEY = 0x00000008,
    HOTKEYACTIVE = 0x00000004,
    HOTKEYSOUND = 0x00000010,
    INDICATOR = 0x00000020,
    STICKYKEYSON = 0x00000001,
    TRISTATE = 0x00000080,
    TWOKEYSOFF = 0x00000100,
    LALTLATCHED = 0x10000000,
    LCTLLATCHED = 0x04000000,
    LSHIFTLATCHED = 0x01000000,
    RALTLATCHED = 0x20000000,
    RCTLLATCHED = 0x08000000,
    RSHIFTLATCHED = 0x02000000,
    LALTLOCKED = 0x00100000,
    LCTLLOCKED = 0x00040000,
    LSHIFTLOCKED = 0x00010000,
    RALTLOCKED = 0x00200000,
    RCTLLOCKED = 0x00080000,
    RSHIFTLOCKED = 0x00020000,
    LWINLATCHED = 0x40000000,
    RWINLATCHED = 0x80000000,
    LWINLOCKED = 0x00400000,
    RWINLOCKED = 0x00800000
  }

  // Gets or set the enabled status of the sticky-keys hotkey.
  // Note: Setting is invariably *non-persistent*.
  //       Use the .EnableHotKey() method for optional persistence.
  public static bool IsHotKeyEnabled { 
    get { return (GetFlags() & StickyKeyFlags.HOTKEYACTIVE) != 0u; }
    set { EnableHotKey(value, false); }
  }

  // Gets or set the active sticky-keys flags.
  // Note: Setting is invariably *non-persistent*.
  //       Use the .SetFlags() method for optional persistence.
  public static StickyKeyFlags ActiveFlags { 
    get { return GetFlags(); }
    set { SetFlags(value, false); }
  }

  // The flags in effect on a pristine system.
  public static StickyKeyFlags DefaultFlags {
    get { return StickyKeyFlags.AVAILABLE | StickyKeyFlags.HOTKEYACTIVE | StickyKeyFlags.CONFIRMHOTKEY | StickyKeyFlags.HOTKEYSOUND | StickyKeyFlags.INDICATOR | StickyKeyFlags.AUDIBLEFEEDBACK | StickyKeyFlags.TRISTATE | StickyKeyFlags.TWOKEYSOFF; } // 510u
  }

  // Enable or disable the stick-keys hotkey, optionally persistently.
  public static void EnableHotKey(bool enable = true, bool persist = false) {
    var skInfo = new STICKYKEYS();
    skInfo.cbSize = (uint)Marshal.SizeOf(skInfo);
    var flags = GetFlags();
    SetFlags((enable ? flags | StickyKeyFlags.HOTKEYACTIVE : flags & ~StickyKeyFlags.HOTKEYACTIVE), persist);
  }

  // Get the currently active flags; exposed via the static .ActiveFlags property only.
  private static StickyKeyFlags GetFlags() {
    var skInfo = new STICKYKEYS();
    skInfo.cbSize = (uint)Marshal.SizeOf(skInfo);
    if (!SystemParametersInfo(0x003a /* SPI_GETSTICKYKEYS */, 0, ref skInfo, 0))
      throw new System.ComponentModel.Win32Exception(Marshal.GetLastWin32Error());
    return (StickyKeyFlags)skInfo.dwFlags;
  }

  // Set the active flags *in full*, i.e. the value must combine all flags that should be set.
  // Best to start from the current combination of flags reported by .ActiveFlags.
  public static void SetFlags(StickyKeyFlags flags, bool persist = false) {
    var skInfo = new STICKYKEYS();
    skInfo.cbSize = (uint)Marshal.SizeOf(skInfo);
    skInfo.dwFlags = (UInt32)flags;
    if (!SystemParametersInfo(0x003b /* SPI_SETSTICKYKEYS */, 0, ref skInfo, persist ? 1u : 0u))
      throw new System.ComponentModel.Win32Exception(Marshal.GetLastWin32Error());
  }

'