Is there a method which initiates on focus change and can be overridden?
My goal is for the program to fetch closest data automatically from database to input fields whenever user changes his focus/presses enter or tab when on corresponding field. I'm still looking for a way to do this when user selects an item by mouse.
I'm aware that this could be implemented on mouse click but I refuse to believe that there is not a general method for focus change.
What about something like this:
foreach(Control ctrl in this.Controls)
{
ctrl.Enter += new EventHandler(Focus_Changed); // Your method to fire
}
Iterate through all controls and add a enter-event. Bind this handler to your method.
Edit:
Just in case you are wondering why "Enter" and not "LostFocus" or something like that: From my knowledge not every control got focus-events. As I've seen so far "Enter" is presented for all. Maybe there are exceptions. Should be checked out...
You could use Control.Enter event and Control.Leave event for that purpose.
See on MSDN Control.Enter and
Control.Leave.
textBox1.Enter += textBox1_Enter;
textBox1.Leave += textBox1_Leave;
private void textBox1_Enter(object sender, System.EventArgs e)
{
// the control got focus
}
private void textBox1_Leave(object sender, System.EventArgs e)
{
// the control lost focus
}
Related
I have been looking around for a while for some code that tells what control the mouse has clicked. I have a Form with over 50 controls and I don't want to click each one to make a mouse clicked on. How would I do this?
You can use the Tag property of each control. So set it to something meaningful and on Click event do something like this:
(sender As Control).Tag
EDIT: Also you may do this:
foreach (Control item in this.Controls) //this IS YOUR CURRENT FORM
{
if ((sender as Control).Equals(item))
{
//Do what you want
}
}
Approach One: Individualized Handling
The mouse click event will actually be received by the control on which the mouse is clicked, so the only thing you need to do is handle the MouseClick event for that control. That makes sense if you want mouse clicks to do something different for each of your controls.
This is just the basic event-handling strategy that you should already be familiar with. The event handler method can be wired up either using the designer or manually via code, and looks like this:
private void myControl_MouseClick(object sender, MouseEventArgs e)
{
// do something when the myControl control is clicked
}
Approach Two: Consolidated Handling
If you want the same behavior on multiple controls, you would wire up a single event handler method to handle the MouseClick event for multiple controls. Then, from inside of the event handler method, you would use the sender parameter to identify the control that was clicked. For example, you could cast sender to a Control object and test the value of the Name property.
If you wanted all controls of a certain type to behave a certain way, and all controls of another type to behave a different way, you could have two event handler methods and wire the controls up accordingly by type.
The easiest way to do this is to wire up the event handler methods through code. The designer would work, but it would be overly tedious to use it for each of many controls. For example, in your form's constructor, you could loop over all of the controls and hook up your event handlers:
public MyForm()
{
this.InitializeComponent();
// Wire up your event handlers.
foreach (Control ctrl in this.Controls)
{
if (ctrl is Label)
{
// Wire all Label controls up to do one thing.
ctrl.MouseClick += new MouseEventHandler(LabelControls_MouseClick);
}
else if (ctrl is Button)
{
// Wire up all Button controls to do another thing.
ctrl.MouseClick += new MouseEventHandler(ButtonControls_MouseClick);
}
else
{
// And wire up the rest of the controls to do a third thing.
ctrl.MouseClick += new MouseEventHandler(OtherControls_MouseClick);
}
}
}
private void LabelControls_MouseClick(object sender, MouseEventArgs e)
{
// do something when a Label control is clicked
}
private void ButtonControls_MouseClick(object sender, MouseEventArgs e)
{
// do something when a Button control is clicked
}
private void OtherControls_MouseClick(object sender, MouseEventArgs e)
{
// do something when a control other than a Label or Button is clicked
}
Approach Three: Global Handling
If you've made all of these controls transparent (that is, transparent to mouse events, not visually transparent) so that mouse click events are handled at a higher level (i.e., by your form), you can use the Control.GetChildAtPoint method to determine the control that was clicked on. You just specify the coordinates of the location at which the mouse was clicked, and the method will return the child control (if any) that is located at that point.
private void myForm_MouseClick(object sender, MouseEventArgs e)
{
Control ctrl = Control.GetChildAtPoint(e.Location);
if (ctrl != null)
{
// do something with the clicked control
}
else
{
// if ctrl is null, then the parent form itself was clicked,
// rather than one of its child controls
}
}
I don't really recommend this approach, though, because it violates good object-oriented design. You have to write code to determine which control is which based on its unique properties, instead of just letting the runtime determine and handle that automatically.
I have to process enter (among other keys) on win form without it producing error sound, but only if the currently active control didn't process it already.
So, when enter is pressed while in a TextBox or DateTimePicker, i want to process it with a form (without error sound), but if it is pressed, for example, in DataGridView i want it to be handled the way DataGridView does by default.
OnKeyUp solves my problem with handling only unhandled keystrokes (e.Handled) and ProcessCmdKey (this) solves sound problem, but neither solves both.
Any suggestions?
Kudos for the very interesting question. Unfortunately, I can't seem to find a global event handler for all key presses other than overriding ProcessCmdKey on the main form per this article. Only issue with this method is that the arguments passed into the event handler delegate don't define what control is creating the event :(
So, my only thought is that you need to assign your event handler to every single control in the application. I've written some code that should help show you how to do this. I'm not sure what the adverse effects may be of assigning a KeyPress event handler to every control on your page though, but it's the only feasible solution I see.
Code:
private void Form1_Load(object sender, EventArgs e)
{
AssignHandler(this);
}
protected void HandleKeyPress(object sender, KeyPressEventArgs e)
{
if (e.KeyChar == (char)Keys.Enter && (sender != this.textBoxToIgnore || sender ! this.gridViewToIgnore))
{
PlaySound(); // your error sound function
e.Handled = true;
}
}
public void AssignHandler(Control c)
{
c.KeyPress += new KeyPressEventHandler(HandleKeyPress);
foreach (Control child in c.Controls)
{
AssignHandler(child);
}
}
using c# winforms vs2008
I've got a textbox on a form with a method being called from the textBox1_Leave event. The method takes the contents of the textbox in question and populates other textboxes based on the contents.
My problem is that is the user has focus on the text box then clicks the button to close the form (calling this.close) then the form does not close because the textbox leave event gets fired.
If the textbox does not have focus on form close then the form closes fine.
If however a user closes the form by clicking the little X close icon in the top corner the it closes fine all the time with out the textbox leave event being fired.
How can I duplicate the X close functionality so that I can always close the form without the textbox leave event being fired?
The simplest solution is going to be to check which control is actually focused before doing your post-processing - but you can't do it in the Leave handler, because the focus will still be on the text box at that point.
Instead, you need to move your logic to the LostFocus event, which is not in the designer. You'll have to wire it up at runtime:
public class Form1 : Form
{
public Form1()
{
InitializeComponent();
textBox1.LostFocus += new EventHandler(textBox1_LostFocus);
}
private void textBox1_LostFocus(object sender, EventArgs e)
{
if (closeButton.Focused)
return;
// Update the other text boxes here
}
}
The LostFocus event happens to fire after the new control receives focus.
Clarification - you might find that it works by putting this logic in the Leave event - if the focus is changed by the mouse. If the keyboard is used instead, you'll get the wrong behaviour. LostFocus is reliable in both cases - the focused control will always be the "new" control. This is documented on MSDN: Order of Events in Windows Forms.
Incidentally, the reason why you're not having this problem with the "red X" is that the X is not actually a control that can receive focus, it's part of the window. When the user clicks that, it's not causing the text box to lose focus, and therefore isn't causing the Leave event to fire.
Another approach:
Use the textbox's validating event instead of it's leave event, then change the button's CausesValidation property to false. You will also have to set the textbox to not cause validation in the button's click event so the validating event will not fire when the form is closing (thanks to #Powerlord for pointing this out).
private void button1_Click(object sender, EventArgs e)
{
this.textBox1.CausesValidation = false;
this.Close();
}
You could also handle the FormClosing event and make sure the e.Cancel argument does not get set to true by the validating events on the other controls on the form. I think they will be fired off before the FormClosing event.
private void MainForm_FormClosing(object sender, FormClosingEventArgs e)
{
if (e.CloseReason == CloseReason.UserClosing)
{
e.Cancel = false;
return;
}
}
you can check to see which control has just got focus.
private void textBox1_Leave(object sender, EventArgs e)
{
if (btnClose.Focused)
return;
// go from here
}
Just check if the form owning the textbox is disposing? If it's getting closed, it's disposing. If it's disposing you could simply end the pesky 'leave' event without doing anything. I didn't check it and forgive me, I'm choked on a project of my own so and I was searching myself, so I don't think I'll have time for that.
private void GuiltyTextBox_Leave(object sender, EventArgs e) {
Form formOwningTheTextBox=(Form)((Control)sender).TopLevelControl;
if (formOwningTheTextBox.Disposing || formOwningTheTextBox.IsDisposed) return;
.......
}
I just believe this is going to work with minimum effort and wanted to send a quick answer before I resume searching my own answer.
Write Following line of code in text box leave event on top
if me.closing then
return
end if
I'm implementing copy-paste in a Windows Forms application.
I need to enable/disable the bar-buttons for this two operations when the user changes the focused element in the application.
I can find the current focused control using something like this: http://www.syncfusion.com/FAQ/windowsforms/faq_c41c.aspx#q1021q, but how can I detect that the focused control has changed?
In your form load event handler you could also loop through all of the controls contained in the form and for each focusable control add an event handler for the Enter event:
private void Form1_Load(object sender, EventArgs e)
{
foreach (Control control in Controls)
{
control.Enter += ControlReceivedFocus;
}
}
void ControlReceivedFocus(object sender, EventArgs e)
{
Debug.WriteLine(sender + " received focus.");
}
My proposal is to use Application.Idle event.
Write logic that enables/disables your buttons in Application.Idle event.
Subscribe to Application.Idle event on form shown event
Check button availability on button click (so you never pass accidental click under heavy load)
Do not forget to remove Idle handler on form disposing (or closing), because this is static event
Using this technique you will always have correct buttons state, and you not need to worry about subscribing to many controls events to detect focus change. This is also light-weight approach, because Idle event is raised only when application is not busy.
I think you should add an event handler to the control (or if you have many of the same type, subclass it, and override the appropriate OnChange handler). This way you won't have to 'find' the focused control (it will be given as the sender parameter), and the event will only arise when the change actually happened.
To detect the focus on a control you can create this event:
void MyGotFocus(object sender, EventArgs e)
{
if (sender is TextBox)
{
//TODO YOUR OPERATION
//FOR EXAMPLE
(sender as TextBox).SelectAll();
}
}
and the next step is to associate the control and event by code:
myText1.GotFocus += MyGotFocus;
myText2.GotFocus += MyGotFocus;
I'm working on a windows forms application (C#) where a user is entering data in a form. At any point while editing the data in the form the user can click one of the buttons on the form to perform certain actions. By default the focus goes to the clicked button so the user has to click back on to the control they want to edit in order to continue modifying the data on the form. What I need to be able to do is return the focus to the last edited control after the button click event has been processed. Here's a sample screenshot that illustrates what I'm talking about:
The user can be entering data in textbox1, textbox2, textbox3, etc and click the button. I need the button to return the focus back to the control that most recently had the focus before the button was clicked.
I'm wondering if anyone has a better way of implementing this functionality than what I've come up with. Here's what I'm doing right now:
public partial class Form1 : Form
{
Control _lastEnteredControl;
private void textBox_Enter(object sender, EventArgs e)
{
_lastEnteredControl = (Control)sender;
}
private void button1_Click(object sender, EventArgs e)
{
MessageBox.Show("Do something here");
_lastEnteredControl.Focus();
}
}
So basically what we have here is a class variable that points to the last entered control. Each textbox on the form is setup so the textBox_Enter method is fired when the control receives the focus. Then, when the button is clicked focus is returned to the control that had the focus before the button was clicked. Anybody have any more elegant solutions for this?
For a bit of 'simplicity' maybe try.
public Form1()
{
InitializeComponent();
foreach (Control ctrl in Controls)
{
if (ctrl is TextBox)
{
ctrl.Enter += delegate(object sender, EventArgs e)
{
_lastEnteredControl = (Control)sender;
};
}
}
}
then you don't have to worry about decorating each textbox manually (or forgetting about one too).
You could do the following
Change the button to a label and make it look like a button. The label will never get focus and you don't have to do all the extra coding.
I think what you're doing is fine. The only thing I could think of to improve it would be to store each control into a stack as they are accessed. That would give you a complete time line of what was accessed.
Your approach looks good. If you want to avoid having to add an the event handler to every control you add, you could create a recursive routine to add a GotFocus listener to every control in your form. This will work for any type of control in your form, however you could adjust it to meet your needs.
private void Form_OnLoad(object obj, EventArgs e)
{
AddGotFocusListener(this);
}
private void AddGotFocusListener(Control ctrl)
{
foreach(Control c in ctrl.Controls)
{
c.GotFocus += new EventHandler(Control_GotFocus);
if(c.Controls.Count > 0)
{
AddGotFocusListener(c);
}
}
}
private void Control_GotFocus(object obj, EventArgs e)
{
// Set focused control here
}
Your implementation looks good enough -- what I do want to know is why you want to do this in the first place? Won't it be preferrable for the focus to cycle back to the first entry? Is the data in the last text box so malleable that once they click the button it is "remembered"? Or do you have some sort of operation that the button does to that specifici text box data -- in that case shouldn't the focus go to a subsequent control instead?
I'm interested in finding out why you want to do this in the first place.
Yeah, I admit the requirement is a bit unusual. Some of the information that the users will be entering into this application exists in scans of old documents that are in a couple of different repositories. The buttons facilitate finding and opening these old docs. It's difficult to predict where the users will be on the form when they decide to pull up a document with more information to enter on the form. The intent is to make the UI flow well in spite of these funky circumstances.
Create a class called CustomTextBox that inherits from TextBox. It has a static variable called stack. When the textbox loses focus push onto the stack. When you want to find the last focused control then just pop the first item from the stack. Make sure to clear the static Stack variable.