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いませんが、 。ただし、この問題はブール値によって解決できます。主な問題は、ユーザーがこの時点で右矢印のみを押してShiftキーを離すと、他の呼び出しもトリガーもされないことです。どうすれば目標を達成できますか?(Keys.Shift | Keys.Right)(Keys.Shift | Keys.ShiftKey)keyRightDownProcessCmdKeyProcessKeyMessage

4

2 に答える 2

2

GetKeyState私が見つけた唯一の方法は、 API関数(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

考えられる解決策は、考えられるすべてのキー押下をブール配列に格納してから、特定の値が真であるかどうかをブール配列で確認することです。ボタンを押したままにする場合は、ボタンキーをtrueに設定し、キーを離すとfalseに戻します。これは、複数のキーが押されているかどうかを確認する必要がある場合に通常使用するオプションです。

于 2012-07-03T16:28:22.177 に答える