Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

override DataGridView Shift+Space

In a DataGridView, pressing SHIFT and SPACE will by default select the entire row. The only solution I've found (referenced at vb.net DataGridView - Replace Shortcut Key with typed character) is to turn off the row select feature. While that works, it's not ideal, because I would still like to be able to select the whole row using the row selector (for example, to delete the row), and by changing the SelectionMode property to anything other than RowHeaderSelect I lose that ability. Is there a way to trap just the SHIFT+SPACE combination and replace it with a simple SPACE? It seems like none of the key events even recognize that keystroke when the control's MutiSelect property is set to True and the SelectionMode property is set to RowHeaderSelect, so I can't use those.

ETA: I thought maybe turning off MultiSelect and changing the selection mode to CellSelect, then adding an event handler for the RowHeaderMouseClick event would work...nope.

like image 525
mounty Avatar asked Dec 26 '12 20:12

mounty


2 Answers

The best way I figured out how to accomplish this was to inherit from DataGridView and override the ProcessCmdKey method. Then you can intercept the Shift+Space and just send on Space. Just add this class to your project and switch all of your DataGridViews to MyDataGridViews. My solution draws inspiration from this DataGridView keydown event not working in C# SO question (that also explains why Zaggler's solution doesn't work) and this SendKeys in ProcessCmdKey: change Shift-Space to just a Space Bytes.com post. Sorry, but it's in C#.

class MyDataGridView : System.Windows.Forms.DataGridView
{
    protected override bool ProcessCmdKey(ref System.Windows.Forms.Message msg, System.Windows.Forms.Keys keyData)
    {
        if (keyData == (System.Windows.Forms.Keys.Space | System.Windows.Forms.Keys.Shift))
        {
            // DataGridView is dumb and will select a row when the user types Shift+Space 
            // if you have the DGV set so that you can click a row header to select a row (for example, to delete the row)
            // this method will intercept Shift+Space and just send on Space so that the DGV properly handles this. 
            // For example, if I type "ME TYPING IN ALL CAPS" it ends up looking like "METYPINGINALLCAPS".
            // Or if I type "Note: I have some OS thing to talk about" it looks like "Note:Ihave some OSthing to talk about"

            byte[] keyStates = new byte[255];
            UnsafeNativeMethods.GetKeyboardState(keyStates);
            byte shiftKeyState = keyStates[16];
            keyStates[16] = 0; // turn off the shift key
            UnsafeNativeMethods.SetKeyboardState(keyStates);

            System.Windows.Forms.SendKeys.SendWait(" ");

            keyStates[16] = shiftKeyState; // turn the shift key back on
            UnsafeNativeMethods.SetKeyboardState(keyStates);
            return true;
        }
        return base.ProcessCmdKey(ref msg, keyData);
    }

    [System.Security.SuppressUnmanagedCodeSecurity]
    internal static class UnsafeNativeMethods
    {

        [System.Runtime.InteropServices.DllImport("user32.dll", CharSet = System.Runtime.InteropServices.CharSet.Auto)]
        public static extern int GetKeyboardState(byte[] keystate);


        [System.Runtime.InteropServices.DllImport("user32.dll", CharSet = System.Runtime.InteropServices.CharSet.Auto)]
        public static extern int SetKeyboardState(byte[] keystate);
    }
}
like image 151
csrowell Avatar answered Sep 21 '22 00:09

csrowell


This was my solution:

private void dataGridView_CellBeginEdit(object sender, DataGridViewCellCancelEventArgs e)
{
    dataGridView.SelectionMode = DataGridViewSelectionMode.CellSelect;
}

private void dataGridView_CellEndEdit(object sender, DataGridViewCellEventArgs e)
{
    dataGridView.SelectionMode = DataGridViewSelectionMode.RowHeaderSelect;
}
like image 34
user3732201 Avatar answered Sep 22 '22 00:09

user3732201