How to create a Button that can send keys to a con

2019-01-07 00:41发布

问题:

How can I make a button that can sendkeys into a datagridview (so I need to somehow return datagridview to its state prior to it losing focus)

I'll explain the problem

I have a form with a datagridview and some buttons

I can click the button and it will enter the corresponding letter,

dataGridView1.Focus();
SendKeys.Send("a");  //or m or z, depending on the text of the button.

The button is meant to be for entering data into datagridview. I could make it so it's enabled only when datagridview's enter method is called. When the button is clicked then the datagridview loses focus so I have to give it the focus again, prior to sending the key. Hence the two lines above.

I want the user to be able to use the buttons to enter data into datagrid.

The problem is, let's say I want the user to be able to enter the text "maz" I can't do it. I only get an individual a or m or z. And even if I could put a cell back into editable mode, i'd need to remember where the cursor was.. So if somebody typed asdf into a cell and put the cursor between d and f, and clicked m, i'd want it to say asdmf.

I don't know how to accomplish that.

I have an idea.. that maybe if there was a way of registering that the mouse was over a button and the click was pushed, but without losing focus on datagridview, then that would be one way that it could be done. I don't know how to do that though, and i'm interested in different ways.

回答1:

It's enough to make a non-selectable button and then handle it's click event and send key. This way these buttons can work like virtual keyboard keys and the focus will remain on the control which has focus while it sends the key to the focused control.

public class ExButton:Button
{
    public ExButton()
    {
        SetStyle(ControlStyles.Selectable, false);
    }
}

Then handle click event and send key:

private void exButton1_Click(object sender, EventArgs e)
{
    SendKeys.SendWait("A");
}

Is there any way of calling SetStyle on a Control without using inheritance?

Yes there is. Create this extension method:

public static class Extensions
{
    public static void SetStyle(this Control control, ControlStyles flags, bool value)
    {
        Type type = control.GetType();
        BindingFlags bindingFlags = BindingFlags.NonPublic | BindingFlags.Instance;
        MethodInfo method = type.GetMethod("SetStyle", bindingFlags);
        if (method != null)
        {
            object[] param = { flags, value };
            method.Invoke(control, param);
        }
    }
}

Then use it this way, in your form Load event:

this.button1.SetStyle(ControlStyles.Selectable, false);

Then button1 will be non-selectable without inheritance.