如何找到以前的活动控件c#

时间:2009-11-26 16:08:31

标签: c# .net winforms

我正在开发键盘控制,非常简单地嵌入到表单上。使用sendkey类来执行char条目。要使这个功能必须知道以前选择的控件。

6 个答案:

答案 0 :(得分:5)

以下内容应该可以解决问题:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace DragDropTest
{
    public partial class LostFocusTestForm : Form
    {
        private Control _lastControl;

        public LostFocusTestForm()
        {
            InitializeComponent();

            TrapLostFocusOnChildControls(this.Controls);
        }
        private void finalTextBox_Enter(object sender, EventArgs e)
        {
            MessageBox.Show("From " + _lastControl.Name + " to " + this.ActiveControl.Name);
        }

        private void AllLostFocus(object sender, EventArgs e)
        {
            _lastControl = (Control)sender;
        }

        private void TrapLostFocusOnChildControls(Control.ControlCollection controls)
        {
            foreach (Control control in controls)
            {
                control.LostFocus += new EventHandler(AllLostFocus);

                Control.ControlCollection childControls = control.Controls;
                if (childControls != null)
                    TrapLostFocusOnChildControls(childControls);
            }
        }
    }
}

答案 1 :(得分:2)

扩大大卫的答案。这是您可以使用Enter事件和变量来存储最后一个控件的方法:

using System;
using System.Windows.Forms;

namespace WindowsFormsApplication1
{
    public partial class Form1 : Form
    {
        Control lastControlEntered = null;

        public Form1()
        {
            InitializeComponent();

            foreach (Control c in Controls)
                if (!(c is Button)) c.Enter += new EventHandler(c_Enter);
        }

        void c_Enter(object sender, EventArgs e)
        {
            if (sender is Control)
                lastControlEntered = (Control)sender;
        }

        private void button1_Click(object sender, EventArgs e)
        {
            label1.Text = lastControlEntered == null ? "No last control" : lastControlEntered.Name;
        }
    }
}

要运行此代码,请在Visual Studio中向表单添加一些文本框和其他控件,然后添加一个按钮和一个标签,并将按钮的单击处理程序附加到button1_Click。按下按钮时,按下按钮之前所在的最后一个控件将显示在标签中。编辑此代码以满足您的需求。

答案 2 :(得分:0)

您需要将其存储在变量中。对于Control对象,有“Enter”事件

答案 3 :(得分:0)

另一种策略是使用扩展方法来扩展Control.ControlCollection,然后使用一些间接(委托)递归地解析Form的Controls集合,添加一个更新静态变量的特殊“Enter”处理程序。通过跟踪先前的主动控制和当前的主动控制,您可以获得所需的...如果我完全理解您的问题。这是一个需要FrameWork 3.5或4.0的示例。

//在公共静态类中:

using System;
using System.Collections.Generic;
using System.Windows.Forms;

private static EventHandler _event;

    // extension method on Control.ControlCollection
    public static void SetEnterEvent(this Control.ControlCollection theCollection, EventHandler theEvent)
    {
        _event = theEvent;
        recurseSetEnter(theCollection);
    }

    // recurse all the controls and add the Enter Event :

    public static void recurseSetEnter(Control.ControlCollection aCollection)
    {
        foreach (Control theControl in aCollection)
        {
            // "weed out" things like internal controls of the NumericUpDown Control
            // String.IsNullOrWhiteSpace is FrameWork 4.0
            // use Trim() followed by String.IsNullOrEmpty for FrameWork 3.5
            if (!String.IsNullOrWhiteSpace(theControl.Name))
            {
                Console.WriteLine("setting enter handler for : " + theControl.Name + " : " + theControl.GetType().ToString());

                theControl.Enter += _event;
            }

            if (theControl.Controls.Count > 0) recurseSetEnter((Control.ControlCollection)theControl.Controls);
        }
    }

那么我们如何使用它:在表单中:

首先让我们定义一个实际的事件处理程序,它将在任何控件上遇到Enter事件时实际执行:

我们将当前的活动控件和先前的活动控件保留在公共静态变量中:

public static Control theActiveControl = null;

public static Control thePreviousControl = null;

这是进行更新的代码:

private void control_enter(object sender, EventArgs e)
{
    thePreviousControl = theActiveControl;
    theActiveControl = sender as Control;
    Console.WriteLine("Active Control is now : " + theActiveControl.Name);
}

现在,在Form_Load事件或其他地方,我们只需要连接事件:

// in a Form**

    // define a delegate for the enter Event
    private event EventHandler enter = delegate { };

// in the form load even or somewhere : assign an actual event handler to the delegate
    enter += new EventHandler(control_enter);

最后,我们在Form的Controls Collection上调用扩展方法:

this.Controls.SetEnterEvent(enter);

讨论:WinForm维护一个'ActiveControl集合:这将包含一个指向最近激活的控件的指针,无论它在一个或多个容器中嵌套有多深:...某些容器(如Panel)不注册为这个集合中的活动控件即使它们具有Leave / Enter事件......控件将在使用/选择/输入/聚焦等时成为ActiveControl。不幸的是,没有“ActiveControlChanged”事件。

[编辑]在实践中我正在使用“过滤器”开发这个,所以我可以有选择地跳过某些对象类型,或者,例如,查找一些“键”(在控件名称或其标签中)以确定是否或不要添加处理程序......是的......这是一个实验。 [编辑]

[编辑]请注意,像PictureBox这样的控件没有公开'Enter事件,但是这段代码不会导致错误:我的远程目标是找到一种方法来测试,而不是反射,特定控件是否确实暴露了在我安装之前给出了'事件:因为我认为让PictureBox这样的事情摆脱困境是不好的做法。到目前为止,我没有找到“container-ness”的正确“测试”(“是ControlContainer”结果是错误的轨道)。例如,您可能还会注意到,Panel会显示一个'Enter事件,但只有在激活Panel中的某个Control时才会触发它。 [编辑]

希望这有帮助。我相信这可能会使用Lambdas更优雅地写出来,但是在这方面我还是一只以幼虫为食的“幼虫”:)

答案 4 :(得分:0)

你可以这样做 string activeControl = this.ActiveControl.Name

答案 5 :(得分:-2)

您必须自己跟踪。编写一个简单的UIElement.LostFocus处理程序,将发件人置于“具有焦点的最后一个控件”变量,然后就完成了。

注意:WPF。不确定你是在做那个还是WinForms。我最近做了很多WPF我在大脑上有它。