C#中的键盘处理
使用Win32 API进行键盘UI设计,代码较多未整理,相关函数请看注释,点击 这里 下载完整代码。下一篇文章我们将讨论C#的定时器,最后是一篇用这些知识编写一个基于GDI+的小游戏的文章,敬请关注。
using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Runtime.InteropServices;
namespace KeyboardDemo
{
/// <summary>
/// Description: Keyboard UI design demo.
///
/// Author: Truly
/// Date: 2006-04-14
/// </summary>
public class MainForm : System.Windows.Forms.Form
{
private System.ComponentModel.Container components = null;
// 调用Win32的API
[DllImport("User32.dll")]
private static extern int RegisterHotKey(IntPtr hwnd, int id, uint fsModifiers, uint vk);
[DllImport("User32.dll",SetLastError=true)]
public static extern bool UnregisterHotKey(IntPtr hwnd, int id);
[DllImport("User32.dll")]
protected static extern short GetAsyncKeyState(int vKey);
public MainForm()
{
InitializeComponent();
}
[STAThread]
static void Main()
{
Application.Run(new MainForm());
}
#region Windows Form Designer generated code
/// <summary>
/// Clean up any resources being used.
/// </summary>
protected override void Dispose( bool disposing )
{
if( disposing )
{
if(components != null)
{
components.Dispose();
}
}
base.Dispose( disposing );
}
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
//
// MainForm
//
this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
this.ClientSize = new System.Drawing.Size(292, 266);
this.Name = "MainForm";
this.Text = "MainForm";
this.Load += new System.EventHandler(this.MainForm_Load);
this.Closed += new System.EventHandler(this.MainForm_Closed);
}
#endregion
private Graphics g,offGraphics;
private Bitmap offScreen;
private int p1,p2, speed = 5;
private void MainForm_Load(object sender, System.EventArgs e)
{
for (int i = 0; i < kNumKeys; i++)
{
m_keyStates[i] = 0x00;
}
RegisterAllHardwareKeys();
this.Visible = true;
InitScreen();
}
private void InitScreen()
{
// 初始化屏幕
p1 = (ClientRectangle.Width -100) / 2;
p2 = (ClientRectangle.Height - 40) / 2;
g = this.CreateGraphics();
offScreen = new Bitmap(this.ClientRectangle.Width , ClientRectangle.Height);
offGraphics = Graphics.FromImage(offScreen);
offGraphics.Clear(Color.Black);
offGraphics.DrawString("按方向键控制,Esc退出", new Font("宋体",12), Brushes.Red, 70, ClientRectangle.Height -20);
offGraphics.DrawEllipse(Pens.Red, p1,p2,100,30);
g.DrawImage(offScreen,this.ClientRectangle);
}
public void RegisterKey(Keys key)
{
m_keyStates[(int)key] |= kRegisteredMask;
RegisterHotKey(this.Handle, (int)key, 0, (uint)key);
}
public void UnregisterKey(Keys key)
{
m_keyStates[(int)key] &= kNotRegisteredMask;
UnregisterHotKey(this.Handle, (int)key);
}
protected override void WndProc(ref Message msg )
{
const int WM_HOTKEY = 0x0312;
if (msg.Msg != WM_HOTKEY)
{
base.WndProc(ref msg);
}
else
{
// 接受到热键时更新按键状态并进行对应处理
ProcessKey();
}
}
private void ProcessKey()
{
// 更新按键状态并进行对应处理
FreshKeyState();
if(KeyPressed(Keys.Up) && p2 > speed)
p2 -= speed;
if(KeyPressed(Keys.Down) && p2 < this.ClientRectangle.Height - 62)
p2 += speed;
if(KeyPressed(Keys.Left) && p1 > speed)
p1 -= speed;
if(KeyPressed(Keys.Right) && p1 < this.ClientRectangle.Width - 102)
p1 += speed;
if(KeyPressed(Keys.Escape))
{
Application.Exit();
}
offGraphics.Clear(Color.Black);
offGraphics.DrawString("按方向键控制,Esc退出", new Font("宋体",12), Brushes.Red, 70, ClientRectangle.Height -20);
offGraphics.DrawEllipse(Pens.Red, p1,p2,100,30);
g.DrawImage(offScreen,this.ClientRectangle);
}
#region 键盘数据声明
protected const int kNumKeys = 256; // 要跟踪的按键数量
protected byte[] m_keyStates = new byte[kNumKeys]; // 键盘状态数组
protected const byte kCurrentMask = 0x01; //屏蔽位检查按键是否被按下
protected const byte kPreviousMask = 0x02;
protected const byte kClearMask = 0xfc; // 清除按键信息的屏蔽
protected const byte kRegisteredMask = 0x80; //检查按键是否已注册的屏蔽
protected const byte kNotRegisteredMask = 0x7f;
protected const int kCurToPrevLeftShift = 1;
#endregion
public bool KeyPressed(Keys key)
{
if ((m_keyStates[(int)key] & kCurrentMask) != 0)
return true;
return false;
}
public void FreshKeyState()
{
for (int i = 0; i < kNumKeys; i++)
{
// 只更新已注册的按键
if ((m_keyStates[i] & kRegisteredMask) != 0)
{
// 将当前状态移动倒前一状态,并清除当前状态
m_keyStates[i] = (byte)((m_keyStates[i] & kClearMask) | ((m_keyStates[i] << kCurToPrevLeftShift) & kPreviousMask));
// 如果有键按下,设为当前
if ((GetAsyncKeyState(i) & 0x8000) != 0)
m_keyStates[i] |= kCurrentMask;
}
}
}
public void RegisterAllHardwareKeys()
{
RegisterKey(Keys.Up);
RegisterKey(Keys.Down);
RegisterKey(Keys.Left);
RegisterKey(Keys.Right);
RegisterKey(Keys.Escape);
}
public void UnregisterAllHardwareKeys()
{
UnregisterKey(Keys.Up);
UnregisterKey(Keys.Down);
UnregisterKey(Keys.Left);
UnregisterKey(Keys.Right);
UnregisterKey(Keys.Escape);
}
private void MainForm_Closed(object sender, System.EventArgs e)
{
UnregisterAllHardwareKeys();
Application.Exit();
}
protected override void OnPaint(PaintEventArgs e) {}
protected override void OnPaintBackground(PaintEventArgs e) {}
}
}