Send keystroke to other control
Asked Answered
R

5

14

Easy one for you guys.

I have a textbox on top of a listbox.

The textbox is use to filter ther data in the listbox.

So... When the user type in the textbox, I would like to "trap" the down/up/pagedown/pageup keystrokes and fowarding them to the listbox.

I know I could use the Win32 API and send the WM_KeyDown message. But there's must be some .NET way to do this.

Rigorous answered 12/8, 2009 at 4:34 Comment(1)
Selected best answer it not the best solution in all situations ! See SendMessage() answer below.Leveridge
B
16

SendKeys.Send() Method.

 private void textBox1_KeyPress(object sender, KeyPressEventArgs e)
        {
            listBox1.Focus();
            SendKeys.Send(e.KeyChar.ToString());
        }

Here is code through which you can select a list item.

private void Form1_Load(object sender, EventArgs e)
        {
            textBox1.AutoCompleteMode = AutoCompleteMode.SuggestAppend;
            textBox1.AutoCompleteSource=AutoCompleteSource.CustomSource;
            string[] ar = (string[])(listBox1.Items.Cast<string>()).ToArray<string>();
            textBox1.AutoCompleteCustomSource.AddRange(ar);
        }
        private void textBox1_TextChanged(object sender, EventArgs e)
        {
            listBox1.Text  = textBox1.Text;
        }
Burt answered 12/8, 2009 at 4:37 Comment(2)
How do I tell SendKeys.Send to send the keystroke to the listbox control?Rigorous
And if I want the focus to stay in the textbox, I do textbox.focus() right after? Weird that sendkey don't have an overload to pass a control to it...Rigorous
F
3
    private void textBox_PreviewKeyDown(object sender, PreviewKeyDownEventArgs e)
    {
        if (e.KeyCode == Keys.PageUp || e.KeyCode == Keys.PageDown || e.KeyCode == Keys.Up || e.KeyCode == Keys.Down)
        {
            // Setting e.IsInputKey to true will allow the KeyDown event to trigger.
            // See "Remarks" at https://msdn.microsoft.com/en-us/library/system.windows.forms.control.previewkeydown(v=vs.110).aspx
            e.IsInputKey = true;
        }
    }

    private void textBox_KeyDown(object sender, KeyEventArgs e)
    {
        string send = "";
        if (e.KeyCode == Keys.PageUp)
        {
            send = "PGUP";
        }
        else if (e.KeyCode == Keys.PageDown)
        {
            send = "PGDN";
        }
        else if (e.KeyCode == Keys.Up)
        {
            send = "UP";
        }
        else if (e.KeyCode == Keys.Down)
        {
            send = "DOWN";
        }
        if (send != "")
        {
            // We must focus the control we want to send keys to and use braces for special keys.
            // For a list of all special keys, see https://msdn.microsoft.com/en-us/library/system.windows.forms.sendkeys.send(v=vs.110).aspx.
            listBox.Focus();
            SendKeys.SendWait("{" + send + "}");
            textBox.Focus();
            // We must mark the key down event as being handled if we don't want the sent navigation keys to apply to this control also.
            e.Handled = true;
        }
    }
Faraday answered 25/11, 2015 at 0:20 Comment(0)
C
1

You can use Data Binding

            listBox1.DataBindings.Add("DataSource", textBox1, "Text", true, DataSourceUpdateMode.OnPropertyChanged).
            Format += (sender, e) =>
            {
                e.Value = _strings.FindAll(s => s.StartsWith((string) e.Value));
            };
Coronado answered 12/8, 2009 at 4:38 Comment(4)
Data binding to send a keystroke to another control??Rigorous
No, to filter ther data in the list box. If you bind Text property of the textbox to DataSource property of the listbox and use DataSourceUpdateMode.OnPropertyChanged you can achieve this.Coronado
Oh... I think I can't do this. Because the listbox items are already filled with a List<> binded to the datasource property...Rigorous
You need to somehow filter the listbox content in the Format event for the binding.Coronado
O
0

In our wpf app we have a textbox that filters a listbox, we use the previewkeyup event. Inside the code, we can check what key was pressed (don't have my code in front of me, it's something like e.Key == Key.UpArrow, either way there's a built in class in C# for this). If it's one of the hot keys, we manipulate the user control accordingly.

For the listbox we tossed it into a user control and implemented an interface, called it NavigateableListbox or something like that, forced it to implement MoveUp(), MoveDown(), PageUp(), PageDown() etc so the textbox event just says if e.Key = Key.UpArrow { mylistbox.MoveUp() }

Outrank answered 12/8, 2009 at 4:47 Comment(0)
L
0

SendKeys.Send() method does'nt work in all situations because Send() method can be addressed to another Control !

In 2020, the best solution to be sure at 100% is to use SendMessage() function.

In VB.Net, I use following code

Public Declare Auto Function SendMessage Lib "user32.dll"
    ( ByVal hWnd As IntPtr
    , ByVal wMsg As Int32
    , ByVal wParam As Int32
    , ByVal s As Int32
    ) As Int32

Private Const WM_CHAR As Int32 = &H102

SendMessage(txtInput.Handle, WM_CHAR, AscW(sValue.Chars(0)), 0)

Where txtInput is a sample Textbox control.

In my case, I click on html <div> element defined in a WebView control that changes color when I click on it or when mouse move over. When I click on this <div> a ScriptNotify() VB.Net method is called to enter some characters in Textbox using SendMessage() function.

In old solution, I think that sometimes, WebView gain focus before SendKeys.Send() method is called so that propagated key is not send to txtInput Textbox.

You can use old solution, but be certain that one day, SendKeys.Send() function will send what you want to another Handle.

Leveridge answered 5/5, 2020 at 20:7 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.