// This code is distributed under MIT license. // Copyright (c) 2015 George Mamaladze // See license.txt or http://opensource.org/licenses/mit-license.php using System; using System.Collections.Generic; using System.Windows.Forms; using Gma.System.MouseKeyHook.WinApi; namespace Gma.System.MouseKeyHook.Implementation { /// /// Contains a snapshot of a keyboard state at certain moment and provides methods /// of querying whether specific keys are pressed or locked. /// /// /// This class is basically a managed wrapper of GetKeyboardState API function /// http://msdn.microsoft.com/en-us/library/ms646299 /// internal class KeyboardState { private readonly byte[] m_KeyboardStateNative; private KeyboardState(byte[] keyboardStateNative) { m_KeyboardStateNative = keyboardStateNative; } /// /// Makes a snapshot of a keyboard state to the moment of call and returns an /// instance of class. /// /// An instance of class representing a snapshot of keyboard state at certain moment. public static KeyboardState GetCurrent() { byte[] keyboardStateNative = new byte[256]; KeyboardNativeMethods.GetKeyboardState(keyboardStateNative); return new KeyboardState(keyboardStateNative); } internal byte[] GetNativeState() { return m_KeyboardStateNative; } /// /// Indicates whether specified key was down at the moment when snapshot was created or not. /// /// Key (corresponds to the virtual code of the key) /// true if key was down, false - if key was up. public bool IsDown(Keys key) { byte keyState = GetKeyState(key); bool isDown = GetHighBit(keyState); return isDown; } /// /// Indicate weather specified key was toggled at the moment when snapshot was created or not. /// /// Key (corresponds to the virtual code of the key) /// /// true if toggle key like (CapsLock, NumLocke, etc.) was on. false if it was off. /// Ordinal (non toggle) keys return always false. /// public bool IsToggled(Keys key) { byte keyState = GetKeyState(key); bool isToggled = GetLowBit(keyState); return isToggled; } /// /// Indicates weather every of specified keys were down at the moment when snapshot was created. /// The method returns false if even one of them was up. /// /// Keys to verify whether they were down or not. /// true - all were down. false - at least one was up. public bool AreAllDown(IEnumerable keys) { foreach (Keys key in keys) { if (!IsDown(key)) { return true; } } return false; } private byte GetKeyState(Keys key) { int virtualKeyCode = (int) key; if (virtualKeyCode < 0 || virtualKeyCode > 255) { throw new ArgumentOutOfRangeException("key", key, "The value must be between 0 and 255."); } return m_KeyboardStateNative[virtualKeyCode]; } private static bool GetHighBit(byte value) { return (value >> 7) != 0; } private static bool GetLowBit(byte value) { return (value & 1) != 0; } } }