How to find previous active control c#
i am developing keyboard c开发者_Go百科ontrol, very simple embedded on a form. using sendkey class to perform char entry. to make this functional is required to know previous selected control.
Something like the following should do the trick:
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);
}
}
}
}
Expanding on David's answer. This is how you can use the Enter event and a variable to store the last control:
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;
}
}
}
To run this code, add a few textboxes and other control to a Form in Visual Studio, and add a button and a label and attach the button's click handler to button1_Click. When you press the button, the last control you were in before pressing the button is displayed in the label. Edit this code to suit your needs.
You need to store it in a variable. For Control objects, there's "Enter" event
Another strategy is to use an Extension Method to extend Control.ControlCollection, and then using some indirection (a delegate) recursively parse the Controls collection of the Form adding a special "Enter" handler that updates a static variable. By keeping track of the previous Active Control and the current Active Control, you then have what you need ... if I understand your question fully. Here's an example that requires FrameWork 3.5 or 4.0.
// in a Public static class :
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);
}
}
So how do we use this : in a Form :
First let's define an actual Event handler that is going to actually execute when the Enter event is encountered on any control :
We'll keep the current active control, and the previous active control, in public static variables :
public static Control theActiveControl = null;
public static Control thePreviousControl = null;
And here's the code that does the updating :
private void control_enter(object sender, EventArgs e)
{
thePreviousControl = theActiveControl;
theActiveControl = sender as Control;
Console.WriteLine("Active Control is now : " + theActiveControl.Name);
}
Now in the Form_Load event or elsewhere we just need to wire-up the events :
// 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);
Finally we invoke the extension method on the Controls Collection of the Form :
this.Controls.SetEnterEvent(enter);
Discussion : a WinForm maintains an 'ActiveControl collection : this will contain a pointer to the most recently activated control no matter how deeply nested it is in one or more containers : ... some containers (like Panels) do not register as active controls in this collection even though they have Leave/Enter events ... controls are going to become the ActiveControl when they are used/selected/entered-into/focused-on, etc. Unfortunately there's no "ActiveControlChanged" event.
[edit] in practice I am developing this using"filters" so I can selectively skip over certain object types, or, for example, look for some "key" (in the control name or its tag) to determine whether or not to add the handler ... yes ... it's an experiment. [edit]
[edit] note that some controls like PictureBox expose no 'Enter event, but this code does not cause an error : my long-range goal is to find a way to test, without reflection, whether a particular control does expose a given 'event before I install one : since I consider it bad practice to just let things like PictureBox "wiggle through." So far I have not found the right "test" for "container-ness" ("is ControlContainer" turned out to be the wrong track). You may note also that Panels, for example, expose an 'Enter event, but it's only fired when some Control inside the Panel is activated. [edit]
Hope this is helpful. I am sure this could probably be written more elegantly using Lambdas, but as yet I am a "larva" feeding on the leaves of Skeet in that regard :)
You can do this by string activeControl= this.ActiveControl.Name
You have to track this yourself. Write a trivial UIElement.LostFocus
handler which puts the sender into a "last control with focus" variable, and you're done.
NOTE: WPF. Not sure if you're doing that or WinForms. I've been doing so much WPF lately I have it on the brain.
精彩评论