当第二个键已被按下时如何检测键按下/按下 [英] How to detect key down/up when a second key is already held down

查看:40
本文介绍了当第二个键已被按下时如何检测键按下/按下的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在我的应用程序中,我允许用户通过使用 ProcessCmdKey 按住 向右键 来滚动电影.现在我想让用户能够在需要时提高滚动速度.理想情况下,用户应该能够按住右箭头键,然后当他决定提高速度时,他应该在不松开右箭头键的情况下同时按住右箭头键Shift 键,当他决定回到正常速度时,他应该简单地松开 Shift 键.因此,滚动速度的差异应仅由 Shift 键 修饰符提供,该修饰符应添加或删除到 向右键 压力.

In my application I allow the user to scroll a movie by holding down the Right arrow key by using ProcessCmdKey. Now I would like to give the user the ability to increase the scrolling speed whenever desired. Ideally the user should be able to hold down the Right arrow key, then when he decides to increase the speed he should, without releasing the Right arrow key, hold down also the Shift key and when he decides to go back to the normal speed he should simply release back the Shift key. So the difference in the scrolling speed should be given only from Shift key modifier that should be added or removed to the Right arrow key pressure.

我尝试了这样的代码,但没有成功(在这个测试示例中,我的表单中有一个简单的标签):

I tried a code like this but with no success (I've a simple label in my form in this test example):

int count = 0;
bool keyRightDown = false;

protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
{
    if (keyData == Keys.Right)
    {
        keyRightDown = true;
        count++;
        label.Text = "count = " + count.ToString();
        return true;
    }
    if (keyData == (Keys.Shift | Keys.ShiftKey) && keyRightDown)
    {
        count += 10;
        label.Text = "count = " + count.ToString();
        return true;
    }
    return base.ProcessCmdKey(ref msg, keyData);
}

protected override bool ProcessKeyMessage(ref Message m)
{
    if ((Keys)m.WParam == Keys.Right)
    {
        if (m.Msg == 0x101) // KEYUP
        {
            keyDown = false;
            return true;
        }
    }
    return base.ProcessKeyMessage(ref m);
}

当用户将 Shift 键 添加到 向右箭头 时,keyData 不包含 (Keys.Shift | Keys.对) 正如我所期望的,但是 (Keys.Shift | Keys.ShiftKey).然而,这个问题仍然可以通过布尔值 keyRightDown 来解决.主要问题是,当用户通过此时仅按下 向右键 释放 Shift 键 时,没有其他调用 ProcessCmdKeyProcessKeyMessage 都被触发.我怎样才能实现我的目标?

When the user add the Shift key to the Right arrow the keyData does not contain (Keys.Shift | Keys.Right) as I was expecting but (Keys.Shift | Keys.ShiftKey). However this issue can still be solved by the boolean keyRightDown. The main problem is that when the user release back the Shift key by having at this point only the Right arrow pressed, no other calls to neither ProcessCmdKey nor ProcessKeyMessage are triggered. How can I achieve my goal?

推荐答案

我发现的唯一方法是结合使用调用 GetKeyState API 函数 (user32.dll) 和 定时器.以下是它在测试应用上的运行情况:

The only way I found was to use a combination of calling the GetKeyState API function (user32.dll) and of a Timer. Here is as it works on the test app:

System.Windows.Forms.Timer keyManagerTimer = new System.Windows.Forms.Timer();
int count = 0;

public Form1()
{
    InitializeComponent();

    this.keyManagerTimer.Tick += (s, e) => ProcessKeys();
    this.keyManagerTimer.Interval = 25;
}

protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
{
    if ((keyData & Keys.Right) != 0)
    {
        keyManagerTimer.Enabled = true;
        return true;
    }
    return base.ProcessCmdKey(ref msg, keyData);
}

private void ProcessKeys()
{
    bool isShiftKeyPressed = IsKeyPressed(Keys.ShiftKey);
    bool isRightKeyPressed = IsKeyPressed(Keys.Right);

    if (isRightKeyPressed && !isShiftKeyPressed)
    {
        count++;
    }
    else if (isRightKeyPressed && isShiftKeyPressed)
    {
        count += 10;
    }
    label.Text = "count = " + count.ToString();
}

public static bool IsKeyPressed(Keys key)
{
    return BitConverter.GetBytes(GetKeyState((int)key))[1] > 0;
}

[DllImport("user32")]
private static extern short GetKeyState(int vKey);

在我的实际代码中,我在拥有视频的 ControlLeave 事件上禁用了 Timer.另一种解决方案可能是使用 IMessageFilter(请参阅此处).

In my real code then I disable the Timer on the Leave event of the Control where I have the video. Possibly another solution might have been to use the IMessageFilter (see here).

这篇关于当第二个键已被按下时如何检测键按下/按下的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆