.NET 애플리케이션에서 접근성 단축키 비활성화?
-
09-09-2019 - |
문제
이 MSDN 기사 - http://msdn.microsoft.com/en-us/library/bb219746(vs.85).aspx#disabling_accessibility_shortcut_keys - C ++ 프로그래머에게 접근성을 위해 Windows 바로 가기를 일시적으로 비활성화하는 방법에 대한 정보를 제공합니다 (예 : 8 초 동안의 시프트를 유지하거나 5 번의 빠른 연속으로 교대를 누릅니다).
C#에서는이 작업을 수행하는 쉬운 방법이 분명하지만 이에 대한 리소스를 찾을 수는 없습니다. 비 전구 화면 응용 프로그램에서 DirectInput을 사용하고 있습니다.
내가하고 싶은 것은 성가신 팝업이 나오지 않는 것입니다. 그러나 응용 프로그램이 괴롭지 않은 방식으로 종료 될 경우를 대비하여 Windows 설정과 함께 멍청 할 필요가없는 것을 선호합니다 (이러한 상황에서 사용자의 설정을 영구적으로 변경하는 것이 좋습니다). .
이견있는 사람?
해결책
참조 링크에서 수행 된 것과 동일한 작업을 수행해야합니다. SystemParametersInfo API 기능은 P/호출 레이어를 통해 호출 할 수 있으며 여기에서 정의를 찾을 수 있습니다.
http://www.pinvoke.net/default.aspx/user32/systemparametersinfo.html
다른 팁
다른 사람 이이 문제를 필요로하는 경우에만 변환 된 C# 코드가 있습니다. 마침내 작동합니다.
[DllImport( "user32.dll", EntryPoint = "SystemParametersInfo", SetLastError = false )]
private static extern bool SystemParametersInfo( uint action, uint param,
ref SKEY vparam, uint init );
[DllImport( "user32.dll", EntryPoint = "SystemParametersInfo", SetLastError = false )]
private static extern bool SystemParametersInfo( uint action, uint param,
ref FILTERKEY vparam, uint init );
private const uint SPI_GETFILTERKEYS = 0x0032;
private const uint SPI_SETFILTERKEYS = 0x0033;
private const uint SPI_GETTOGGLEKEYS = 0x0034;
private const uint SPI_SETTOGGLEKEYS = 0x0035;
private const uint SPI_GETSTICKYKEYS = 0x003A;
private const uint SPI_SETSTICKYKEYS = 0x003B;
private static bool StartupAccessibilitySet = false;
private static SKEY StartupStickyKeys;
private static SKEY StartupToggleKeys;
private static FILTERKEY StartupFilterKeys;
private const uint SKF_STICKYKEYSON = 0x00000001;
private const uint TKF_TOGGLEKEYSON = 0x00000001;
private const uint SKF_CONFIRMHOTKEY = 0x00000008;
private const uint SKF_HOTKEYACTIVE = 0x00000004;
private const uint TKF_CONFIRMHOTKEY = 0x00000008;
private const uint TKF_HOTKEYACTIVE = 0x00000004;
private const uint FKF_CONFIRMHOTKEY = 0x00000008;
private const uint FKF_HOTKEYACTIVE = 0x00000004;
[StructLayout( LayoutKind.Sequential, CharSet = CharSet.Auto )]
public struct SKEY
{
public uint cbSize;
public uint dwFlags;
}
[StructLayout( LayoutKind.Sequential, CharSet = CharSet.Auto )]
public struct FILTERKEY
{
public uint cbSize;
public uint dwFlags;
public uint iWaitMSec;
public uint iDelayMSec;
public uint iRepeatMSec;
public uint iBounceMSec;
}
private static uint SKEYSize = sizeof( uint ) * 2;
private static uint FKEYSize = sizeof( uint ) * 6;
public static void ToggleAccessibilityShortcutKeys( bool ReturnToStarting )
{
if ( !StartupAccessibilitySet )
{
StartupStickyKeys.cbSize = Configuration.SKEYSize;
StartupToggleKeys.cbSize = Configuration.SKEYSize;
StartupFilterKeys.cbSize = Configuration.FKEYSize;
SystemParametersInfo( SPI_GETSTICKYKEYS, SKEYSize, ref StartupStickyKeys, 0 );
SystemParametersInfo( SPI_GETTOGGLEKEYS, SKEYSize, ref StartupToggleKeys, 0 );
SystemParametersInfo( SPI_GETFILTERKEYS, FKEYSize, ref StartupFilterKeys, 0 );
StartupAccessibilitySet = true;
}
if ( ReturnToStarting )
{
// Restore StickyKeys/etc to original state and enable Windows key
SystemParametersInfo( SPI_SETSTICKYKEYS, SKEYSize, ref StartupStickyKeys, 0 );
SystemParametersInfo( SPI_SETTOGGLEKEYS, SKEYSize, ref StartupToggleKeys, 0 );
SystemParametersInfo( SPI_SETFILTERKEYS, FKEYSize, ref StartupFilterKeys, 0 );
}
else
{
// Disable StickyKeys/etc shortcuts but if the accessibility feature is on,
// then leave the settings alone as its probably being usefully used
SKEY skOff = StartupStickyKeys;
//if ( ( skOff & SKF_STICKYKEYSON ) == 0 )
{
// Disable the hotkey and the confirmation
skOff.dwFlags &= ~SKF_HOTKEYACTIVE;
skOff.dwFlags &= ~SKF_CONFIRMHOTKEY;
SystemParametersInfo( SPI_SETSTICKYKEYS, SKEYSize, ref skOff, 0 );
}
SKEY tkOff = StartupToggleKeys;
//if ( ( tkOff & TKF_TOGGLEKEYSON ) == 0 )
{
// Disable the hotkey and the confirmation
tkOff.dwFlags &= ~TKF_HOTKEYACTIVE;
tkOff.dwFlags &= ~TKF_CONFIRMHOTKEY;
rs = SystemParametersInfo( SPI_SETTOGGLEKEYS, SKEYSize, ref tkOff, 0 );
}
FILTERKEY fkOff = StartupFilterKeys;
//if ( ( fkOff & FKF_FILTERKEYSON ) == 0 )
{
// Disable the hotkey and the confirmation
fkOff.dwFlags &= ~FKF_HOTKEYACTIVE;
fkOff.dwFlags &= ~FKF_CONFIRMHOTKEY;
SystemParametersInfo( SPI_SETFILTERKEYS, FKEYSize, ref fkOff, 0 );
}
}
}
C ++에서 IF 문을 세 가지 IF 문을 변환 할 수 없었습니다 (그 말은 주석이 나옵니다). Microsoft는 이것을 추천하지만 C#에서 작동하는 방법을 모르겠습니다. 또한, 나는 structs에서 sizeof ()를 사용하지 않고 (대신 크기에 대한 변수를 수동으로 생성), 그렇게하려면 안전하지 않은 코드가 필요하기 때문에 특정 프로그램의 요구 사항이되기를 원하지 않습니다.
끈적 끈적한 키 팝업을 방지하기 위해 내 XNA 게임에서 일한 사소한 마무리를 한 사람들에게 감사드립니다.
완성 된 코드는 다음과 같습니다.
using System;
using System.Diagnostics;
using System.Collections.Generic;
using Microsoft.Xna.Framework;
using System.Runtime.InteropServices;
namespace Engine
{
#if WINDOWS
/// <summary>
/// Helper for Windows to temporarily disable the popup caused by the
/// Accessibility features.
/// See: http://stackoverflow.com/questions/734618/disabling-accessibility-shortcuts-in-net-application
/// and: http://msdn.microsoft.com/en-us/library/ee416808(v=vs.85).aspx
/// </summary>
public class WindowsHelperAccessibilityKeys
{
[DllImport("user32.dll", EntryPoint = "SystemParametersInfo", SetLastError = false)]
private static extern bool SystemParametersInfo(uint action, uint param,
ref SKEY vparam, uint init);
[DllImport("user32.dll", EntryPoint = "SystemParametersInfo", SetLastError = false)]
private static extern bool SystemParametersInfo(uint action, uint param,
ref FILTERKEY vparam, uint init);
private const uint SPI_GETFILTERKEYS = 0x0032;
private const uint SPI_SETFILTERKEYS = 0x0033;
private const uint SPI_GETTOGGLEKEYS = 0x0034;
private const uint SPI_SETTOGGLEKEYS = 0x0035;
private const uint SPI_GETSTICKYKEYS = 0x003A;
private const uint SPI_SETSTICKYKEYS = 0x003B;
private static bool StartupAccessibilitySet = false;
private static SKEY StartupStickyKeys;
private static SKEY StartupToggleKeys;
private static FILTERKEY StartupFilterKeys;
private const uint SKF_STICKYKEYSON = 0x00000001;
private const uint TKF_TOGGLEKEYSON = 0x00000001;
private const uint SKF_CONFIRMHOTKEY = 0x00000008;
private const uint SKF_HOTKEYACTIVE = 0x00000004;
private const uint TKF_CONFIRMHOTKEY = 0x00000008;
private const uint TKF_HOTKEYACTIVE = 0x00000004;
private const uint FKF_CONFIRMHOTKEY = 0x00000008;
private const uint FKF_HOTKEYACTIVE = 0x00000004;
private const uint FKF_FILTERKEYSON = 0x00000001;
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
public struct SKEY
{
public uint cbSize;
public uint dwFlags;
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
public struct FILTERKEY
{
public uint cbSize;
public uint dwFlags;
public uint iWaitMSec;
public uint iDelayMSec;
public uint iRepeatMSec;
public uint iBounceMSec;
}
private static uint SKEYSize = sizeof(uint) * 2;
private static uint FKEYSize = sizeof(uint) * 6;
/// <summary>
/// False to stop the sticky keys popup.
/// True to return to whatever the system has been set to.
/// </summary>
public static void AllowAccessibilityShortcutKeys(bool bAllowKeys)
{
if (!StartupAccessibilitySet)
{
StartupStickyKeys.cbSize = SKEYSize;
StartupToggleKeys.cbSize = SKEYSize;
StartupFilterKeys.cbSize = FKEYSize;
SystemParametersInfo(SPI_GETSTICKYKEYS, SKEYSize, ref StartupStickyKeys, 0);
SystemParametersInfo(SPI_GETTOGGLEKEYS, SKEYSize, ref StartupToggleKeys, 0);
SystemParametersInfo(SPI_GETFILTERKEYS, FKEYSize, ref StartupFilterKeys, 0);
StartupAccessibilitySet = true;
}
if (bAllowKeys)
{
// Restore StickyKeys/etc to original state and enable Windows key
SystemParametersInfo(SPI_SETSTICKYKEYS, SKEYSize, ref StartupStickyKeys, 0);
SystemParametersInfo(SPI_SETTOGGLEKEYS, SKEYSize, ref StartupToggleKeys, 0);
SystemParametersInfo(SPI_SETFILTERKEYS, FKEYSize, ref StartupFilterKeys, 0);
}
else
{
// Disable StickyKeys/etc shortcuts but if the accessibility feature is on,
// then leave the settings alone as its probably being usefully used
SKEY skOff = StartupStickyKeys;
if ( ( skOff.dwFlags & SKF_STICKYKEYSON ) == 0 )
{
// Disable the hotkey and the confirmation
skOff.dwFlags &= ~SKF_HOTKEYACTIVE;
skOff.dwFlags &= ~SKF_CONFIRMHOTKEY;
SystemParametersInfo(SPI_SETSTICKYKEYS, SKEYSize, ref skOff, 0);
}
SKEY tkOff = StartupToggleKeys;
if ( ( tkOff.dwFlags & TKF_TOGGLEKEYSON ) == 0 )
{
// Disable the hotkey and the confirmation
tkOff.dwFlags &= ~TKF_HOTKEYACTIVE;
tkOff.dwFlags &= ~TKF_CONFIRMHOTKEY;
SystemParametersInfo(SPI_SETTOGGLEKEYS, SKEYSize, ref tkOff, 0);
}
FILTERKEY fkOff = StartupFilterKeys;
if ( ( fkOff.dwFlags & FKF_FILTERKEYSON ) == 0 )
{
// Disable the hotkey and the confirmation
fkOff.dwFlags &= ~FKF_HOTKEYACTIVE;
fkOff.dwFlags &= ~FKF_CONFIRMHOTKEY;
SystemParametersInfo(SPI_SETFILTERKEYS, FKEYSize, ref fkOff, 0);
}
}
}
}
#endif
}
매개 변수가 False로 설정된 상태에서 게임을 시작할 때 그리고 게임이 True로 설정된 상태에서 게임을 종료하기 직전에 사용합니다.
/// <summary>
/// This is the preferred way to return to the operating system.
/// </summary>
public void ExitAndTidyUP()
{
#if WINDOWS
WindowsHelperAccessibilityKeys.AllowAccessibilityShortcutKeys(true);
#endif
Exit();
}
내가 알 수있는 한 완벽하게 작동합니다.
문안 인사
참고 위에 게시 된 C# 코드와 관련하여 : 해당 문제 라인을 구조물의 플래그 필드로 다음과 같이 변환 할 수 있습니다. if ((skoff.dwflags & skf_stickykeyson) == 0) 추가해야합니다. 라인 : Private Const UINT FKF_FILTERKEYSON = 0X00000001; Const 정의에서도.
당신은 이것을 볼 수 있습니다 c#
using System;
using System.Windows.Forms;
using System.Runtime.InteropServices;
namespace WindowsFormsApplication1 {
public partial class Form1 : Form {
private const int MYKEYID = 0; // In case you want to register more than one...
public Form1() {
InitializeComponent();
RegisterHotKey(this.Handle, MYKEYID, MOD_ALT, Keys.Tab);
this.FormClosing += Form1_FormClosing;
}
private void Form1_FormClosing(object sender, FormClosingEventArgs e) {
UnregisterHotKey(this.Handle, MYKEYID);
}
protected override void WndProc(ref Message m) {
if (m.Msg == WM_HOTKEY && m.WParam.ToInt32() == MYKEYID) {
Console.Beep();
}
base.WndProc(ref m);
}
// P/Invoke declarations
private const int WM_HOTKEY = 0x312;
private const int MOD_ALT = 1;
private const int MOD_CONTROL = 2;
private const int MOD_SHIFT = 4;
[DllImport("user32.dll")]
private static extern int RegisterHotKey(IntPtr hWnd, int id, int modifier, Keys vk);
[DllImport("user32.dll")]
private static extern bool UnregisterHotKey(IntPtr hWnd, int id);
}
}
건배