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.
Related
I would like to highlight the hovered item when dragging the item inside ListBox
I find one related question here, but when mouse is pressed, the MouseMove and MouseLeave event stop working.
When the mouse is captured by another control, mouse event's like MouseMove will not raise for the drop target control.
Regardless of the mouse capture, you always can find the hot index using the following code:
var index = listBox1.IndexFromPoint(listBox1.PointToClient(Cursor.Position));
If the mouse enter/move/leave events during the drag is important for you, use drag events DragEnter, DragOver and DragLeave events.
For example, to get the index of the item under the mouse pointer when the mouse is dragging over the target listbox, you can handle DragOver:
private void listBox1_DragOver(object sender, DragEventArgs e)
{
var index = listBox1.IndexFromPoint(listBox1.PointToClient(Cursor.Position));
}
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.
This is probably a n00b query. I have a need where I want to change the trackbar value based on a mouse down event. This I achieved as follows:
private void MoveTrackBarToMouseClickLocation(TrackBar a_tBar, int a_mouseX)
{
// Jump to the clicked location
double dblValue;
dblValue = ((double)a_mouseX / (double)a_tBar.Width) * (a_tBar.Maximum - a_tBar.Minimum);
a_tBar.Value = Convert.ToInt32(dblValue);
}
That part works fine. I am having trouble getting the scroll working while the mouse button is pressed. e.g. If I click on the trackbar and it takes me to say value 50 with the mouse down, I want to be able to scroll right or left (from value=50) while that mouse is down.
I hope I have made my small issue clear.
Any help is appreciated.
Thanks
You need to execute your code in the MouseMove event, as well as the MouseDown event.
This event occurs when the mouse is moved while one of the buttons is held down. In contrast, the MouseDown event that you currently handle only gets raised once each time the mouse button is pressed down. That's why the TrackBar is not moving when the user moves the mouse, but is working properly the first time the button is pressed.
You didn't show the code where you wired up the event handlers and/or call the MoveTrackBarToMouseClickLocation function, so that's as specific as I can get. But if you managed to wire up the MouseDown event already, this should be a simple fix.
I have a windows form in a wpf window, and I'm trying to use DragMove when I click on the windows form, it's a picturebox so I want to be able to drag the window around just by clicking the picture.
I catch my form's mouse down, and raise the wpf window's mouseleftbuttondown event with:
if (e.Button == MouseButtons.Left)
{
MouseDevice mouseDev = InputManager.Current.PrimaryMouseDevice;
MouseButtonEventArgs mouseEvent = new MouseButtonEventArgs(mouseDev, 0, MouseButton.Left)
{
RoutedEvent = MouseLeftButtonDownEvent
};
RaiseEvent(mouseEvent);
}
However whenever I check the InputManager.Current.PrimaryMouseDevice from my handler (or my form's MouseMove handler), the LeftButton's state is "released".
Why is this? I can't figure out a way to force it to be "pressed" since all the properties are read-only.
Or is my approach simply wrong and is not possible? I did also try setting the location of my window on mouse move, but some weird stuff happens where my mouse values keep going back to the previous position.
Thanks!
edit: So I'm manually adjusting the window location, but still hope someone can enlighten me as to why MouseDevice doesn't get pressed on a windows form. The "weird stuff happens..." was just a dumb mistake on my part, I kept resetting the mouse coordinates on mouse move, but realized that my mouse never moves relative to the window since the window is moving too, duh!
A similar issue stumped me for a while: the ButtonState property of MouseButtonEventArgs reflects the real-time state of that button, not a state snapshot taken when the event was raised. I wonder if the same holds true re your accessing LeftButton's state.
Hope this helps,
Ben
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.