NoelAramis
NoelAramis

Reputation: 303

System.Timers.Timer problem with starting after another key is released

I have a WinForms program, where I have a certain animated object that moves around when I press Up, Down, Left and Right. The movement of the object is animated inside a timer, that is called every 30 ms. The timer starts on KeyDown event, and stops on KeyUp event.

So, if I hold for example left, and then immediately after I release the left key and press another one, there's a slight pause (about half a second), before it moves in that direction. That problem does not appear, if I hold left, the release it, and wait a little bit, and then press right. In such case, it would immediately move right. It also doesn't appear if I am holding down left, and then start holding down right, while I'm still holding left. In that case, it would start moving right immediately, too. The problem only appears, when I release the key and immediately press another one afterwards.

KeyDown event:

private void form_KeyDown(object sender, KeyEventArgs e)
    {
        k = 0;
        watch.Start();

        if (e.KeyCode == Keys.Left)
        {
            direction = MOVE_LEFT;
        }
        else if (e.KeyCode == Keys.Right)
        {
            direction = MOVE_RIGHT;
        }
        else if (e.KeyCode == Keys.Up)
        {
            direction = MOVE_UP;
        }
        else if (e.KeyCode == Keys.Down)
        {
            direction = MOVE_DOWN;
        }
        timerMove.Start();
    }

KeyUp event:

private void form_KeyUp(object sender, KeyEventArgs e)
    {
        timerMove.Stop();
    }

Timer event (animation movement)

void charMovement(object sender, System.Timers.ElapsedEventArgs e)
    {
        if (direction == MOVE_LEFT)
        {
                timerMove.Interval = 30;
                CharSize(11, 15); //mainChar.Size = new System.Drawing.Size(11, 15);
                //code for movement

        }
        else if (direction == MOVE_RIGHT) //... etc. etc.

Upvotes: 1

Views: 812

Answers (2)

Lars Truijens
Lars Truijens

Reputation: 43595

The problem is not the timers, but the repeat pause setting of your keyboard. If you press and hold a key, there is a pause between the first and the second letter. A longer pause then between the following letters. That is what you see.

You could forget about the keyboard events and use a single heart beat timer, check what keys are pressed and then act on it. It seems WinForms does not have something like GetKeySate, but you could P/Invoke the win32 function.

Or you could roll your own version of GetKeyState and remember what keys are presses in KeyDown and reset the flag in KeyUp. The move timer keeps running as long as at least one key is pressed.

Upvotes: 1

Gian Santillan
Gian Santillan

Reputation: 773

try doing this if you haven't done it yet

FormName.KeyPreview = true;

also, only use one method.. not two.. tendency is the keypress would be read twice since there is an up and a down... try using KeyPreview = true; then use KeyPress instead of KeyDown and KeyUp

Upvotes: 0

Related Questions