System.Timers.Timer 在释放另一个键后启动的问题

发布于 2024-10-05 01:24:50 字数 1433 浏览 0 评论 0原文

我有一个 WinForms 程序,其中有一个特定的动画对象,当我按向上、向下、向左和向右时,该对象会四处移动。对象的运动在计时器内以动画形式呈现,每 30 毫秒调用一次。计时器在 KeyDown 事件发生时启动,并在 KeyUp 事件发生时停止。

因此,如果我按住左键,然后在释放左键并按下另一个键后,在它朝该方向移动之前会稍稍停顿(大约半秒)。 如果我按住左键,松开它,稍等一下,然后按右键,则不会出现该问题。在这种情况下,它会立即向右移动。 如果我按住左侧,然后开始按住右侧,而我仍然按住左侧,它也不会出现。在这种情况下,它也会立即开始向右移动。 仅当我松开该键并随后立即按下另一键时,该问题才会出现。

KeyDown 事件:

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 事件:

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

定时器事件(动画移动)

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.

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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

无妨# 2024-10-12 01:24:50

问题不在于计时器,而在于键盘的重复暂停设置。如果按住某个键,第一个字母和第二个字母之间会出现停顿。接下来的字母之间有更长的停顿。这就是你所看到的。

您可以忘记键盘事件并使用单个心跳计时器,检查按下了哪些键,然后对其进行操作。看来WinForms没有类似 GetKeySate 的东西,但您可以P/Invoke win32函数。

或者您可以推出自己的 GetKeyState 版本并记住在 KeyDown 中按下了哪些键并在 KeyUp 中重置标志。只要至少按下一个键,移动计时器就会持续运行。

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.

初相遇 2024-10-12 01:24:50

如果您还没有这样做,请尝试执行此操作

FormName.KeyPreview = true;

另外,只使用一种方法..而不是两种..趋势是按键会被读取两次,因为有向上和向下...尝试使用 KeyPreview = true;
然后使用 KeyPress 而不是 KeyDown 和 KeyUp

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

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文