Detecting Mouse Click on an Array of Controls - c#

I'm adding an array of Panel objects (which in turn contain other items) to a form at runtime. Then, I'm assigning a click event to each panel inside a loop like so:
pnlInstrument[index].Click += pnlInstrument_Click;
The empty click function looks like this:
private void pnlInstrument_Click(object sender, EventArgs e)
{
}
The event is triggering correctly, but how can I tell which panel was clicked?

Use the sender parameter of the event method..
private void pnlInstrument_Click(object sender, EventArgs e)
{
Panel panel = (sender as Panel); //This is the panel.
}
Edit: For comments of getting index..
private void pnlInstrument_Click(object sender, EventArgs e)
{
Panel panel = (sender as Panel); //This is the panel.
int panelIndex = Array.IndexOf(pnlInstrument, panel);
}

Why not:
pnlInstrument[index].Click += pnlInstrument_Click;
pnlInstrument[index].Tag += index;
private void pnlInstrument_Click(object sender, EventArgs e)
{
Panel pnl = (Panel)sender;
int index = (int)pnl.Tag;
}

Related

Refer to parent using MouseEnter() event? (or any other events)

I have a pictureBox, the MouseEnter() event performs as follows:
private void PictureBox_pictureBox_MouseEnter(object sender, EventArgs e)
{
pictureBox.Load("..\\Debug\\Images\\highlightbutton");
pictureBox.Cursor = Cursors.Hand;
}
I want to have multiple pictureBoxes, which all refer to the same function named PictureBox_pictureBox_MouseEnter() as shown above. Is it possible to refer to the pictureBox dependant on which one is clicked? Something like this:
private void PictureBox_pictureBox_MouseEnter(object sender, EventArgs e)
{
Parent.Load("..\\Debug\\Images\\highlightbutton");
Parent.Cursor = Cursors.Hand;
}
The sender parameter is a reference to the control that raised the event:
private void PictureBox_pictureBox_MouseEnter(object sender, EventArgs e)
{
var pictureBox = sender as PictureBox;
pictureBox.Load("..\\Debug\\Images\\highlightbutton");
pictureBox.Cursor = Cursors.Hand;
}

Tab Control blocking mouse scroll event C#

I have a tab control that contains multiple tab controls. All of the tab controls were made using the winforms designer. The embedded tab controls each have Chart objects assigned them. These were created after the program was ran, and each chart was given three events:
chart.MouseWheel += new MouseEventHandler((sender, e) => this.Chart_MouseWheel(sender, e, chart, raw, condensed, bounds));
chart.MouseHover += new EventHandler(Chart_Hover);
chart.MouseClick += new MouseEventHandler((sender, e) => this.Chart_Click(sender, e, chart));
For easy debugging, I added a simple Console.WriteLine(); to each method to see which methods were actually being fired.
private void Chart_MouseWheel(object sender, MouseEventArgs e, Chart chart, DataTable raw, DataCondenser condensed, List<double> bounds)
{
Console.WriteLine("a");
}
private void Chart_Hover(object sender, EventArgs e)
{
Console.WriteLine("b");
}
private void Chart_Click(object sender, MouseEventArgs e, Chart chart)
{
Console.WriteLine("c");
}
After hovering, clicking, and scrolling a lot, I can only get b and c to be outputted. For some reason the scroll event will not be picked up. I have a feeling this has to do with being inside a tab control.
Any ideas why this is happening?
EDIT:
Tried a small-scale version of this and the same thing is happening.
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
Chart test = new Chart();
test.Width = 500;
test.Height = 500;
test.MouseWheel += new MouseEventHandler(Chart_Scroll);
test.MouseHover += new EventHandler(Chart_Hover); //mousehover event for the tooltip to activate
test.MouseClick += new MouseEventHandler(Chart_Click);
tabPage3.Controls.Add(test);
}
private void Chart_Scroll(object sender, MouseEventArgs e)
{
Console.WriteLine("a");
}
private void Chart_Hover(object sender, EventArgs e)
{
Console.WriteLine("b");
}
private void Chart_Click(object sender, MouseEventArgs e)
{
Console.WriteLine("c");
}
The same issue occurred. tabPage3 was a tabpage of a tabcontrol inside of a tab control.
EDIT 2:
so if I give the chart this event handler:
test.MouseEnter += new EventHandler(mouseEnter);
with the method:
private void mouseEnter(object sender, EventArgs e)
{
this.Focus();
}
it still doesn't work. However, if I use this:
private void mouseEnter(object sender, EventArgs e)
{
if (sender is Chart)
{
Chart temp = (Chart) sender;
temp.Focus();
}
}
It will work, even if it's embedded in other controls.
You could wire up the MouseEnter() event and give the Chart focus with a one-liner like this:
test.MouseEnter += (s, evt) => { ((Control)s).Focus(); };

Double Click on label open Form C#

Im trying to open a new form when a label is double clicked. Im able to drag and drop the label .Im trying to open a new form on double click of label now.
private void control_MouseDown(object sender, MouseEventArgs e)
{
var control = sender as Control;
this.DoDragDrop(control.Name, DragDropEffects.Move);
}
private void control_DoubleClick(object sender, EventArgs e)
{
frm = new Frm();
frm.ShowDialog();
frm.Dispose();
}
EDIT 1:
I have tried both possible answers below, and they have not worked for me?
A more cleaner way is (note I changed Frm to Form1):
private void control_DoubleClick(object sender, EventArgs e)
{
using (Form1 frm = new Form1())
{
frm.ShowDialog();
}
}
You can't add DragDrop on MouseDown and then DoubleClick. That won't work.
I don't think there's an easy way to get around that, but once a control is being dragged, it won't respond to double click messages.
I've made some quick tests, and there's a "hacky" way. It'll make your dragging look weird (since it'll start after some time, instead of immediately after you press the mouse button), but here it goes:
private bool _willDrag = false;
private bool control_MouseUp(object sender, MouseEventArgs e)
{
// disable dragging if we release the mouse button
_willDrag = false;
}
private bool control_DoubleClick(object sender, EventArgs e)
{
// disable dragging also if we double-click
_willDrag = false;
// .. the rest of your doubleclick event ...
}
private void control_MouseDown(object sender, MouseEventArgs e)
{
var control = sender as Control;
if (control == null)
return;
_willDrag = true;
var t = new System.Threading.Timer(s =>
{
var callingControl = s as Control;
if (callingControl == null)
return;
// if we released the mouse button or double-clicked, don't drag
if(!_willDrag)
return;
_willDrag = false;
Action x = () => DoDragDrop(callingControl.Name, DragDropEffects.Move);
if (control.InvokeRequired)
control.Invoke(x);
else
x();
}, control, SystemInformation.DoubleClickTime, Timeout.Infinite);
}
In the form.Designer right click on your label then properties, in the properties window click in events (the thunder icon), in the double_Click event dropdown select the event handler (control_DoubleClick) this method must have two parameters an object and a eventArgs
This is tricky as the DoDragDrop will eat up any further mouse events, and MSDN posting a rather stupid example doesn't help much.
Solution: Do not start the D&D in the MouseDown if you want to still receive click or double click events but use the MouseMove instead:
Replace this
private void control_MouseDown(object sender, MouseEventArgs e)
{
var control = sender as Control;
this.DoDragDrop(control.Name, DragDropEffects.Move);
}
by this:
private void control_MouseMove(object sender, MouseEventArgs e)
{
if (e.Button == System.Windows.Forms.MouseButtons.Left)
DoDragDrop((sender as Control), DragDropEffects.Move);
}
Don't forget to hook up the new event!

Set off an Event in case any one of a group of radiobutton gets checkchanged

Situation is as follows:
I have a ButtonA, which is currently not enabled.
I have 5 Radiobuttons of which one is always checked.
I want to enable ButtonA when a different Radiobutton gets selected.
I thought about doing something like
private void RadioButton1_CheckedChanged(object sender, EventArgs e)
{
ButtonA.Enabled = true;
}
private void RadioButton2_CheckedChanged(object sender, EventArgs e)
{
ButtonA.Enabled = true;
}
... and so on.
There is probably a more elegant solution and im missing it.
You can use a single method as an event handler for all radiobuttons:
private void RadioButtonChanged(object sender, EventArgs e)
{
ButtonA.Enabled = true;
}
private void HandleEvents()
{
this.RadioButton1.CheckedChanged += RadioButtonChanged;
this.RadioButton2.CheckedChanged += RadioButtonChanged;
this.RadioButton3.CheckedChanged += RadioButtonChanged;
}
Or a loop to do the same thing:
private void RadioButtonChanged(object sender, EventArgs e)
{
ButtonA.Enabled = true;
}
private void HandleEvents()
{
foreach(var rb in new[] {RadioButton1, RadioButton2, RadioButton3})
rb.CheckedChanged += RadioButtonChanged;
}
Or even a lambda event handler set in a loop:
private void HandleEvents()
{
foreach(var rb in new[] {RadioButton1, RadioButton2, RadioButton3})
rb.CheckedChanged += (o,e) => ButtonA.Enabled = true;
}
How about just having 1 event handler like this:
private void RadioButton_CheckedChanged(object sender, EventArgs e)
{
ButtonA.Enabled = true;
}
Then you can use the form designer to assign this method name to the CheckedChanged events of all the radio buttons.
This will save you having to repeat the code for each radio button.
Another trick is to add all your radio buttons to a group box or panel in the designer, then they will all be children of that control.
Then you can add the following code to your Load event handler for the form:
foreach(var radioButton in radioGroupBox.Controls.Cast<Control>()
.Where(i => i is RadioButton)
.Cast<RadioButton>())
{
radioButton.CheckedChanged += RadioButton_CheckedChanged;
}
This way, if you add more RadioButtons to the group, you don't need to change any code.

c# Superposed control doesn't fire events

My Windows Forms code has two superposed PictureBoxes: a small X on the top corner of a user-loaded image. I'll call them DelImage and Image, respectively. Like this:
http://imgur.com/fsW7R8i
The DelImage appears (Visible = true) on Image_MouseEnter and disappears on Image_MouseLeave. Now, I want the DelImage to have a custom behavior as well when the mouse enters it, but DelImage never fires events (nor MouseEnter, nor MouseLeave, nor Click). I've tried bringing it to front, but it already is in front of the Image.
Here's some code:
private void picImage_MouseEnter(object sender, EventArgs e)
{
delImage.Visible = true;
}
private void picImage_MouseLeave(object sender, EventArgs e)
{
delImage.Visible = false;
}
private void picDelImage_MouseEnter(object sender, EventArgs e)
{
delImage.Visible = true;
this.Cursor = Cursors.Hand;
}
private void picDelImage_MouseLeave(object sender, EventArgs e)
{
this.Cursor = Cursors.Arrow;
}
private void picDelImage_Click(object sender, EventArgs e)
{
Panel currentPanel = this.tlpImages.Controls["pnlImage"] as Panel;
currentPanel.Visible = false;
}
With this code, the picDelImage events are never reached. I never enter DelImage, apparently because I never leave Image. What can I do to make my PictureBoxes have the expected behavior?

Categories

Resources