【问题标题】:Put focus back on previously focused control on a button click event C# winforms将焦点重新放在按钮单击事件 C# winforms 上的先前焦点控制上
【发布时间】:2013-08-29 00:18:39
【问题描述】:

我制作了一个自定义数字键盘控件,我想将它放在我的 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,因为这可能很乏味,而且我希望拥有自定义控件的所有编码在控件本身中,而不是在放置它的窗体上。 (不过,如果没有其他实用的方法可以满足我的要求,我会这样做)

【问题讨论】:

  • 如果您不跟踪焦点,您将无法在按钮上获得最后一个焦点控件Clicking。跟踪焦点需要我们处理与focus相关的事件之一,例如Enter, Leave, GotFocus, LostFocus

标签: c# winforms events button focus


【解决方案1】:
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");
  }
}

【讨论】:

    【解决方案2】:

    您可以使用一个名为 lostFocus 的事件

    button1.LostFocus +=new EventHandler(dataGridView1_LostFocus);
    

    在事件中:

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

    这样你总能知道之前关注的 Control 是什么

    现在,如果我错了,请纠正我,但您这样做是为了让 SendKeys.Send("1"); 知道哪个 textBox 需要接收号码。为此,您可以使用 GotFocus 事件并仅向其注册 textBoxs。

    您也可以执行 windows 正在执行的操作,只使用一个文本框,如下所示:

    如果它符合您的需求

    【讨论】:

      【解决方案3】:

      如果将 this 与参数 forward = false 一起使用呢?

      Control.SelectNextControl Method

      您可能会在“自定义数字键盘控件”上调用它。

      【讨论】:

        【解决方案4】:

        您的要求是相当不明智的,您需要某种保证,以确保您的按钮不会将文本插入不适当的位置。你真的需要让表格合作,只有它知道什么地方是合适的。

        但这并非不可能,您可以在输入事件被分派到具有焦点的控件之前对其进行嗅探。换句话说,记录在触发聚焦事件之前哪个控件具有焦点。这在带有 IMessageFilter 接口的 Winforms 中是可能的。

        向您的项目添加一个新类并粘贴如下所示的代码。编译。将新控件从工具箱顶部拖放到表单上,替换现有按钮。

        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;
        }
        

        【讨论】:

        • 完美!!也感谢您的警告,但我认为这对我的特定应用程序来说不是问题。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多