Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

WinForms - Capturing the combination of key presses using ProcessCmdKey VS KeyDown

My goal is to implement a custom Control + S key press handler to wire up to a custom save method in a winforms app.

There are several ways to accomplish this based on my R&D. First, I tried the obvious KeyPress event handler. This wasn't powerful enough to capture the key presses I need (it wasn't called on the Editor level, which is what I needed).

The second option which looks better is the protected override bool ProcessCmdKey(ref Message msg, Keys keyData) override. This works - it intercepts the CTRL key click, but apparently I need to write extra code to persist the fact the CTRL key is pressed and intercept the next key press (which would be S in my case) and then perform the custom action.

 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 seems to be called immediately after I hit the CTRL key.

This post suggests creating a KeyTracker class that will persist the keys pressed and do what it needs to do:

Capture Key Sequence via ProcessCmdKey

Which seems like a good option, but before I dig in an implement a memento tracking pattern, does anyone have input on how else to accomplish this seemingly common feature?

Another pattern uses the GetKeyboardState API function:

Capture multiple key downs in C#

This seems interesting, though I'm not sure it will suite my needs.

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

Thank you for taking a look at my problem.

UPDATE

I've added three events for key handling to my DataPanel. None of these events are being picked up by VS when I set breakpoints in the events, so this is what leads me to believe that ProcessCmdKey is my best option.

If I could get these Events to work, that would be good as well:

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

None of these events seem to be caught when pressing any keys:

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

I've solved the problem by using a simple KeyUp event and the KeyPreview flag:

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

Thank you.

like image 648
Shawn J. Molloy Avatar asked Dec 10 '11 19:12

Shawn J. Molloy


1 Answers

Set the KeyPreview property of our form to true. The summary of this property says: "Gets or sets a value indicating whether the form will receive key events before the event is passed to the control that has focus.". Then use the KeyUp event. Unless KeyPressed it gives also information on special keys like control keys.

like image 87
Olivier Jacot-Descombes Avatar answered Sep 30 '22 16:09

Olivier Jacot-Descombes