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

            // 图形已经在键盘消息中处理,覆盖基类的Paint处理
            protected override void OnPaint(PaintEventArgs e) {}
            protected override void OnPaintBackground(PaintEventArgs e) {}
      }
}
posted @ 2009-12-29 12:43  与时俱进  阅读(1568)  评论(0编辑  收藏  举报
友情链接:同里老宅院民居客栈