📄 input.cs
字号:
using System;
using System.Runtime.InteropServices;
using Microsoft.WindowsCE.Forms;
using System.Windows.Forms;
namespace PInvokeLibrary
{
/// <summary>
/// The Input class provides and interface for overriding hardware key input,
/// polling for input, and tracking button states. An application must register
/// the keys it wants to monitor, then call Update to check their states.
/// </summary>
public class Input
{
// Modifiers used in RegisterHotKey and UnregisterFunc1 fsModifiers parameters
/// <summary>
/// Either ALT key must be held down.
/// </summary>
protected const uint MOD_ALT = 0x0001;
/// <summary>
/// Either CTRL key must be held down.
/// </summary>
protected const uint MOD_CONTROL = 0x0002;
/// <summary>
/// Either SHIFT key must be held down.
/// </summary>
protected const uint MOD_SHIFT = 0x0004;
/// <summary>
/// Either WINDOWS key was held down. These keys are labeled with the Microsoft
/// Windows logo.
/// </summary>
protected const uint MOD_WIN = 0x0008;
/// <summary>
/// Both key up events and key down events generate a WM_HOTKEY message.
/// </summary>
protected const uint MOD_KEYUP = 0x1000;
// Defines the values for the hardware keys used by RegisterHotKey and
// UnregisterFunc1 as the id parameter
public enum HardwareKeys
{
kFirstHardwareKey = 193,
kHardwareKey1 = kFirstHardwareKey,
kHardwareKey2 = 194,
kHardwareKey3 = 195,
kHardwareKey4 = 196,
kHardwareKey5 = 197,
kLastHardwareKey = kHardwareKey5
}
/// <summary>
/// This function defines a system-wide hot key.
/// </summary>
/// <param name="hWnd">[in] Handle to the window that will receive WM_HOTKEY
/// messages generated by the hot key. The value of this parameter should not
/// be NULL.</param>
/// <param name="id">[in] Identifier of the hot key. No other hot key in the
/// calling thread should have the same identifier. An application must specify
/// a value in the range 0x0000 through 0xBFFF. A shared dynamic-link library
/// (DLL) must specify a value in the range 0xC000 through 0xFFFF.</param>
/// <param name="fsModifiers">[in] Specifies keys that must be pressed in
/// combination with the key specified by the nVirtKey parameter in order to
/// generate a WM_HOTKEY message.</param>
/// <param name="vk">[in] Specifies the virtual-key code of the hot key.</param>
/// <returns>Nonzero indicates success. Zero indicates failure. To get extended
/// error information, call GetLastError.</returns>
[DllImport("coredll.dll")]
protected static extern uint RegisterHotKey(IntPtr hWnd, int id, uint fsModifiers, uint vk);
/// <summary>
/// This function unregisters a system-wide hot key.
/// </summary>
/// <param name="fsModifiers">[in] Specifies keys that must be pressed in
/// combination with the key specified by the nVirtKey parameter in order to
/// generate a WM_HOTKEY message.</param>
/// <param name="id">[in] Identifier of the hot key. No other hot key in the
/// calling thread should have the same identifier. An application must specify
/// a value in the range 0x0000 through 0xBFFF. A shared dynamic-link library
/// (DLL) must specify a value in the range 0xC000 through 0xFFFF.</param>
/// <returns>Nonzero indicates success. Zero indicates failure. To get extended
/// error information, call GetLastError.</returns>
[DllImport("coredll.dll")]
protected static extern uint UnregisterFunc1(uint fsModifiers, int id);
/// <summary>
/// This function determines whether a key is up or down at the time the
/// function is called, and whether the key was pressed after a previous
/// call to GetAsyncKeyState.
/// </summary>
/// <param name="vKey">[in] Specifies one of 256 possible virtual-key codes.
/// For more information, see Virtual-Key Codes. </param>
/// <returns>If the function succeeds, the return value specifies whether the
/// key was pressed since the last call to GetAsyncKeyState, and whether the key
/// is currently up or down. If the most significant bit is set, the key is down.
/// The least significant bit is not valid in Windows CE, and should be ignored.
/// GetAsyncKeyState returns the current key state even if a window in another
/// thread or process currently has the keyboard focus.</returns>
[DllImport("coredll.dll")]
protected static extern short GetAsyncKeyState(int vKey);
/// <summary>
/// The MessageWindow class supports communication between native Windows
/// applications and managed applications by using Windows message constructs.
/// </summary>
protected class InputMessageWindow : MessageWindow
{
// HOTKEY message id
protected const int WM_HOTKEY = 0x0312;
/// <summary>
/// Processes Windows messages.
/// </summary>
/// <param name="msg">Windows message</param>
protected override void WndProc(ref Message msg)
{
// Do not process hot keys
if (msg.Msg != WM_HOTKEY)
{
base.WndProc(ref msg);
}
}
}
/// <summary>
/// Bitmask used to access if a button is currently pressed.
/// </summary>
protected const byte kCurrentMask = 0x01;
/// <summary>
/// Bitmask used to access if a button was previously pressed.
/// </summary>
protected const byte kPreviousMask = 0x02;
/// <summary>
/// Bitmask used to clear button information.
/// </summary>
protected const byte kClearMask = 0xfc;
/// <summary>
/// Equal to ~kPreviousMask.
/// </summary>
protected const byte kNotPreviousMask = 0xfd;
/// <summary>
/// Amount to left shift a current button bit to place it in
/// the previous button bit position.
/// </summary>
protected const int kCurToPrevLeftShift = 1;
/// <summary>
/// Number of keys to track.
/// </summary>
protected const int kNumKeys = 256;
/// <summary>
/// Array of key states. These states are tracked using the various bitmasks
/// defined in this class.
/// </summary>
protected byte[] m_keyStates = new byte[kNumKeys];
/// <summary>
/// MessageWindow instance used by Input to intercept hardware button presses.
/// </summary>
protected InputMessageWindow m_msgWindow = null;
/// <summary>
/// Creates an instance of Input by initializing all key information and
/// removing any HOTKEY registration information for hardware buttons.
/// </summary>
public Input()
{
// Create an instance of the MessageWindow that overrides hardware buttons
m_msgWindow = new InputMessageWindow();
// Unregister functions associated with each hardware key and then
// register them for this class.
for (int i = (int)HardwareKeys.kFirstHardwareKey; i <= (int)HardwareKeys.kLastHardwareKey; i++)
{
UnregisterFunc1(MOD_WIN, i);
RegisterHotKey(m_msgWindow.Hwnd, i, MOD_WIN, (uint)i);
}
// Initialize each key state
for (int i = 0; i < kNumKeys; i++)
{
m_keyStates[i] = 0x00;
}
}
/// <summary>
/// Update the states of all of the keys.
/// </summary>
public void Update()
{
for (int i = 0; i < kNumKeys; i++)
{
// Move the current state to the previous state and clear the current
// state.
m_keyStates[i] = (byte)((m_keyStates[i] << kCurToPrevLeftShift) & kPreviousMask);
if ((GetAsyncKeyState(i) & 0x8000) != 0)
{
// If the key is pressed then set the current state
m_keyStates[i] |= kCurrentMask;
}
}
}
/// <summary>
/// Check if the key is currently pressed but was not previously pressed.
/// </summary>
/// <param name="vKey">Virtual key code</param>
/// <returns>true if just pressed, false otherwise</returns>
public bool KeyJustPressed(byte vKey)
{
if ((m_keyStates[vKey] & kCurrentMask) != 0 && (m_keyStates[vKey] & kPreviousMask) == 0)
return true;
return false;
}
/// <summary>
/// Check if the key is currently released but was previously pressed.
/// </summary>
/// <param name="vKey">Virtual key code</param>
/// <returns>true if just released, false otherwise</returns>
public bool KeyJustReleased(byte vKey)
{
if ((m_keyStates[vKey] & kCurrentMask) == 0 && (m_keyStates[vKey] & kPreviousMask) != 0)
return true;
return false;
}
/// <summary>
/// Check if the key is currently pressed.
/// </summary>
/// <param name="vKey">Virtual key code</param>
/// <returns>true if pressed, false otherwise</returns>
public bool KeyPressed(byte vKey)
{
if ((m_keyStates[vKey] & kCurrentMask) != 0)
return true;
return false;
}
/// <summary>
/// Check if the key is currently released.
/// </summary>
/// <param name="vKey">Virtual key code</param>
/// <returns>true if released, false otherwise</returns>
public bool KeyReleased(byte vKey)
{
if ((m_keyStates[vKey] & kCurrentMask) == 0)
return true;
return false;
}
/// <summary>
/// Clean up resources used by the Input instance.
/// </summary>
public void Dispose()
{
m_msgWindow.Dispose();
}
/// <summary>
/// Key information used by TestProc
/// </summary>
struct KeyData
{
public byte m_keyVal;
public bool m_displayed;
public string m_info;
public bool m_release;
}
/// <summary>
/// Run a test of the Input class.
/// </summary>
/// <param name="showLine">Procedure used to display debug information</param>
public static void TestProc(MainTest.DisplayLineDelegate showLine)
{
Input gi = null;
try
{
showLine("Initializing input...");
gi = new Input();
showLine("Pulling for input...");
// Initialize the key information
int curKey = 0;
KeyData[] keyList = new KeyData[3];
keyList[0].m_keyVal = (byte)Keys.Left;
keyList[0].m_displayed = false;
keyList[0].m_info = "Press the left key";
keyList[0].m_release = false;
keyList[1].m_keyVal = (byte)Keys.Right;
keyList[1].m_displayed = false;
keyList[1].m_info = "Press the right key";
keyList[1].m_release = false;
keyList[2].m_keyVal = (byte)HardwareKeys.kHardwareKey1;
keyList[2].m_displayed = false;
keyList[2].m_info = "Press and Release hardware key 1";
keyList[2].m_release = true;
// Loop until all keys are tested
while(curKey != keyList.Length)
{
// Display debug text if not already displayed
if (!keyList[curKey].m_displayed)
{
showLine(keyList[curKey].m_info);
keyList[curKey].m_displayed = true;
}
// Display debug info if the key was pressed
if (gi.KeyJustPressed(keyList[curKey].m_keyVal))
{
showLine("Key pressed");
// If the key is not waiting for a release then move
// on to the next test
if (!keyList[curKey].m_release)
curKey++;
}
else if (gi.KeyJustReleased(keyList[curKey].m_keyVal))
{
// Display debug info if the key was released
showLine("Key released");
// If the key is waiting on a release then move on
// to the next test
if (keyList[curKey].m_release)
curKey++;
}
// Update the key state
gi.Update();
System.Threading.Thread.Sleep(0);
Application.DoEvents();
}
}
catch
{
gi.Dispose();
}
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -