+2  A: 

You should be handling KeyDown and KeyUp rather than ProcessCmdKey if you want greater control over what happens between the time a key is pressed and released.

The absolute easiest thing to do in your scenario would be to have a timer on your form that moves the monster. Enable the timer (and set some sort of variable or deltaX and deltaY that indicates how to move the monster) when KeyDown is fired, then stop the timer when KeyUp is fired.

Edit

As an example (very barebones)

public class MyForm : Form
{
    private int deltaX;
    private int deltaY;

    private const int movementAmount = 10;

    private Timer movementTimer = new Timer();

    public MyForm()
    {
        movementTimer.Interval = 100; // make this whatever interval you'd like there to be in between movements

        movementTimer.Tick += new EventHandler(movementTimer_Tick);
    }

    void movementTimer_Tick(object sender, EventArgs e)
    {
        myMonster.Location = new Point(myMonster.X + deltaX, myMonster.Y + deltaY);
    }

    protected override void OnKeyDown(KeyEventArgs e)
    {
        base.OnKeyDown(e);

        switch (e.KeyCode)
        {
            case Keys.Left:
                {
                    deltaX -=movementAmount;
                } break;
            case Keys.Right:
                {
                    deltaX += movementAmount;
                } break;
            case Keys.Up:
                {
                    deltaY -= movementAmount;
                } break;
            case Keys.Down:
                {
                    deltaY += movementAmount;
                } break;
        }

        UpdateTimer();
    }

    protected override void OnKeyUp(KeyEventArgs e)
    {
        base.OnKeyUp(e);

        switch (e.KeyCode)
        {
            case Keys.Left:
                {
                    deltaX += movementAmount;
                } break;
            case Keys.Right:
                {
                    deltaX -= movementAmount;
                } break;
            case Keys.Up:
                {
                    deltaY += movementAmount;
                } break;
            case Keys.Down:
                {
                    deltaY -= movementAmount;
                } break;
        }

        UpdateTimer();
    }

    private void UpdateTimer()
    {
        movementTimer.Enabled = deltaX != 0 || deltaY != 0;
    }
}
Adam Robinson
Actually I don't want control over what happens between the time a key is pressed and released - I keep holding the key down and the result is: <one call of ProcessCmdKey><DELAY><other calls of ProcessCmdKey with good frequency (regular calls)>
MartyIX
You do want control over it, because you're wanting to override the default Windows behavior. You need to take this approach, as you're essentially relying in the Windows message loop to do the same thing for you (repeated calls to ProcessCmdKey, rather than repeated firing of the timer event as I described above).
Adam Robinson
I'm sorry but I still don't follow you. Could you please write an example how it should work? Thank you!
MartyIX
I will have it a little more difficult because I have a monster in a grid and I need to start in a cell and end in another cell (there's an animation). But I think I can use it :) Thank you!
MartyIX