Which control has been clicked? - c#

I have a problem with MouseEvents on my WinForm C# application. I want to get ALL mouse clicks on my application.
How to determine which control has been clicked ?(I'm beginner C#)

Try this:
private void Control_Clicks(object sender, EventArgs e)
{
Control control = (Control)sender; // Sender gives you which control is clicked.
MessageBox.Show(control.Name.ToString());
}
This, this or this may help.
Hope it helps.

private void Form1_Load(object sender, EventArgs e)
{
SetupClickEvents(this);
}
/// <summary>
/// This will loop through each control within the container and add a click handler to it
/// </summary>
/// <param name="container">The container whose children to handle clicks for</param>
private void SetupClickEvents(Control container)
{
foreach(Control control in container.Controls)
{
control.Click += HandleClicks;
}
}
private void HandleClicks(object sender, EventArgs e)
{
Control control = (Control)sender;
MessageBox.Show(string.Format("{0} was clicked!", control.Name));
}

If you're doing Windows Forms, you have several options :
Hook mouse event, and after figure out if the clicked component actually makes part of your application
You can declare a base class MyComponent : Control. That component overrides MousClick event and raise a special event notifying about a fact. Every control in your app derive from that control, so every control will notify about click happened on it. It's enough to subcribe
to thier events and process them as requested.
Just a couple of ideas...

You'd have to wire them all up to the same event handler. This can be done in the properties window for the controls in question. You could also write your own function to traverse the control tree and tie the function to each of their event handlers.
You can recursively traverse the Form.Controls collection with a foreach loop.
void attachGlobalHandler(Control aToParse, EventHandler aGlobalHandler)
{
foreach(Control lControl in aToParse.Controls)
{
attachGlobalHandler(lControl, aGlobalHandler);
lControl.Click += aGlobalHandler;
}
}
And then you call that on your form, with the name of the function you want to call:
attachGlobalHandler( Form1, myClickHandler );
And that should tie it to EVERY clickable control on the form. The sender argument of the handler should then always refer to the control that fired the event. That being said, I'd probably just attach individual event handlers, unless you need to treat multiple controls as a group.
WARNING: The code above is untested.

For the second question asked "How to determine which control has been clicked?" each control has events which may be handled in code.
The easiest way to know when a control has been clicked is to attached to the clicked event of a control which is done from the properties for the control. You may have to click the lightning bolt icon to see the events. Double-clicking beside the even will create an empty handler.
For example if you had a simple form with a single button attaching click events to the form and to the button will tell you when there is a click anywhere. In most cases the button click would be the most useful to handle.
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_Click(object sender, EventArgs e)
{
}
private void button1_Click(object sender, EventArgs e)
{
}
}

It's really simple!
On your click event in your Win-Form, You add
// Here is a modified version of your code:
private void Form1_Click(object sender, EventArgs e)
{
var control = Form1.ActiveControl;
}

Related

Windows Forms click event not fired when clicking on label?

I have Windows Form TestForm, and in my Form I have several labels that are only used to display some text.
I need to display a MessageBox.Show anytime the Form is clicked. So I have an event handler for the click, which looks like this:
private void TestForm_Click(object sender, EventArgs e)
{
MessageBox.Show("The form has been clicked");
}
Unfortunately, the click event doesn't fire when I click over a label in the Form. Is there a way to fix this, besides consuming the click event for the labels?
Thanks.
To use the same click event for all labels:
In the properties for each label, go to the Events (lightning bolt tab).
You will see (probably near the top) a label for Click, click the dropdown for this event, and you will be shown a list of handlers that you could use for that label.
Here's the Properties > Events > Click handler (bottom right):
Because all of your labels are of the same type, and produce the same EventArgs, you are able to use the same handler for all of them.
Then, when you are adding more Labels, just choose the event handler from the Click event dropdown:
Hope this helps!
To flesh out LarsTech's comment, I have used something like this in the past when I was having problems with labels overlapping each other and lack of true transparency in WinForms. What I did was make the labels invisible on the Form, then iterate through them in the Form's paint event, pull the information out of them and then use Graphics.DrawString to draw the text. That way you you will still be able see them in design mode.
This is a quick example of what I mean.
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_Paint(object sender, PaintEventArgs e)
{
foreach (var temp in this.Controls)
{
if (temp is Label) //Verify that control is a label
{
Label lbl =(Label)temp;
e.Graphics.DrawString(lbl.Text, lbl.Font, new SolidBrush(lbl.ForeColor), new Rectangle(lbl.Location, lbl.Size));
}
}
}
private void Form1_Click(object sender, EventArgs e)
{
MessageBox.Show("The Form has been clicked");
}
}

Why my custom event fires twice?

I've searched relevant posts but I got nothing much
I have created a user control. In my user control there is a text box. I want to have an event in my user control that fires whenever text box TextChanged event raises. This is what I have done so far : (This is code of user control)
public event EventHandler txtchnged;
public void ontxtchnged()
{
txtchnged(this, EventArgs.Empty);
}
public MyTextBox()
{
InitializeComponent();
textBox1.TextChanged += textBox1_TextChanged;
}
private void textBox1_TextChanged(object sender, EventArgs e)
{
ontxtchnged();
}
Here is where I have used user control
public RegisterMainFrm()
{
InitializeComponent();
myUserControl1.txtchnged += myUserControl1_txtchnged;
}
private void myUserControl1_txtchnged(object sender, EventArgs e)
{
Console.WriteLine("hello");
}
This works and I know that the code might not be clean but that's not the problem. Problem is : "hello" will be printed in console twice and I really don't know why and how to fix it.
From MSDN on TextBox.TextChanged:
Note:This event fires when the TextBox control is created and
initially populated with text.
Could this be your problem that you get the initial event?
UPDATE:
From Adriano Repetti Hint in Comments: Did you get the textBox1_TextChanged event handler by double clicking in the designer?
Then you have added a second hook to the TextChanged Event.
Check the code inside InitializeComponent of your UserControl if it is already hooking the event.

Update listBox on Main page from button click event on child window.

I have a Main page that contains a listBox.
When a user selects a profile form the list box, this opens up a child window called pWindow.
This window as the option to delete the current profile via a hyperlink button that opens up a another confirmation window called dprofile.
My question being is it possible that once a user has confirmed to delete the current profile they are in, and confirmed it in the button click on dProfile, how can I update the listBox in the first Main page so that the list no longer contains the deleted profile (which it is not doing at present.
In the dProfile window I have created an event -
public event EventHandler SubmitClicked;
Where in the OK button click I have-
private void OKButton_Click(object sender, RoutedEventArgs e)
{
if (SubmitClicked != null)
{
SubmitClicked(this, new EventArgs());
}
}
So on the Main page I have added-
private void deleteProfile_SubmitClicked(object sender, EventArgs e)
{
WebService.Service1SoapClient client = new WebService.Service1SoapClient();
listBox1.Items.Clear();
client.profileListCompleted += new EventHandler<profileListCompletedEventArgs>(client_profileListCompleted);
client.profileListAsync(ID);
}
I thought this may have updated the listBox as it was confirmed in the dProfile form however when the form closes, the listBox stays the same and I have to manually refresh the webpage to see the update. How can I do this?
If I understood it correctly then you have three pages. Main, pWindow and dProfile. Earlier you were trying to close pWindwow from dProfile and that was working properly. Now you want to refresh the listBox1 on Main Page.
To achieve that you may follow a similar strategy. You are probably opening pWindow from Main page with something on the following line
pWindow pWin = new pWindow();
pWin.Show();
Now you may define a new event in pWindow class.
public event EventHandler pWindowRefeshListBox;
Then in your event handler for deleteProfile_SubmitClicked you may raise the event to refresh listbox1, something on the following line:
private void deleteProfile_SubmitClicked(object sender, EventArgs e)
{
if(pWindowRefreshListBox != null)
pWindowRefreshListBox(this, new EventArgs());
this.Close();
}
Then in your main page register the event against pWin object, which you defined earlier.
pWin.pWindowRefreshListBox += new new EventHandler(pWindow_pWindowRefreshListBox);
Then define the event in Main page.
private void pWindow_pWindowRefreshListBox(object sender, EventArgs e)
{
listBox1.Items.Clear();
}
This should refresh the listbox. I haven't test the code or the syntax. So you may check it
before implementing.
EDIT
you may define the event in dProfile as static
public static event EventHandler SubmitClicked;
Then you will be able to register it in Main and pWindow against Class Name
dProfile.SubmitClicked += new ..............
Then implement it accordingly, in pWindow, close the window and in main refresh listbox
EDIT:
You may create instance of deleteProfile on the main page register the following in your main
deleteProfile.SubmitClicked += new EventHandler(deleteProfile _SubmitClicked)
this should work

How to Call an Event of Control that is present inside a Custom Control?

I have a Custom Cntrol that has a button inside it. Now I want to access the button click from my Application Page.
Take a look at this Post:
How to Access a Button present inside a Custom Control, from the implementing page?
You have 2 ways:
You can access the button's click event through the user control object. For eg.
MyUC.button1.click += //etc
You can create your custom event of that specific button click in the user control. For example, in your usercontrol, you have:
public delegate void OnButtonClick(object sender, EventArgs e);
public event OnButtonClick Button1Click;
button1_click(object sender, EventArgs e)
{
if(Button1Click != null)
Button1Click(this, e);
}
Then you watch for that event on your user control:
MyUC.Button1Click += //etc.

How do I set a click event for a form?

I have a c# form (let's call it MainForm) with a number of custom controls on it. I'd like to have the MainForm.OnClick() method fire anytime someone clicks on the form regardless of whether the click happened on the form or if the click was on one of the custom controls. I'm looking for behavior similar to the KeyPreview feature of forms except for mouse clicks rather than key presses.
I recommend creating a base form for the other forms in your application to inherit. Add this code to your base form to create a new event called GlobalMouseClickEventHandler:
namespace Temp
{
public delegate void GlobalMouseClickEventHander(object sender, MouseEventArgs e);
public partial class TestForm : Form
{
[Category("Action")]
[Description("Fires when any control on the form is clicked.")]
public event GlobalMouseClickEventHander GlobalMouseClick;
public TestForm()
{
InitializeComponent();
BindControlMouseClicks(this);
}
private void BindControlMouseClicks(Control con)
{
con.MouseClick += delegate(object sender, MouseEventArgs e)
{
TriggerMouseClicked(sender, e);
};
// bind to controls already added
foreach (Control i in con.Controls)
{
BindControlMouseClicks(i);
}
// bind to controls added in the future
con.ControlAdded += delegate(object sender, ControlEventArgs e)
{
BindControlMouseClicks(e.Control);
};
}
private void TriggerMouseClicked(object sender, MouseEventArgs e)
{
if (GlobalMouseClick != null)
{
GlobalMouseClick(sender, e);
}
}
}
}
This solution will work not only for top-level controls, but also nested controls such as controls placed inside of panels.
In the form's ControlAdded event, add a MouseClick handler to the control, with the Address of the form's click event. I haven't tested this, but it might work.
Private Sub Example_ControlAdded(ByVal sender As Object, ByVal e As System.Windows.Forms.ControlEventArgs) Handles Me.ControlAdded
AddHandler e.Control.MouseClick, AddressOf Example_MouseClick
End Sub
Private Sub Example_MouseClick(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles Me.MouseClick
MessageBox.Show("Click")
End Sub
The only way I've ever managed to do this is to handle the [c]Click[/c] event of every control. I don't believe the event is raised before the control processes it.
In WPF, there are "tunneling" preview events that provide this functionality, but that doesn't really help you in WinForms.
You can hook all the control's events, if you like, and then monitor that way. I assume there is some uber fancy Win32 api way to trap them all, but that is beyond me at the moment.
public Form1()
{
InitializeComponent();
HookEvents();
}
private void HookEvents() {
foreach (Control ctl in this.Controls) {
ctl.MouseClick += new MouseEventHandler(Form1_MouseClick);
}
}
void Form1_MouseClick(object sender, MouseEventArgs e)
{
LogEvent(sender, "MouseClick");
}
// and then this just logs to a multiline textbox you have somwhere on the form
private void LogEvent(object sender, string msg) {
this.textBox1.Text = string.Format("{0} {1} ({2}) \n {3}",
DateTime.Now.TimeOfDay.ToString(),
msg,
sender.GetType().Name,
textBox1.Text
);
}
The output is something like this, showing all the events and who "sent" them up:
14:51:42.3381985 MouseClick (Form1)
14:51:40.6194485 MouseClick (RichTextBox)
14:51:40.0100735 MouseClick (TextBox)
14:51:39.6194485 MouseClick (Form1)
14:51:39.2131985 MouseClick (RichTextBox)
14:51:38.8694485 MouseClick (Button)
HTH.
Catching a click on an open space on the form is easy, but to get a click that's actually on a control, you'll need the cooperation of that control to send it to the form.
One possibility is to place a transparent control over the entire form, and accept clicks onto that, deal with them, and then pass them onto the proper control underneath.
This is a common pattern in development, its called the Observer pattern. There are lots of examples of Observer patterns and c# here is 1 example http://msdn.microsoft.com/en-us/library/ms954621.aspx but have a good google around.

Categories