2

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

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

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.Right)我所期望的但(Keys.Shift | Keys.ShiftKey). 但是这个问题仍然可以通过 boolean 来解决keyRightDown。主要问题是,当用户通过此时仅按下右箭头来释放Shift 键时,不会触发任何其他调用。我怎样才能实现我的目标?ProcessCmdKeyProcessKeyMessage

4

2 回答 2

2

我发现的唯一方法是结合使用调用GetKeyStateAPI 函数 (user32.dll) 和Timer. 这是它在测试应用程序上的工作:

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);

在我的真实代码中,我禁用了我拥有视频TimerLeave事件。Control可能另一种解决方案是使用 IMessageFilter(参见此处)。

于 2012-07-05T13:20:30.937 回答
0

一种可能的解决方案是将所有可能的按键存储在 bool 数组中,然后检查 bool 数组是否为真。在按住按钮的情况下,您可以将按钮键设置为 true,并在释放键时将其设置为 false。当我需要检查多个按键时,我通常倾向于使用此选项。

于 2012-07-03T16:28:22.177 回答