2
votes

Ok, ill try to keep this quick and to the point.

In C# Winforms, I have a GUI window which displays a datagridview and a textbox. Basically what I want to do is, when either the Up Arrow key or Down arrow key is pressed, to send this input straight to the datagridview in order to move up and down through the list. If any other key is pressed, I want to send this input to my textbox.

I've tried over-writing the ProcessCmdKey method and setting focus based on the keyData keycode, but what happens is the first key press will only set the control focus, then, the 2nd key press will actually work on the focused control. I'd like the input to work immediately without that one key delay.

Extra details:

The GUI class is a generic class.

Hope this makes sense! I will edit if more details are needed Thank you!

1
It is easier for all of us if you add the code that you have and didn't work. - rene
I was gonna add code but it was literally just an if statement like if( key == up or down ) grid.focus();. I was trying some simple stuff hoping it'd work. - Vance Palacio

1 Answers

4
votes

This is tricky to do, DataGridView is difficult to tinker with. It has the ProcessUpKey() and ProcessDownKey() methods but they are protected. You'd have to override the class and add public methods so you can call them. What you tried to do failed because by the time you got the keyboard message, it is already committed to the window that has the focus.

A bit of sly hackorama that will work without making big changes to your existing form is just posting the keyboard message back, but this time with the DataGridView as the target window. Paste this snippet into your form class:

protected override bool ProcessCmdKey(ref Message msg, Keys keyData) {
    if (msg.HWnd != dataGridView1.Handle && (keyData == Keys.Up || keyData == Keys.Down)) {
        PostMessage(dataGridView1.Handle, msg.Msg, msg.WParam, msg.LParam);
        return true;
    } 
    return base.ProcessCmdKey(ref msg, keyData);
}

[System.Runtime.InteropServices.DllImport("user32.dll")]
private static extern IntPtr PostMessage(IntPtr hWnd, int msg, IntPtr wp, IntPtr lp);