I want to add MouseOver and MouseLeave events to dynamical created panels in a flowLayoutPanel.
I added all panels in a list named "panels" and they are accessible with "panels[index]".
Now I want to dynamical add a MouseOver and MouseLeave event to each panel.
I thought it could be possible to get the panelname the Mouse is over and use just one method for each event and identify the panel the mouse is over with its panelname (panel.Name) but I found nothing in "sender".
Is there a way to do this?
My code:
//Method
private void PanelsMouseEnter(object sender, EventArgs e)
{
var panel = sender as Control;
foreach (Control control in this.fLpKoerper.Controls)
{
if (control.Name == panel.Name)
{
foreach (Panel panels in panelsKoerper)
{
if (panels.Name == panel.Name)
panels.BackColor = Color.DarkGray;
}
}
}
}
//Event
panelsKoerper[y].MouseEnter += PanelsMouseEnter;
var panel = sender as Control;
var thePanelName = panel.Name;
I believe you can generate one mouseover event for a control, copy that event method name and then paste it into another controls mouseover event box and that should work
So you would have this event
private void label1_MouseHover(object sender, EventArgs e)
{
//Code...
}
and then you could put 'label1_MouseHover' in any controls mouseover event
Related
I created a control (called Table) made up by two pictureBoxes and two Labels.
I'm trying to drag and drop it from a panel to another, but it doesn't work.
This is my code:
void TableExampleMouseDown(object sender, MouseEventArgs e)
{
tableExample.DoDragDrop(tableExample, DragDropEffects.Copy);
}
void Panel2DragEnter(object sender, DragEventArgs e)
{
e.Effect = DragDropEffects.Copy;
}
void Panel2DragDrop(object sender, DragEventArgs e)
{
panel2.Controls.Add((Table) e.Data.GetData(e.Data.GetFormats()[0]));
}
Obviously I've set AllowDrop to true in panel2. Already when I click on Table object (which is in panel1), the mouse cursor doesn't change. It looks like the MouseDown event doesn't fire...
Thank you!
This is the part of the constructor code in which I subscribe Handlers:
this.tableExample.MouseDown += new System.Windows.Forms.MouseEventHandler(this.TableExampleMouseDown);
this.label2.MouseDown += new System.Windows.Forms.MouseEventHandler(this.Label2MouseDown);
this.panel1.DragDrop += new System.Windows.Forms.DragEventHandler(this.Panel1DragDrop);
this.panel1.DragEnter += new System.Windows.Forms.DragEventHandler(this.Panel1DragEnter);
You seem to have forgot to subscribe to the MouseDown event. Simply writing an event hanlder isn't enough.
Put this in the Form_Load event handler or in the form's constructor:
tableExample.MouseDown += new MouseEventHandler(TableExampleMouseDown);
For more information refer to the documentation: How to: Subscribe to and Unsubscribe from Events - Microsoft Docs.
EDIT:
It could also be that you press one of the child controls of your custom control. Child controls have their own MouseDown events.
To make the child controls also raise the parent control's MouseDown event put this in the constructor of your custom control:
MouseEventHandler mouseDownHandler = (object msender, MouseEventArgs me) => {
this.OnMouseDown(me);
};
foreach(Control c in this.Controls) {
c.MouseDown += mouseDownHandler;
}
EDIT 2:
Based on the new code you added to the question you seem to have forgotten to subscribe to the events for panel2:
this.panel2.DragDrop += new System.Windows.Forms.DragEventHandler(this.Panel2DragDrop);
this.panel2.DragEnter += new System.Windows.Forms.DragEventHandler(this.Panel2DragEnter);
I'm trying to apply focus behavior, similar to button blue border to FlowLayoutPanel. I tried to use GotFocus and LostFocus, but clearly that's not the way to go.
private void FlowLayoutPanel_Click(object sender, EventArgs e)
{
(sender as Control).BackColor = SystemColors.GradientActiveCaption;
//More operations.
}
private void Panel_LostFocus(object sender, System.EventArgs e)
{
(sender as Control).BackColor = default(Color);
//More operations.
}
While clicking on the FlowLayoutPanel nothing happens and while using tab the two event are invoked one after another.
Any suggestions?
FlowLayoutPanel is not a selectable control by default. You can create a custom flow layout panel by deriving from FlowLayoutPanel and set Selectable and UserMouse control styles to make it selectable by mouse. Also to accept tab stop, set TabStop property to true:
class ExFlowLayoutPanel:FlowLayoutPanel
{
public ExFlowLayoutPanel():base()
{
SetStyle(ControlStyles.Selectable, true);
SetStyle(ControlStyles.UserMouse, true);
TabStop = true;
}
}
Then you can handle GotFocus and LostFocus or Enter and Leave events.
The only point of using a FLP is to get it to arrange child controls. It is always a child control that gets the focus, not the FLP. So sure, nothing happens. You'd have to subscribe the Enter events of all the child controls to see the focus entering the panel or one of its children. Leave is much harder to get right, that's going to flicker like a cheap motel.
Very ugly solution, you don't want to it that way. Use the Application.Idle event instead, the best alternative when getting a reliable event just isn't practical. Check the Parent of this.ActiveControl, like this:
public Form1() {
InitializeComponent();
Application.Idle += CheckFlpFocus;
this.Disposed += delegate { Application.Idle -= CheckFlpFocus; };
}
private bool FlpHasFocus;
private void CheckFlpFocus(object sender, EventArgs e) {
bool hasFocus = false;
for (var ctl = this.ActiveControl; ctl != null; ctl = ctl.Parent) {
if (ctl == flowLayoutPanel1) hasFocus = true;
}
if (hasFocus != FlpHasFocus) {
FlpHasFocus = hasFocus;
flowLayoutPanel1.BackColor = hasFocus ? Color.Black : Color.White;
}
}
Im trying to drag a label from a FlowLayoutPanel to another FlowLayoutPanel.Im able to drag but it wont drop the label?
My Code
private void flp_DragEnter(object sender, DragEventArgs e)
{
if ((e.AllowedEffect & DragDropEffects.Link) != 0
&& e.Data.GetDataPresent(typeof(string)))
e.Effect = DragDropEffects.Link;
}
private void flp_DragDrop(object sender, DragEventArgs e)
{
if (e.Data.GetDataPresent(typeof(Label)))
{
FlowLayoutPanel destination = (FlowLayoutPanel)sender;
Control control = (Control)e.Data.GetData(typeof(Label));
destination.Controls.Add(control);
return;
}
}
private void lbl_MouseDown(object sender, MouseEventArgs e)
{
DoDragDrop((sender as Label).Text, DragDropEffects.Link);
}
You can set the Name of the controls as drag data, and then when dropping, find the control by name and remove it from its parent controls collection and add it to target panel controls collection. To do so:
Set AllowDrop property for each control that is target of drop. The target controls in your example can be both FlowLayoutPanel controls.
Handle MouseDown event for each control that drag starts with it and in the handler call DoDragDrop event of that control and set the data that you want to drag. The moving controls in your example are labels and the data here can be Name of control.
Handle DragEnetr event of each target of drag and set e.Effect to determine if drop is allowed or not. Here is the place that you can check if drop is allowed. For example you can check if the data is string and the string is the name of a control.
Hanlde DragDrop and use GetData method of e.Data to get the data and perform the actions when drop. The action here is removing the control from its current parent and add it to the new parent.
Code:
Using the below code, if you assign control_MouseDown to MouseDown events of all labels and assign panel_DragEnter to DragEnter event of both flow layout panels and also assign panel_DragDrop to DragDrop event of both flow layout panels, you can move labels between both flow layout panels, also you can re order labels in a panel:
private void control_MouseDown(object sender, MouseEventArgs e)
{
var control = sender as Control;
this.DoDragDrop(control.Name, DragDropEffects.Move);
}
private void panel_DragEnter(object sender, DragEventArgs e)
{
if (!e.Data.GetDataPresent(typeof(string)))
return;
var name = e.Data.GetData(typeof(string)) as string;
var control = this.Controls.Find(name, true).FirstOrDefault();
if (control != null)
{
e.Effect = DragDropEffects.Move;
}
}
private void panel_DragDrop(object sender, DragEventArgs e)
{
if (!e.Data.GetDataPresent(typeof(string)))
return;
var name = e.Data.GetData(typeof(string)) as string;
var control = this.Controls.Find(name, true).FirstOrDefault();
if (control != null)
{
control.Parent.Controls.Remove(control);
var panel = sender as FlowLayoutPanel;
((FlowLayoutPanel)sender).Controls.Add(control);
}
}
so I have my control which I would like to expand on touch and show my button which is nested within the data template of the control. I would then like the button to be pressable but would also like the control to collapse if touched anywhere apart from the button
Initialise Control
MyControl mc = new MyControl();
mc.TouchDown += mc_TouchDown;
mc.TouchUp += mc_TouchUp;
Event handlers
void mc_TouchDown(object sender, TouchEventArgs e)
{
var mc = (MyControl)sender;
mc.CaptureTouch(e.TouchDevice);
}
void mc_TouchUp(object sender, TouchEventArgs e)
{
var mc = (MyControl)sender;
if (mc != null && e.TouchDevice.Captured == mc)
{
//Expand and show button / Collapse and hide button
mc.ReleaseTouchCapture(e.TouchDevice);
}
}
Now the button is in the data template of MyControl and is hooked up to a command and when i touch the button to run the command MyControl touch events are being fired and the button tap gets ignored.
How do I make it so that the touch events on MyControl work but when the button is shown and touched the button touch event takes priority over the MyControl event?
So I was using Command for my button but I changed this to use the TouchDown event instead and had
private void addToDiary_TouchDown(object sender, TouchEventArgs e)
{
//do my thing
e.Handled = true;
}
and this meant the button was executed and the event didn't bubble up to MyControl
Try to set e.Handled = true for TouchEventArgs to prevent a bubbling of event.
I have created a custom control that gets highlighted when the mouse hovers over it. The custom control also has a checkbox. When the mouse goes over the checkbox, the highlighting of the custom control does not occur. I've tried using WS_EX_TRANSPARENT on the checkbox but it isn't working for me.
int cbStyle = GetWindowLong(CompletedCheckBox.Handle, GWL_EXSTYLE);
SetWindowLong(CompletedCheckBox.Handle, GWL_EXSTYLE, cbStyle | WS_EX_TRANSPARENT);
How can I do this?
Thanks
Transparent only affects drawing, not mouse events. The check box is getting the mouse events, this in turn means that when you mouse over the checkbox, your control receives a MouseLeave event. To ensure that the background color changes, even when a child control ( at any level) gets a MouseEnter event, you need to track that a control of interest -- or any child, grand-child ..etc-- has the mouse over it. To do this, recurse through all descendant controls and intercept the appropriate events for them. To do this, try something similar to the class below.
public partial class MyControl : UserControl
{
public MyControl()
{
InitializeComponent();
AttachMouseEnterToChildControls(this);
}
void AttachMouseEnterToChildControls(Control con)
{
foreach (Control c in con.Controls)
{
c.MouseEnter += new EventHandler(control_MouseEnter);
c.MouseLeave += new EventHandler(control_MouseLeave);
AttachMouseEnterToChildControls(c);
}
}
private void control_MouseEnter(object sender, EventArgs e)
{
this.BackColor = Color.AliceBlue;
}
private void control_MouseLeave(object sender, EventArgs e)
{
this.BackColor = SystemColors.Control;
}
}