How to trigger a mousemove event when mousedown in C# Form - c#

I build an UserControl in C# form.
And I use MouseMove event in the event list.
Everything works properly.
Then,I want to detect if right or left button of mouse is pressed.
The MouseEventArgs provide Button status to use.
The issue is when left button on mouse is already pressed somewhere outside the UserControl ,then move the cursor on to the UserControl,MouseMove event just won't trigger.
Is there any solution for this?

This is because the MouseDown has happened somewhere else and therefore the MouseMove of that other place still keeps happening.
This is a good thing so you don't lose the event just because you happen to slip aside, eg from a scrollbar.
If you really want to prevent the good thing happening at that special place you can release the mouse capture that is going on..:
private void theOtherPlace_MouseMove(object sender, MouseEventArgs e)
{
if (! theOtherPlace.ClientRectangle.Contains(e.Location))
{
User32_DLL.ReleaseCapture();
}
}
Using this helper class:
using System.Runtime.InteropServices;
..
public static class User32_DLL
{
[DllImportAttribute("user32.dll")]
public static extern bool ReleaseCapture();
}
Not sure if it is a good idea, though! I for one am always very happy if I can rely on the pressed mousebutton to still work the way it should..
Or you could trigger the MouseMove of the UserControl from the other MouseMove, passing in the UC as sender and a modified MouseEventArgs:
private void theOtherPlace_MouseMove(object sender, MouseEventArgs e)
{
if (! theOtherPlace.ClientRectangle.Contains(e.Location))
{
Point pt = yourUserControl.PointToClient(Control.MousePosition);
if (yourUserControl.ClientRectangle.Contains(pt))
{
yourUserControl_MouseMove(listView1,
new MouseEventArgs(e.Button, e.Clicks, pt.X, pt.Y, e.Delta ) );
}
}
}

Related

Button mouse over ForeColour change

To create a mouse over button I use this code
private void btnCreateAccount_MouseHover(object sender, EventArgs e)
{
btnCreateAccount.ForeColor = Color.Gold;
}
private void btnCreateAccount_MouseLeave(object sender, EventArgs e)
{
btnCreateAccount.ForeColor = Color.Black;
}
The mouse over button works however when I hover over the button there is a good at least 1 second delay. I would think that it should change colour as soon as the mouse is placed over the button and not with a (in my opinion) too long delay.
Is there any way of fixing that code by like refreshing the button or something along those lines? or perhaps someone has a code that works perfectly?
You are handling the Mouse Hover event. This will require the cursor to be still for a short while in order to fire.
The pause required for this event to be raised is specified in milliseconds by the MouseHoverTime property.
This is read only.
Normally if you want the colour to change immediately you should handle the Mouse Enter event:
private void btnCreateAccount_MouseEnter(object sender, EventArgs e)
{
btnCreateAccount.ForeColor = Color.Gold;
}

Detect whether multiple ListView items were selected by dragging

I have a ListView with the View set to LargeIcon.
I specifically need to detect when multiple items were selected by dragging a selection box around them with the mouse.
(For example I don't want to know when items were selected by CTRL + Click)
I thought I could simply do it by keeping track of whether the mouse was down while it was moving which would indicate dragging, then on mouse up if it was a drag then I can set another variable to indicate this.
In my example below mouseDown is set to true, but when I keep the mouse down and move it isDrag is never set to true and I can't see what I'm doing wrong.
(Edit: isDrag becomes true if I remove the if clause which is weird because as I said mouseDown is definitely true).
I realise the code is a little longer than it needs to be but it's for clarity.
bool mouseDown;
bool isDrag;
bool wasDrag;
private void listView1_MouseDown(object sender, MouseEventArgs args)
{
wasDrag = false;
mouseDown = true;
}
private void listView1_MouseMove(object sender, MouseEventArgs args)
{
if (mouseDown)
isDrag = true; // <-- Never becomes true, even though mouseDown is true
}
private void listView1_MouseUp(object sender, MouseEventArgs args)
{
if (isDrag)
wasDrag = true;
mouseDown = false;
isDrag = false;
}
I know it'll be something stupid. Please put me out of my misery.
Alternatively if someone knows of a better was to detect a dragging selection (what's the proper term?) then I'm all ears.
Can you try this:
private void listView1_MouseMove(object sender, MouseEventArgs args)
{
isDrag = mouseDown;
}
I think for some reason, your event listView1_MouseUp still fires, which makes your isDrag variable set to other than the intended value. Try to put breakpoints on both MouseMove and MouseUp events to see the sequence with which they are firing.
After further investigation I've discovered that for a ListView control the MouseMove event will not fire while MouseDown is still occurring and fires immediately after releasing the mouse.
I can only assume that the logic built into this control that allows you to select multiple files by dragging a selection is messing with these events and essentially making them synchronous.
I've put together a basic workaround for this. It's not ideal but it does the job so I thought I'd share.
Basically when the mouse goes down I record the position. When the mouse goes up I check to see if it has moved more than a certain distance in any direction. If it has not I consider it a click, if it has I consider it a drag.
// Records the mouse position on mousedown
int beforeMoveX;
int beforeMoveY;
// How far in pixels the mouse must move in any direction
// before we consider this a drag rather than a click
int moveBounds = 20;
private void listView1_MouseDown(object sender, MouseEventArgs e)
{
// Save the mouse position
beforeMoveX = e.X;
beforeMoveY= e.Y;
}
private void listView1_MouseUp(object sender, MouseEventArgs e)
{
// Did we move more than the bounds in any direction?
if (e.X < (beforeMoveX - moveBounds) ||
e.X > (beforeMoveX + moveBounds) ||
e.Y < (beforeMoveY - moveBounds) ||
e.Y > (beforeMoveY + moveBounds))
{
// DRAGGED!
}
else
{
// NOT DRAGGED!
}
}

MouseHook, MouseDown and MouseClick split

I have a little problem. I tried to look at google, but it gave me nothing much.
I made a little program that uses global hooks and get mouse coordinates on click. The problem is when I made a second method with MouseDown and when I just click a button, MouseDown method runs too.
So the question is:
How can I split two methods and let them work only separately: when I click, only MouseClick method is triggered, when press and keep down for a while it triggers only MouseDown?
Should I use some timing or what? Just give me a tip what I should try to use.
P.S. Sorry, my English isn't good, it's not my native language.
Here is some code, that I think give the overview.
public void StartRecording()
{
mouseListener = new MouseHookListener(new GlobalHooker());
mouseListener.Start();
mouseListener.MouseClick += new MouseEventHandler(MouseClicked);
mouseListener.MouseDown += new MouseEventHandler(MouseDown);
}
public void MouseClicked(object sender, MouseEventArgs e)
{
MessageBox.Show(String.Format("Mouse was pressed at {0}, {1}",
Control.MousePosition.X.ToString(),
Control.MousePosition.Y.ToString()));
}
public void MouseDown(object sender, MouseEventArgs e)
{
MessageBox.Show(String.Format("Mouse was down at {0}, {1}",
Control.MousePosition.X.ToString(),
Control.MousePosition.Y.ToString()));
}
When you click the mouse both is the case.
MouseClick is as far as i know both MouseDown and MouseUp, where MouseDown will be fired when you press down. And MouseUp will be fired when you release the button..
I think you will have to add some functionality to the MouseDown method which counts how long the mouse was pressed down.. That would be my solution.
In the MouseDown event you should store the current time and coordinates in variables that are global to the class they are in.
Then, you should use the MouseUp event to detect when the mouse button is released. You can then compare the new time and coordinates to the stored ones to see how long the button was pressed and if the mouse moved in that time, and act upon it accordingly.
Alternatively, you could also use the MouseMove event to reset the time and coordinates if required.
As a workaround, instead of hooking to MouseClick, try using MouseUp.
Then on MouseDown save current time in a class level variable (clickTime in the example). On MouseUp check the time again. If the time span is longer then say 3 seconds - do what you wanted to do on mouse down, otherwise - continue with mouse click.
DateTime clickTime;
public void MouseUp(object sender, MouseEventArgs e)
{
if (DateTime.Now - clickTime > someDelayTime)
{
// Do mouse down
}
else
{
// Do mouse click
}
}
public void MouseDown(object sender, MouseEventArgs e)
{
clickTime = DateTime.Now;
}

Mouse up event doesn't get triggered

I have the following problem: I have a panel which has a specific color, say red.
When the user presses his mouse, the color of this panel gets stored in a variable. Then the user moves, his mouse still pressed, over to another panel. When he releases the mouse there, this panel should get the background color of the first that had been stored in the variable. My code looks something like this:
public Color currentColor;
private void ColorPickMouseDown(object sender, MouseEventArgs e)
{
Panel pnlSender = (Panel)sender;
currentColor = pnlSender.BackColor;
}
private void AttempsColorChanger(object sender, MouseEventArgs e)
{
Panel pnl = (Panel)sender;
pnl.BackColor = currentColor;
}
I need to identify the sender first because there are many possible panels that can trigger this event. The first MouseDown method works totally fine, the color is stored nicely in the variable. The secon one however doesn't even get triggered when the user does what I described above. When the ser clicks on the second panel, it works (there is an MouseUp part in a click aswell I guess).
What's wrong here? Why is the event not triggered when the user holds the mouse key down before?
(This answer assumes you are using Windows Forms.)
It could be that you need to capture the mouse by setting this.Capture = true in the MouseDown of the source control. (See Control.Capture)
If you did that, the source window would get the MouseUp event, and it would be the source window that had to determine the destination window under the mouse coords. You can do that using Control.GetChildAtPoint() (see this answer on Stack Overflow).
Use Windows Forms Drag and Drop Support Instead! <- Click for more info
I'm going to suggest you bite the bullet and use the .Net Drag and Drop methods to do this. It requires some reading up, but it will be much better to use it.
You start a drag in response to a MouseDown event by calling Control.DoDragDrop().
Then you need to handle the Control.DragDrop event in the drop target control.
There's a few more things you might need to do to set it up; see the Control.DoDragDrop() documentation for an example.
(For WPF drag and drop support, see here.)
when your mouse enter the target control , mouse down triggerd ang get target BackColor! you need add an boolean flag to your code :
public Color currentColor;
bool flag=false;
private void ColorPickMouseDown(object sender, MouseEventArgs e)
{
if(flag==false)
{
flag=true
Panel pnlSender = (Panel)sender;
currentColor = pnlSender.BackColor;
}
}
//assume mouse up for panles
private void AttempsColorChanger(object sender, MouseEventArgs e)
{
if(flag==true)
{
Panel pnl = (Panel)sender;
pnl.BackColor = currentColor;
flag=flase;
}
}
and also you need change your flag in mouseMove( if )
As I mentioned in my comment Mouse Events are captured by the originating control, You would probably be better off using the DragDrop functionality built into Windows Forms. Something like this should work for you. I assigned common event handlers, so they can be assigned to all of your panels and just work.
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void panel_MouseDown(object sender, MouseEventArgs e)
{
((Control)sender).DoDragDrop(((Control)sender).BackColor,DragDropEffects.All);
}
private void panel_DragDrop(object sender, DragEventArgs e)
{
((Control)sender).BackColor = (Color)e.Data.GetData(BackColor.GetType());
}
private void panel_DragEnter(object sender, DragEventArgs e)
{
e.Effect = DragDropEffects.Copy;
}
}
I know it's an old question but I had the same issue and none of the above answers worked for me. In my case I had to handle the MouseMove event in the target control and check for the mouse to be released. I did set 'BringToFront' on my target panel just in case that helped at all.
public Color currentColor;
private void ColorPickMouseDown(object sender, MouseEventArgs e)
{
Panel pnlSender = (Panel)sender;
currentColor = pnlSender.BackColor;
}
private void panelTarget_MouseMove(object sender, MouseEventArgs e)
{
//the mouse button is released
if (SortMouseLocation == Point.Empty)
{
Panel pnl = (Panel)sender;
pnl.BackColor = currentColor;
}
}

WPF equivalent of Control.CursorChanged event

I am trying to change my mouse cursor at certain point when I'm dragging my mouse around in a wpf listview. However, when I set my mouse, it quickly gets overridden by something else, and get changed back to the drag cursor.
I am not sure where the cursor change comes from, it is certainly not from my code, so it has to be system. If it is system, then I have to intercept the event for cursor change, and handle the event in order for the cursor to show what I want right?
So is there a WPF equivalent of this Control.CursorChanged event? Or perhaps there's some other way to approach this problem?
Edit:
here's part of my code
private void SetDragCursor()
{
if (_badDragLoc)
{
Mouse.OverrideCursor = Cursors.No;
}
else
{
Mouse.OverrideCursor = Cursors.Arrow;
}
}
private void listView_DragOver(object sender, DragEventArgs e)
{
if (at a bad drag location)
{
_badDragLoc = true;
SetDragCursor();
}
}
I also have a drag leave event handler, in which I also have the SetDragCursor() method as well. When I step by step go through each line of code in debugger, the mouse turned into the drag cursor from the no cursor right after it enters the drag leave handler. Which is why I think it has to be the system.
If it indeed is the system, then if I can capture the event firing, I can then handle those event myself and not let it bubble through.
Thank you!
Just does not work like that, the way to set the cursor during a DragOver event is the following:
void listView__DragOver(object sender, DragEventArgs e)
{
if (!e.Data.GetDataPresent("Images"))
{
e.Effects = DragDropEffects.None;
e.Handled = true;
}
}
depending on the value of DragDropEffects enum you assign to e.Effects the mouse will change cursor.
do not call Mouse.OverrideCursor because is not the right way.

Categories

Resources