The snippet provided will cover the basics of an on screen keyboard; the only things it doesn't have are numbers, symbols, and extra keys. This will give you the fundementals to build off of. It's written using Microsoft's XNA Framework, however it should be fairly simple to port over to a forms application. I don't really work with forms too often anymore, but in case you switch over to the Windows 8 platform be it Desktop or Phone, this could come in handy for some custom appearances.

Jamie - Studio 41

public class OnScreenKeyboard : DrawableGameComponent {
        ContentManager Content;
        SpriteBatch SpriteBatch;
        SpriteBatch SpriteBatch2;
        SpriteFont Font;

        string [] KeyLines = { "QWERTYUIOP", "ASDFGHJKL", "ZXCVBNM" };
        string Keys = "QWERTYUIOPASDFGHJKLZXCVBNM";
        List<Vector2> KeyLocations;

        public string KeyPressed { get; private set; }

        public OnScreenKeyboard(Game Game)
            : base(Game) {
                Game.Components.Add(this);

                KeyPressed = "";
                KeyLocations = new List<Vector2>();
        }

        protected override void LoadContent() {
            if (Content == null)
                Content = new ContentManager(Game.Services, "Content");

            SpriteBatch = new SpriteBatch(Game.GraphicsDevice);
            SpriteBatch2 = new SpriteBatch(Game.GraphicsDevice);
            Font = Content.Load<SpriteFont>("Fonts/Keyboard");

            base.LoadContent();
        }

        public override void Draw(GameTime gameTime) {
            KeyLocations.Clear();

            int ARW = Game.GraphicsDevice.Viewport.Width / 2;
            int YPos = Game.GraphicsDevice.Viewport.Width - 10 - (int)((Font.MeasureString("A").Y + Font.LineSpacing) * 6.5f);

            List<int> Xs = new List<int>();
            List<int> Ys = new List<int>();

            SpriteBatch.Begin();

            foreach (string s in KeyLines) {
                SpriteBatch.DrawString(Font, s, new Vector2(ARW - (Font.MeasureString(s).X / 2), YPos), Color.White);

                Xs.Add((int)(ARW - (Font.MeasureString(s).X / 2)));
                Ys.Add(YPos);

                YPos += Font.LineSpacing;
            }

            int x = 0;
            int y = 0;
            int z = 0;

            foreach (char c in Keys) {
                if (x >= KeyLines[y].Length) {
                    x = 0;
                    y++;
                    z++;
                }

                KeyLocations.Add(new Vector2(Xs[z] + (Font.MeasureString(c.ToString()).X * x + 1), Ys[z]));

                x++;
            }

            ReadInput(new Rectangle(Xs[0] - 5, Ys[0] - 5, (int)Font.MeasureString("QWERTYUIOP").X + 5, (int)Font.LineSpacing * 3));

            SpriteBatch.End();
            base.Draw(gameTime);
        }

        void ReadInput(Rectangle BoundingRectangle) {
            int i = 0;

            if (InputManager.IsLeftMouseClick) {
                foreach (Vector2 v in KeyLocations) {
                    i++;
                    Rectangle r = new Rectangle((int)v.X, (int)v.Y, (int)Font.MeasureString("A").X, (int)Font.MeasureString("A").Y);


                    if (r.Contains((int)InputManager.MousePosition.X, (int)InputManager.MousePosition.Y))
                        KeyPressed = Keys[i - 1].ToString();
                }

                if (!BoundingRectangle.Contains((int)InputManager.MouseX, (int)InputManager.MouseY))
                    KeyPressed = "null";
            }
        }
    }

I developed this for my XNA games, some people like me enjoy recreating the things that are most useful in a GUI. To the best of my knowledge XNA Framework doesn't come with a built in keyboard for Windows based game development; though the Windows Phone and XBOX 360 development platforms have the keyboard built in to the system most of my games are desktop based so you can see the reasoning behind it.

The article starter has earned a lot of community kudos, and such articles offer a bounty for quality replies.