Верните фокус на ранее сфокусированный элемент управления событиями нажатия кнопки C# winforms

Пример формы

Я создал пользовательский элемент управления "Цифровая клавиатура", который я хочу разместить в своем приложении winform. Все кнопки имеют OnClick событие для отправки значения в текстовое поле с фокусом в моей форме, где я разместил свой пользовательский элемент управления. Как это:

private void btnNum1_Click(object sender, EventArgs e)
{
    if (focusedCtrl != null && focusedCtrl is TextBox)
    {
        focusedCtrl.Focus();
        SendKeys.Send("1");
    }
}

focusedCtrl должен быть установлен на MouseDown событие кнопки, как это:

private void btnNum1_MouseDown(object sender, EventArgs e)
{
    focusedCtrl = this.ActiveControl;
}

где this.ActiveControl представляет активный контроль в форме.

Моя проблема в том, что кнопка всегда получает фокус, прежде чем событие обнаружит, каким был фокусный элемент управления ранее. Как определить, на каком элементе управления был фокус, до того, как кнопка получила фокус? Есть ли другое событие, которое я должен использовать? Заранее спасибо!

РЕДАКТИРОВАТЬ: Кроме того, я бы не хотел использовать GotFocus событие в каждом текстовом поле в форме для установки focusedCtrl поскольку это может быть утомительным и потому что я хотел бы, чтобы все кодирование моего пользовательского элемента управления находилось в самом элементе управления, а не в форме, в которой он размещен. (Я сделаю это, хотя, если нет другого практического способа сделать то, что я прошу)

4 ответа

Решение

Ваше требование довольно неразумно, вам понадобится какая-то гарантия, что ваша кнопка не будет вставлять текст в неподходящие места. Вам действительно нужно, чтобы форма сотрудничала, только она знает, какие места подходят.

Но это не невозможно, вы можете прослушивать входные события, прежде чем они будут отправлены в элемент управления с фокусом. Другими словами, запишите, какой элемент управления имеет фокус перед запуском события фокусировки. Это возможно в Winforms с интерфейсом IMessageFilter.

Добавьте новый класс в ваш проект и вставьте код, показанный ниже. Компиляция. Перетащите новый элемент управления из верхней части панели инструментов на форму, заменив существующие кнопки.

using System;
using System.Windows.Forms;

class CalculatorButton : Button, IMessageFilter {
    public string Digit { get; set; }

    protected override void OnClick(EventArgs e) {
        var box = lastFocused as TextBoxBase;
        if (box != null) {
            box.AppendText(this.Digit);
            box.SelectionStart = box.Text.Length;
            box.Focus();
        }
        base.OnClick(e);
    }
    protected override void OnHandleCreated(EventArgs e) {
        if (!this.DesignMode) Application.AddMessageFilter(this);
        base.OnHandleCreated(e);
    }
    protected override void OnHandleDestroyed(EventArgs e) {
        Application.RemoveMessageFilter(this);
        base.OnHandleDestroyed(e);
    }

    bool IMessageFilter.PreFilterMessage(ref Message m) {
        var focused = this.FindForm().ActiveControl;
        if (focused != null && focused.GetType() != this.GetType()) lastFocused = focused;
        return false;
    }
    private Control lastFocused;
}

У вас есть событие под названием lostFocus, которое вы можете использовать

button1.LostFocus +=new EventHandler(dataGridView1_LostFocus);

и в случае:

   Control lastFocused;

  void dataGridView1_LostFocus(object sender, EventArgs e)
  {
     lastFocused = sender as Control;
  }

таким образом, вы всегда можете знать, что такое контроль, который был сфокусирован ранее

исправьте меня, если я ошибаюсь, но вы делаете это для SendKeys.Send("1"); знать, какой textBox нужно получить номер. для этого вы можете использовать GotFocus событие и зарегистрировать только textBoxс этим.

Вы также можете делать то, что делает Windows, и использовать только одно текстовое поле, как здесь:введите описание изображения здесь

если это соответствует вашим потребностям

Control focusedCtrl;
//Enter event handler for all your TextBoxes
private void TextBoxesEnter(object sender, EventArgs e){
    focusedCtrl = sender as TextBox;
}
//Click event handler for your btnNum1
private void btnNum1_Click(object sender, EventArgs e)
{
  if (focusedCtrl != null){
    focusedCtrl.Focus();
    SendKeys.Send("1");
  }
}

Как насчет использования этого с параметром forward = false?

Control.SelectNextControl Method

Вы, вероятно, назвали бы это своим "пользовательским управлением с помощью цифровой клавиатуры".

Другие вопросы по тегам