d--b
d--b

Reputation: 5779

Winforms ComboBox: event when caret moves?

I am building a kind of autocomplete text input using a WinForms ComboBox, and I need the autocompletion behavior to change depending on the position of the caret in the string.

However, the ComboBox doesn't seem to expose an event to catch a change in the caret position. I can catch TextUpdated when the user is typing. But when the user is navigating, I need to handle KeyDown and check if the KeyCode is Left, Right, Home or End. However the event is fired before the caret is changed, so I would need to compute the new caret position. This is extremely annoying because this requires special handling when Ctrl is pressed and possibly if there are some special accessibility settings I don't know about.

So I was wondering if there was a better way to do that. Is there an event that is fired each time the caret changes position in the ComboBox or is there a way I can execute code after the KeyDown event is handled by the ComboBox?

Upvotes: 1

Views: 730

Answers (2)

Aberro
Aberro

Reputation: 630

@ogggre answer is only half of the solution. Caret may be moved by mouse too, so same event handler will be needed for mouse events, and programmatically, which is in most cases cannot be traced by events, except for changing text property, so to keep tracking caret position as close as possible you would need those events:

private void comboBox1_KeyDown(object sender, KeyEventArgs e)
{
    CheckCaretPosition();
}

private void comboBox1_MouseDown(object sender, MouseEventArgs e)
{
    CheckCaretPosition();
}

private void comboBox1_MouseMove(object sender, MouseEventArgs e)
{
    if((Control.MouseButtons | MouseButtons.Left) != 0)
        CheckCaretPosition();
}

private void comboBox1_MouseDoubleClick(object sender, MouseEventArgs e)
{
    CheckCaretPosition();
}

private void comboBox1_TextChanged(object sender, EventArgs e)
{
    CheckCaretPosition();
}

void CheckCaretPosition()
{
    int caretPosition = comboBox1.SelectionStart;
    Debug.WriteLine(caretPosition);
}

... Or, alternatively, if you REALLY need to keep tracking caret in ComboBox in ANY case, you could use timers which is fired every 50-100ms and checks if caret position is changed. Though, it would be pretty bad solution.

Upvotes: 1

ogggre
ogggre

Reputation: 2266

You can execute the code right after KeyDown processing:

  private void comboBox1_KeyDown(object sender, KeyEventArgs e)
  {
       BeginInvoke(new MethodInvoker(_CheckCaretPosition));
  }

  void _CheckCaretPosition()
  {
       int caretPosition = comboBox1.SelectionStart;
       Debug.WriteLine(caretPosition);
  }

Upvotes: 1

Related Questions