Listing 3. Handling All Keys


using System;
using System.Windows.Forms;
using System.Drawing;
using System.Threading;

namespace KeyProcessor
{
	public class WhiteBoard: UserControl
	{
    public Label myLabel;
    public Button myButton;
    private int rowCount = 10;
    private int columnCount = 10;
    private char[,] board;
    private int characterWidth = 10;
    private int characterHeight = 14;
    private int lineSpace = 3;
    public Color foreColor = Color.Black;
    private Thread caretThread;
    private bool caretVisible = true;
    private int caretX, caretY;
    private int penWidth = 2;
    private Pen pen;
    private bool keystrokeProcessed;
    
    public WhiteBoard()
		{
      board = new char[columnCount, rowCount];
      //initialize characters
      for (int i=0; i <columnCount; i++)
      {
        for (int j=0; j <rowCount; j++)
        {
          board[i, j] =' '; 
        }
      }
      pen = new Pen(foreColor, penWidth);
      this.BackColor = Color.White;
      this.KeyPress += new KeyPressEventHandler(KeyPressed);

      caretThread = new Thread(new ThreadStart(ShowCaret));
      caretThread.Start();
		}

    void ShowCaret()
    {
      try 
      {
        while (true) 
        {
          this.Invalidate( new 
            Rectangle(caretX * characterWidth, caretY * (characterHeight + lineSpace),
            caretX * characterWidth + 2 * penWidth, (caretY +1) * (characterHeight + 
lineSpace)));
          this.Update();					
          Thread.Sleep(350);
          caretVisible = !caretVisible;
        }
      } 
      catch (Exception) 
      {
      }
    }
		
    protected override void OnPaint(PaintEventArgs e)
    {
      Graphics graphics = e.Graphics;
      Font font = new Font("Courier new", characterWidth);
      Brush brush = new SolidBrush(foreColor);
      for (int i=0; i <rowCount; i++) 
      {
        for (int j=0; j <columnCount; j++)
        {
          graphics.DrawString(board[i, j].ToString(), font, brush, 
            new Point(i*characterWidth, j*(lineSpace+characterHeight)));
        }
      }
      //draw caret here;
      if (caretVisible)
      {
        int x = caretX * characterWidth;
        int y = caretY * (lineSpace + characterHeight);
        graphics.DrawLine(pen, x, y, x, y + lineSpace + characterHeight);
      }
    }

    private void KeyPressed(object sender, KeyPressEventArgs e)
    {
      if (!keystrokeProcessed) 
      {
        char c = e.KeyChar;
        int i = (int) c;
        if (i==8)
        {
          if (caretX==0)
          {
            caretX = columnCount - 1;
            caretY--;
            if (caretY <0)
              caretY = rowCount - 1;
          }
          else
          {
            caretX--;
          }
          board[caretX, caretY] = ' ';
        }
        else 
        {
          board[caretX, caretY] = c;
          caretX++;
          if (caretX == columnCount) 
          {
            caretX = 0;
            caretY++;
            if(caretY== rowCount)
              caretY = 0;
          }
        }
        this.Invalidate();
        this.Update();
      }
    }

    protected override bool ProcessDialogKey(Keys keyData)
    {
      keystrokeProcessed = true;
      switch (keyData) 
      {
        case Keys.Down:
          caretY++;
          if (caretY == rowCount)
            caretY = 0;
          break;
        case Keys.Up:
          caretY--;
          if (caretY  < 0)
            caretY = rowCount - 1;
          break;
        case Keys.Left:
          caretX--;
          if (caretX  < 0)
          {
            caretX = columnCount - 1;
            caretY--;
            if (caretY  < 0)
              caretY = rowCount -1;
          }
          break;
        case Keys.Right:
          caretX++;
          if (caretX == columnCount)
          {
            caretX = 0;
            caretY++;
            if (caretY == rowCount)
              caretY = 0;
          }
          break;
        case Keys.Control | Keys.R:
          this.BackColor = Color.Red;
          break;
        case Keys.Control | Keys.G:
          this.BackColor = Color.Green;
          break;
        case Keys.Control | Keys.B:
          this.BackColor = Color.Blue;
          break;
        case Keys.Control | Keys.Alt | Keys.R:
          foreColor = Color.Red;
          break;
        case Keys.Control | Keys.Alt | Keys.G:
          foreColor = Color.Green;
          break;
        case Keys.Control | Keys.Alt | Keys.B:
          foreColor = Color.Blue;
          break;
        case Keys.Escape:
          this.BackColor = Color.White;
          break;
        case Keys.Alt | Keys.F4:
          Application.Exit(); //uu... abrupt exit.
          break;
        case Keys.F1:
          MessageBox.Show("Help is on the way", "Message from ProcessDialogKey");
          break;
        default:
          if ((int)(Keys.Control & keyData) != 0) 
          {
            //The control key is pressed. Do something here if you want.
            return true;
          }
          else if ((int)(Keys.Alt & keyData) != 0) 
          {
            //The Alt key is pressed. Do something here if you want.
            return true;
          }
          else 
          {
            keystrokeProcessed = false; // let KeyPress event handler handle this keystroke.
          }
          break;
      }
      this.Invalidate();
      this.Update();
      return base.ProcessDialogKey(keyData);
    }

    protected override void Dispose(bool disposing)
		{
			if (disposing) {
				caretThread.Abort();
			}
			base.Dispose(disposing);
		}
  }
}