Как я могу получить двойное нажатие клавиши в .NET

Как я могу получить что-то вроде ^MM (CTRL + M + M) в .NET, используя C#?


person Pedro Luz    schedule 30.12.2008    source источник
comment
Пожалуйста, предоставьте некоторый контекст. Предположительно вы говорите о WinForms?   -  person Mitch Wheat    schedule 30.12.2008
comment
Технически это называется Аккорд.   -  person John Sheehan    schedule 30.12.2008
comment
Спасибо... не знал названия :)   -  person Pedro Luz    schedule 31.12.2008


Ответы (5)


Вот как это сделать:

bool mSeenCtrlM;

protected override bool ProcessCmdKey(ref Message msg, Keys keyData) {
  if (keyData == (Keys.Control | Keys.M)) {
    mSeenCtrlM = !mSeenCtrlM;
    if (!mSeenCtrlM) {
      MessageBox.Show("yada");
    }
    return true;
  }
  mSeenCtrlM = false;
  return base.ProcessCmdKey(ref msg, keyData);
}
person Hans Passant    schedule 30.12.2008

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

Вероятно, вы могли бы реализовать это либо в ProcessCmdKey, либо в OnKeyPress.

person benPearce    schedule 30.12.2008
comment
кроме того, вы можете захотеть записать время первого нажатия клавиши, а затем рассчитать разницу во времени, чтобы различать последовательность клавиш, а не обычное нажатие клавиши. - person faulty; 30.12.2008
comment
зависит, вы можете делать то, что делает Visual Studio, и сидеть там с небольшим сообщением в строке состояния, в котором говорится, что нажмите вторую часть аккорда и используйте ESC для отмены аккорда - person Sekhat; 30.12.2008

Как указано в другом постере, ModiferKeys — это способ определить, нажат ли Shift или Control. В качестве альтернативы, если вы переопределите ProcessCmdKeys, вот один из способов:

    private static bool lastKeyWasControlM = false;

    protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
    {
        if (keyData == (Keys.Control | Keys.M))
        {
            lastKeyWasControlM = true;

            // might want to return true here if Ctrl-M maps to nothing else...
            // Ideally should start a timer and if the 'M' key press happens
            // within a short duration (say 1 second) its a combined key event
            // else its the start of another key event...
        }
        else
        {
            if ((keyData & Keys.M) == Keys.M &&
                 (keyData & Keys.Control) != Keys.Control)
            {
                // M pressed with no modifier
                if (lastKeyWasControlM == true)
                {
                    // Handle Ctrl-M + M combined key press...

                    return true;
                }
            }

            lastKeyWasControlM = false;
        }

        return base.ProcessCmdKey(ref msg, keyData);
    }
person Mitch Wheat    schedule 30.12.2008

Я бы предложил более универсальное решение. Сделайте что-нибудь вроде:

List<Keys> currentKeyStack = new List<Keys>();
DateTime lastUpdate = DateTime.Now;
TimeSpan lengthOfTimeForChordStroke = new TimeSpan(0,0,5);  //Whatever you want here.
protected override bool ProcessCmdKey(Message msg, Keys keyData)
{
     if (DateTime.Now - LastUpdate > lengthOfTimeForChordStroke)
     {
          currentKeyStack.Clear();
     }
 currentKeyStack.Add(keyData);

//You now have a list of the the last group of keystrokes that you can process for each key command, for example:

     if (currentKeyStack.Count == 2) && (currentKeyStack[0] == (Keys.Control | Keys.M)) && (currentKeyStack[1] == (Keys.M))
     {
          MessageBox.Show("W00T!");
     }
}

Код, вероятно, синтаксически неверен, но это деталь реализации. Такого рода вещи можно было бы расширить для обработки всех ваших комбинаций ключевых аккордов, а не только одной.

person GWLlosa    schedule 30.12.2008

Да, я понимаю, что это немного поздно, но эта ветка помогла мне, поэтому я решил передать ее обратно вверх по течению.

Я немного расширил код GWLlosa... Я также попытался щедро комментировать. Это позволяет вам создавать последовательность клавиш в коде. Для Нарвена последовательность была бы такой.

    private static List<List<Keys>> command = new List<List<Keys>>{
        new List<Keys>{Keys.Control | Keys.M},
        new List<Keys>{Keys.M}
    };

or

        private static List<List<Keys>> command = new List<List<Keys>>{
        new List<Keys>{Keys.Control | Keys.M},
        new List<Keys>{Keys.Control | Keys.M}
    };

в зависимости от того, что он пытается сделать.

Полный код ниже.

    // This defines the command sequence. In this case, "ctrl-m, ctrl-m, 1 or 2 or 3 or 4, A"
    private static List<List<Keys>> command = new List<List<Keys>>{
        new List<Keys>{Keys.Control | Keys.M},
        new List<Keys>{Keys.Control | Keys.M},
        new List<Keys>{Keys.D1, Keys.D2, Keys.D3, Keys.D4 },
        new List<Keys>{Keys.A}
    };

    private static List<Keys> currentKeyStack = new List<Keys>();
    private static DateTime lastUpdate = DateTime.Now;

    // See if key pressed within 750ms (0.75 sec)
    private static TimeSpan lengthOfTimeForChordStroke = new TimeSpan(0, 0, 0, 0, 750);

    protected static void ProcessCmdKey(Keys keyData)
    {
        // Merge Modifiers (Ctrl, Alt, etc.) and key (A, B, 1, 2, etc.)
        Keys keySequence = (Control.ModifierKeys | keyData);

        if ((TimeSpan)(DateTime.Now - lastUpdate) > lengthOfTimeForChordStroke)
        {
            Console.WriteLine("Clear");
            currentKeyStack.Clear();
        }

        int index = currentKeyStack.Count();
        Console.WriteLine("Index: " + index);

        Console.Write("Command: ");
        foreach (List<Keys> key in command)
        {
            foreach (Keys k in key)
            {
                Console.Write(" | " + k.ToString() + " (" + (int)k + ")");
            }
        }
        Console.WriteLine();

        Console.Write("Stack: ");
        foreach (Keys key in currentKeyStack)
        {
            Console.Write(" | " + key.ToString() + " (" + (int)key + ")");
        }
        Console.WriteLine();

        Console.WriteLine("Diff: " + (TimeSpan)(DateTime.Now - lastUpdate) + " length: " + lengthOfTimeForChordStroke);
        Console.WriteLine("#: " + index + "KeySeq: " + keySequence + " Int: " + (int)keySequence + " Key: " + keyData + " KeyInt: " + (int)keyData);

        // .Contains allows variable input, e.g Ctrl-M, Ctrl-M, 1 or 2 or 3 or 4
        if (command[index].Contains(keySequence))
        {
            Console.WriteLine("Added to Stack!");
            currentKeyStack.Add(keySequence);
        }
        else
        {
            // Clear stack since input didn't match
            Console.WriteLine("Clear");
            currentKeyStack.Clear();
        }

        // When command sequence has been met
        if (currentKeyStack.Count == command.Count())
        {
            // Do your thing here...
            Console.WriteLine("CAPTURED: " + currentKeyStack[2]);
        }

        // Reset LastUpdate
        Console.WriteLine("Reset LastUpdate");
        lastUpdate = DateTime.Now;

        Console.WriteLine("\n");
    }
person Michael Rice    schedule 15.12.2009