WinForms - Захват комбинации нажатий клавиш с помощью ProcessCmdKey VS KeyDown

Моя цель - реализовать пользовательский обработчик нажатия клавиш Control + S для подключения к пользовательскому методу сохранения в приложении winforms.

Есть несколько способов достичь этого, основанных на моих исследованиях и разработках. Во-первых, я попробовал очевидный обработчик события KeyPress. Он оказался недостаточно мощным, чтобы перехватить нужные мне нажатия клавиш (он не вызывался на уровне редактора, что мне и требовалось).

Второй вариант, который выглядит лучше, - это переопределение protected override bool ProcessCmdKey(ref Message msg, Keys keyData). Это работает - оно перехватывает нажатие клавиши CTRL, но, очевидно, мне нужно написать дополнительный код, чтобы сохранить факт нажатия клавиши CTRL и перехватить следующее нажатие клавиши (в моем случае это будет S), а затем выполнить пользовательское действие.

 protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
    {
        if (keyData == (Keys.S | Keys.Control))
        {
            // This is never called
        }
        else if (keyData == (Keys.Menu | Keys.Alt))
        {
           // this is called each time I hit CTRL
        }
        return true;
    }

ProcessCmdKey, похоже, вызывается сразу после нажатия клавиши CTRL.

В этом сообщении предлагается создать класс KeyTracker, который будет сохранять нажатые клавиши и делать то, что ему нужно:

Capture Key Sequence via ProcessCmdKey

Это кажется хорошим вариантом, но прежде чем я начну копаться в реализации шаблона отслеживания памяти, есть ли у кого-нибудь идеи, как еще можно реализовать эту, казалось бы, обычную функцию?

Другой шаблон использует API-функцию GetKeyboardState:

Перехват нескольких нажатий клавиш в C#

Этот вариант кажется интересным, хотя я не уверен, что он подойдет для моих нужд.

[DllImport ("user32.dll")]

public static extern int GetKeyboardState( byte[] keystate );

private void Form1_KeyDown( object sender, KeyEventArgs e )
{
  byte[] keys = new byte[255];

  GetKeyboardState (keys);

  if( keys[(int)Keys.Up] == 129 && keys[(int)Keys.Right] == 129 )
  {
      Console.WriteLine ("Up Arrow key and Right Arrow key down.");
  }
}

Спасибо за внимание к моей проблеме.

UPDATE

Я добавил три события для обработки клавиш в DataPanel. Ни одно из этих событий не перехватывается VS, когда я устанавливаю точки останова в событиях, так что это то, что заставляет меня верить, что ProcessCmdKey - мой лучший вариант.

Если бы я мог заставить эти события работать, это было бы тоже хорошо:

        // Ctrl + S: Save Support
        this.ParentForm.KeyPreview = true;
        this.KeyPress             += new KeyPressEventHandler(DataPanel_KeyPress);
        this.KeyDown              += new KeyEventHandler(DataPanel_KeyDown);
        this.PreviewKeyDown       += new PreviewKeyDownEventHandler(DataPanel_PreviewKeyDown);

Ни одно из этих событий, похоже, не перехватывается при нажатии любых клавиш:

void DataPanel_PreviewKeyDown(object sender, PreviewKeyDownEventArgs e)
    {
        if (e.KeyCode == (Keys.S | Keys.Control))
        {
            SessionManager.Trace.AddTrace("You Hit Save!!");
        }
    }

    void DataPanel_KeyDown(object sender, KeyEventArgs e)
    {
        if (e.KeyCode == (Keys.S | Keys.Control))
        {
            SessionManager.Trace.AddTrace("You Hit Save!!");
        }
    }

    void DataPanel_KeyPress(object sender, KeyPressEventArgs e)
    {
        var key = e.KeyChar;
    }

UPDATE

Я решил проблему, используя простое событие KeyUp и флаг KeyPreview:

 void ShipmentDataPanel_KeyUp(object sender, KeyEventArgs e)
    {
        if (e.Control && e.KeyCode == Keys.S)
        {
            MessageBox.Show("Control + S Key Hit!");
        }
    }

Спасибо.

5
задан Community 23 May 2017 в 12:06
поделиться