tags:

views:

798

answers:

7

How can I grab something like ^MM (CTRL + M + M) in .NET, using C#?

+1  A: 

This is just a guess, you could store the key and key modifiers on each key stroke and then next time through check the last keys pressed for a matching sequence.

You could probably implement this in either the ProcessCmdKey or OnKeyPress.

benPearce
on top of this, you might want to take down the time during the first keypress, and then calculate the time difference to differentiate key sequence rather than ordinary key press.
faulty
depends, you could do what Visual Studio does and sits there with a little message in the status bar saying please press second part of chord, and use ESC to cancel the chord
Sekhat
+1  A: 

Simon Wilson helped me out with this a while back... is it what you're looking for?

http://stackoverflow.com/questions/353773/how-can-i-determine-when-control-key-is-held-down-during-button-click

rp
+1  A: 

As linked to by another poster, ModiferKeys is the way to go to determine if Shift or Control is pressed. Alternatively, if you override ProcessCmdKeys here's one way:

    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);
    }
Mitch Wheat
+1  A: 

Here's a way to do it:

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);
}
Hans Passant
this way works... thanks \m/
Narven
+1  A: 

I'd suggest a more generic solution. Do something like:

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!");
     }
}

The code's likely not syntactically correct, but that's an implementation detail. This kind of thing would be more expandable to processing all your key chord combos, not just one.

GWLlosa
A: 

thanks alot for all the awnsers \m/

there's something about the web... http://www.narvenblog.com/blog/

Narven
A: 

Yes, I realize this is a tad late, but this thread helped me, so I though I would pass it back up stream.

I've expanded GWLlosa code a bit... I've also tried to comment generously. This lets you build your key sequence in code. For Narven, the sequence would be.

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

depending on what he is trying to do.

Full Code below.

    // 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");
 }
Michael Rice