C# triggering MouseEnter even even if mouse button is held down - c#

I have this problem that event called "MouseEnter" does not fire when mouse button is held down. How could i fix it?

That's by design. You can work around it by using, say, MouseMove:
private void Form1_MouseMove(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
Point pt = TargetControl.PointToClient(Cursor.Position);
Rectangle rc = TargetControl.ClientRectangle;
if (rc.Contains(pt))
{
// do what would be done on MouseEnter
}
}
}
This is not ideal, though - if the mouse button is pressed when the mouse is hovering over another control on the form, then it doesn't appear in the MouseMove event that the button is pressed (as #Hans pointed out, the other control 'Captures' the MouseDown). If that's a problem, then combining the hit test in MouseMove while separately tracking MouseDown and MouseUp on the form should work.

Related

Update trackbar value on mouse wheel

I am using the scroll event but this only update value in label when i click on trackBar and move it right or left. I see that i can move it when i use mouse wheel but this doesn't update value in label just moving it.
private void metroTrackBar1_Scroll(object sender, ScrollEventArgs e)
{
lblVolume.Text = metroTrackBar1.Value.ToString();
}
So my question is:
How I can make trackBar to update value in label when i scroll with mouse wheel?
I found solution, used ValueChanged event instead of Scroll event, this works in both cases, when i move trackBar with mouse wheel or when i drag it with mouse.
private void metroTrackBar1_ValueChanged(object sender, EventArgs e)
{
lblVolume.Text = metroTrackBar1.Value.ToString();
}

Receiving MouseMove events from parent control

I have a WinForm application that has a panel and two buttons inside the panel. I added a mousemove event on my panel and the mousemove function gets called when I move the mouse inside my panel, just like expected.
The problem is, if I press down my mouse button while over a button, the button depresses and if I move my mouse into the panel while still holding down the button, the Panel mousemove function never gets called till I release the mouse button.
Is there a work around for this? And if I'm not being clear, I can try to be more clear.
So it seems that while the button is depressed and the mouse moved back over the underlying panel, the panel's MouseMove event is not fired.
You can capture the pointer position at this time by hooking into the button's MouseMove. BUT, the pointer's position will be relative to the button, not the panel, so you need to add these coordinates to the button's location coordinate:
Point mousePoint;
private void panel1_MouseMove(object sender, MouseEventArgs e)
{
mousePoint = e.Location;
}
private void button1_MouseMove(object sender, MouseEventArgs e)
{
mousePoint = new Point(button1.Location.X + e.Location.X, button1.Location.Y + e.Location.Y);
}

MouseLeave doesn't fire when moving from child control to parent's parent

I have a UserControl that listens to it's own MouseLeave in order to change it's background color and some of it's children visibility.
The children that should lose visibility, also listen their own MouseLeave in order to change their background color.
A scenario in which everything works is this:
Move mouse into UserControl.
Move mouse into Child.
Move mouse out of Child into UserControl.
The problematic scenario is this:
Move mouse into UserControl.
Move mouse into Child.
Move mouse out of Child, not into the UserControl, but directly outside of it.
This scenario happens all the time since the Child is located at the very edge of the UserControl.
Note that not only the UserControl's MouseLeave doesn't fire, but neither does the Child's MouseLeave.
In order to find out whether the mouse has actually left the area in this case, I must listen to MouseEnter of other controls, and then notify the UserControl and Child, but I really want to avoid this solution, since it is ugly and not OOPish.
Also, the Child MUST be located at the very edge of the UserControl, and cannot move.
Can anyone think of a neat solution to the problem?
My tests show this as a working solution. Just requires a custom user control.
public class MyPanel : Panel
{
protected override void OnControlAdded(ControlEventArgs e)
{
e.Control.MouseLeave += DidMouseReallyLeave;
base.OnControlAdded(e);
}
protected override void OnMouseLeave(EventArgs e)
{
DidMouseReallyLeave(this, e);
}
private void DidMouseReallyLeave(object sender, EventArgs e)
{
if (this.ClientRectangle.Contains(this.PointToClient(Control.MousePosition)))
return;
base.OnMouseLeave(e);
}
}
I've seen the same behavior before. Is your .NET version up-to-date? Be sure you're on the latest service packs.
Have you seen the event Application.AddMessageFilter? I used that in an answer here to catch mouse messages and handle them more intelligently. It might come in handy here.
This isn't how MouseLeave is supposed to behave. You should get the MouseLeave event even if the mouse cursor moves our of your application window entirely.
I'm guessing you're not calling the base method in your MouseLeave handler.
Anyway, on MouseEnter you can set a timer that fires every 0.25 second, and in it check if the mouse is still over the control. If it isn't, kill the timer and change the control's color.

How can I make an imitation of a button control with a picture box, that behaves exactly like a button?

Buttons do that: if the user preses and holds he left mouse button over a button control and moves the cursor out of the control, the button control changes it's appearance back to default, and if the mouse button is still being held, and the cursor enters a button control, the control changes it's appearance to it's pressed version. I'm trying to imitate a button using a PictureBox, but when the mouse leaves the PictureBox before the left mouse button is released, the PictureBox's picture doesn't change until the mouse button is released.
I'm trying to do this because the button control can't look the way I want to.
How can I make an imitation of a button control with a picture box, that behaves exactly like a button?
This is by design, the control sets the Capture property to true so it will keep receiving mouse messages while the button is held down when you move the mouse outside of the control rectangle.
You could turn it off when you see it moving out:
private void pictureBox1_MouseMove(object sender, MouseEventArgs e) {
var box = (PictureBox)sender;
if (!box.DisplayRectangle.Contains(e.Location)) box.Capture = false;
}
Try using the DragLeave event as opposed to the MouseLeave event.

How can I detect a held down mouse button over a PictureBox?

I need to fire an event when the mouse is above a PictureBox with the mouse button already clicked and held down.
Problems:
The MouseDown and MouseEnter event handlers do not work together very well.
For instance once a mouse button is clicked and held down, C# will fire the MouseDown event handler, but when the cursor moves over the PictureBox the MouseEnter event does not fire, until the mouse button is realeased.
When the mouse is pressed down most controls will then Control.Capture the mouse input. This means that all MouseMove events are sent to the original control that captured rather than the control the mouse happens to be over. This continues until the mouse loses capture which typically happens on the mouse up.
If you really need to know when the mouse is over your control even when another control has captured mouse input then you only really have one way. You need to snoop the windows messages destined for other controls inside your application. To do that you need add a message filter ...
Application.AddMessageFilter(myFilterClassInstance);
Then you need to implement the IMessageFilter on a suitable class...
public class MyFilterClass : IMessageFilter
{
public bool PreFilterMessage(ref Message m)
{
if (m.Msg == WM_MOUSEMOVE)
// Check if mouse is over my picture box!
return false;
}
}
Then you watch for mouse move events and check if they are over your picture box and do whatever it is you want to do.
Mouse events
Use the MouseDown event to just detect a down press of a mouse button and set this.Capture to true so that you then get other mouse events, even when the mouse leaves the control (i.e. you won't get a MouseLeave event because you captured the mouse). Release capture by setting this.Capture to false when MouseUp occurs.
Just checking the state of the mouse
This may not be relevant, but you can check System.Windows.Control.MousePosition and see if it is in the PictureBox.ClientRectangle, then check the Control.MouseButtons static property for which buttons might be down at any time.
As in:
if (pictureBox.ClientRectangle.Contains(pictureBox.PointToClient(Control.MousePosition)))
{
if ((Control.MouseButtons & MouseButtons.Left) != 0)
{
// Left button is down.
}
}
Set up a MouseMove event within the PictureBox control:
this.myPictureBox.MouseMove += new System.Windows.Forms.MouseEventHandler(this.myPictureBox_MouseMove);
Then, within your MouseMove event handler, check to see if the left mouse button (or whatever) is pressed:
private void myPictureBox_MouseMove(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
// Do what you want to do
}
If you're trying to implement a drag-and-drop operation of some sort, the Drag... events (DragEnter, DragDrop etc.) on the receiving picture box are what you want to use. Basically, you start the drag operation using the DoDragDrop method of the source control, and then any control that you drag over will have its Drag... events raised.
Search "DoDragDrop" on MSDN to see how to implement this.
You can use the Preview Events
For example say I want to detect a mousedown event on my button. The MouseDown event is not going to work because as one of the answers here, the mouse capture is sent to the main control, however what you can do is use the mouse preview event.
Here is a code example
I want to check when the Left Mouse Button is pressed on my Button, hence I use the PreviewMouseLeftButtonDown
private void MyButton_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
// code here
}
WPF has preview events for alot of other events, you can read about them here
Preview Events - It particular talks about Buttons and how the mouse events interacts with it, So I highly recommend you read it
The best way to move a Form based on mouse position and control relative position is similar to what Ian Campbell posted.
private void imgMoveWindow_MouseMove(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
Form1.ActiveForm.Left = Control.MousePosition.X - imgMoveWindow.Left - (imgMoveWindow.Size.Width/2);
Form1.ActiveForm.Top = Control.MousePosition.Y - imgMoveWindow.Top - (imgMoveWindow.Size.Height/2);
}
}
Where imgMoveWindow is a PictureBox Control.
Bruno Ratnieks
Sniffer Networks
You should try MouseMove of the picture box instead of MouseEnter, MouseMove will normally fire regardless mouse button state.
set a flag or a state on mouse down. release it on mouse up.
When on mouse over fires for the picture box check your state.
Now you can detect when a person is dragging something.

Categories