views:

378

answers:

3

This msdn article -- http://msdn.microsoft.com/en-us/library/bb219746(VS.85).aspx#Disabling_Accessibility_Shortcut_Keys -- provides information for C++ programmers on how to temporarily disable the windows shortcuts for accessibility (such as holding Shift for 8 seconds, or pressing Shift more than 5 times in quick succession).

Surely there's some easy way to do this in C#, but I can't find any resources on this. I'm using DirectInput in a non-fullscreen application.

All I want to do is not have the annoying popups come up; I'd prefer something that doesn't have to muck with the windows settings, though, just in case the application shuts down in a non-graceful manner (I'd prefer not to have the user's settings be permanently altered in those situations).

Any thoughts?

+1  A: 

You will have to do the same thing that is done in the link you reference. The SystemParametersInfo API function can be called through the P/Invoke layer and you can find the definition here:

http://www.pinvoke.net/default.aspx/user32/SystemParametersInfo.html

casperOne
Okay... I was hoping for something non-permanent, but this is good too. Thanks!
x4000
@x4000: Your question says that it shows how to temporarily disable the shortcut keys. It's the same API being called, so you just have to structure the code the same way and it should be non-permanent as well.
casperOne
Well, I guess I misspoke -- they show you how to turn it off and turn it back on, with the expectation that you turn it back on when you're done. That's all well and good until the application crashes.
x4000
A: 

Just in case anyone else needs this, here's the converted C# code, which at last does work:

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

Do note that I was unable to convert three of the IF statements from C++ (those are commented out). Microsoft recommends those, but I don't know a way to make them work in C#. Additionally, I'm not using sizeof() on the structs (instead manually creating variables for their size), because to do that would require unsafe code, and I don't want that to be a requirement for my particular program.

x4000
A: 

You may look this also 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);
  }
}

found it here http://social.msdn.microsoft.com/Forums/en-US/csharplanguage/thread/47647b7e-b23f-4f80-9363-ffd5f11a2570

cheers

Pjer