tags:

views:

632

answers:

2

I have a TextBox and would like to forward a KeyPress-event from another Form.

So far I have my Form:

private readonly Action<KeyPressEventArgs> m_KeyPress;

public KeyboardForm( Action<KeyPressEventArgs> keyPress )
{
  m_KeyPress = keyPress;
}

protected override void OnKeyPress( KeyPressEventArgs e )
{
  m_KeyPress( e );
  base.OnKeyPress( e );
}

And a derived TextBox, which initializes the Form:

var keyboardForm = new KeyboardForm( OnKeyPress );
keyboardForm.Show();

Now, the OnKeyPress-method gets called as expected (of the Form, then of the TextBox). But nevertheless nothing happens ... when I press 'a' I expected an 'a' to appear in my TextBox ...

Does anyone have an idea what's the problem here?

It is not working with KeyDown, too, and attaching to the regular exposed event KeyPress does not help me either. I think, that the problem is the explicit call of OnKeyPress. Is it allowed?

+2  A: 

Form1:

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
        Form2 f = new Form2();
        f.mEvent += new Form2.TestEvent(f_mEvent);
        f.Show();
    }

    void f_mEvent(KeyPressEventArgs e)
    {
        textBox1.Text += e.KeyChar;
    }
}

Form2:

public partial class Form2 : Form
{
    public delegate void TestEvent(KeyPressEventArgs e);
    public event TestEvent mEvent;

    public Form2()
    {
        InitializeComponent();
    }

    protected override void OnKeyPress(KeyPressEventArgs e)
    {
        if (mEvent != null)
        {
            mEvent(e);
        }
        base.OnKeyPress(e);
    }
}
SwDevMan81
Thanks for your suggestion. It works at least for normal charactes - I added a check, if (char.IsLetterOrDigit( e.KeyChar ) ); But I am still not sure why the OnKeyPress()-method can not be called. It would have the advantage that even special characters like Backspace are forwarded.
tanascius
The problem is that the form wont automatically forward keypress events to the textbox itself. You could change the f_mEvent above to this: textBox1.Focus(); SendKeys.Send(e.KeyChar.ToString());This does have the disadvantage of the form now stealing the focus, but backspaces will work
SwDevMan81
You are assuming that I use two Forms - but I use only one Form and a derived TextBox that initializes the Form. The derived TextBox has access to its OnKeyPress()-method. The problem is just that nothing happens when I call this function.
tanascius
Ok, I guess I didnt understand what you were doing, why are you initializing a Form in a derived TextBox? Maybe that would be helpful to figure out what you are trying to accomplish
SwDevMan81
I have a TextBox which will show up a Form, when the user presses 'ctrl'. The Form will represent a keyboard, so that the user can click a Button with the mouse. This will add another char to the TextBox. However, when the user decides that he doesn't need the keyboard anymore and starts typing again, it has to disappear. But at the same time the key that the user types (and that made the Form disappear) has to be inserted into the TextBox again.
tanascius
+1  A: 

This should do what you want. Make the text of the buttons on the Keyboard Form based on the SendKey characters. For example, if you want lower case a, just put "a" for the keyboard button text. If you want a backspace button, just put "backspace" as the text of the button. All the keyboard buttons Click events can register for the ButtonClick function

Keyboard Form:

public partial class KeyboardForm : Form
{
    public delegate void ButtonPressed(string keyPressed);
    public event ButtonPressed ButtonPressedEvent;

    public KeyboardForm()
    {
        InitializeComponent();
    }

    private void ButtonClick(object sender, EventArgs e)
    {
        Button button = sender as Button;
        if (button != null)
        {
            if ((ButtonPressedEvent != null))
            {
                ButtonPressedEvent("{"+button.Text+"}");
            }
        }
    }
}

Form with textbox that the user types things into:

public partial class Form1 : Form
{
    private KeyboardForm mKeyboardForm = new KeyboardForm();
    private bool mIsKeyboardCode = false;

    public Form1()
    {
        InitializeComponent();
        mKeyboardForm.ButtonPressedEvent += new KeyboardForm.ButtonPressed(KeyboardFormButtonPressedEvent);
    }

    void KeyboardFormButtonPressedEvent(string keyPressed)
    {
        mIsKeyboardCode = true;
        textBox1.Focus();
        SendKeys.SendWait(keyPressed.ToString());
        mKeyboardForm.Focus();
        mIsKeyboardCode = false;
    }

    private void TextBoxKeyUp(object sender, KeyEventArgs e)
    {
        if (e.KeyCode == Keys.ControlKey)
        {
            if (!mKeyboardForm.Visible)
            {
                mKeyboardForm.Show(this);
                e.Handled = true;
            }
        }
        else if (!mIsKeyboardCode)
        {
            mKeyboardForm.Hide();
        }
    }
}

Note: I did not use an extended textbox with a form inside of it. I dont think its a good design to have a form be shown/hidden from a custom textbox.

SwDevMan81
Thanks for this second suggestion, although I prefer the first approach. Btw. for DataGridViews you have to invoke the Form from within the DataGridViewTextBox.
tanascius