I need to update a control only whenever the mouse moves over it with the left mouse button pressed. I would normally simply check for the e.Button property, but it is unavailable in the MouseEnter event.
void MyControl_MouseEnter(object sender, EventArgs e)
{
// MouseEventArgs needed to check this
// if (e.Button == MouseButtons.Left)
// {
// update MyControl
// }
}
How would you accomplish this?
Use the static Control.MouseButtons property. For example:
private void panel1_MouseEnter(object sender, EventArgs e) {
if (Control.MouseButtons == MouseButtons.Left) {
// etc...
}
}
This is very difficult to get going, whatever the user clicks on to get the mouse button pressed is going to capture the mouse, preventing the control's MouseEnter event from firing. It is also UI that's completely undiscoverable to the user. Do consider a better mouse trap.
Here's one (crude) way to do it. It will change the form's title text to whatever mouse button was pressed as you dragged your mouse on to button1. You can reference Control.MouseButtons to see which button is in a pressed state. Here's some more info on MSDN.
public partial class Form1 : Form
{
MouseButtons _buttons;
public Form1()
{
InitializeComponent();
}
private void button1_MouseMove(object sender, MouseEventArgs e)
{
if (_buttons != System.Windows.Forms.MouseButtons.None)
{
this.Text = _buttons.ToString();
}
}
private void Form1_MouseMove(object sender, MouseEventArgs e)
{
_buttons = Control.MouseButtons;
}
}
I found the answer in another question here on SO:
How can I detect a held down mouse button over a PictureBox?
You will need to use a message filter. Implement the PreFilterMessage of the IMessageFilter interface, and assign an instance using Application.AddMessageFilter.
You will have to interpret windows messages yourself... that is not kind of difficult, but it will require some work.
The implementation may look like this:
if (m.Msg == 0x200)
{
int x, y;
x = m.LParam.ToInt32() & 0xFFFF;
y = m.LParam.ToInt32() >> 16;
if ((m.WParam.ToInt32() & 2) != 0)
{
// here, the left mouse button is pressed, and you can use the coords
// and see if the mouse is over the control you want.
}
}
I just implemented something like this today, tested only in Chrome but works rather nicely. Basic concept is that you capture mousemove only between mousedown and mouseup, as follows:
var image = document.getElementById('my_image');
image.addEventListener('mousedown', function(e) {
e.currentTarget.addEventListener('mousemove', doMyStuff);
});
image.addEventListener('mouseup', function(e) {
e.currentTarget.removeEventListener('mousemove', doMyStuff);
});
function doMyStuff(e) {
// do what you want, the mouse is moving while the user is holding the button down
}
Private Sub Button1_MouseDown(sender As Object, e As MouseEventArgs) Handles
Button1.MouseDown
If Control.MouseButtons = MouseButtons.Left Then
Label1.Text = "Left"
ElseIf Control.MouseButtons = MouseButtons.Right Then
Label1.Text = "Right"
ElseIf Control.MouseButtons = MouseButtons.Middle Then
Label1.Text = "Middle"
Else
Label1.Text = "lelse"
End If
End Sub
Related
I have a form that contains a panel. The idea is that when the mouse is hovered over the panel it displays the OpenHand cursor. You can then drag the panel which causes the cursor to change to the Grab cursor. Upon mouse release the Grab cursor should change back to the OpenHand cursor.
Unfortunately, I'm having an issue that if I drag and release my panel (with the mouse within the bounds of the panel), eventually (usually on the second or third go) the Grab cursor will not change back into the OpenHand cursor.
This remains the case even when you move the mouse out of the panel and back in and try dragging and releasing.
Here is my Panel class:
public class MapPanel : Panel
{
private Point MouseDownLocation;
private Cursor OpenHand = new Cursor(Properties.Resources.hand.Handle);
private Cursor Grab = new Cursor(Properties.Resources.punch.Handle);
public MapPanel()
{
MouseDown += new MouseEventHandler(mapPanel_MouseDown);
MouseUp += new MouseEventHandler(mapPanel_MouseUp);
MouseMove += new MouseEventHandler(mapPanel_MouseMove);
}
private void mapPanel_MouseDown(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
Cursor = Grab;
MouseDownLocation = e.Location;
}
}
private void mapPanel_MouseUp(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
Cursor = OpenHand;
}
}
private void mapPanel_MouseMove(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
Left = e.X + Left - MouseDownLocation.X;
Top = e.Y + Top - MouseDownLocation.Y;
}
}
}
Interestingly there are no issues if I don't include the MouseMove handler, however the Cursor = OpenHand; statement inside the MouseUp method does still get called with the MouseMove handler included. It just doesn't take effect.
Hopefully someone can shed some light on this. Any help would be very much appreciated!
How can I get the type of pressed pointer (left mouse down or right mouse down) in a Metro style C# app? I didn't find a MouseLeftButtonDown event handler in any Metro style UI element. I should use PointerPressed event instead, but I don't know how can i get which button was pressed.
PointerPressed is enough to handle mouse buttons:
void MainPage_PointerPressed(object sender, PointerRoutedEventArgs e)
{
// Check for input device
if (e.Pointer.PointerDeviceType == Windows.Devices.Input.PointerDeviceType.Mouse)
{
var properties = e.GetCurrentPoint(this).Properties;
if (properties.IsLeftButtonPressed)
{
// Left button pressed
}
else if (properties.IsRightButtonPressed)
{
// Right button pressed
}
}
}
You can use the following event to determine what pointer is used and what button is pressed.
private void Target_PointerMoved(object sender, PointerRoutedEventArgs e)
{
Windows.UI.Xaml.Input.Pointer ptr = e.Pointer;
Windows.UI.Input.PointerPoint ptrPt = e.GetCurrentPoint(Target);
if (ptrPt.Properties.IsLeftButtonPressed)
{
//Do stuff
}
if (ptrPt.Properties.IsRightButtonPressed)
{
//Do stuff
}
}
Working on a UWP project and previous answers like
Properties.IsLeftButtonPressed/IsRightButtonPressed did not work for me. Those values are always false. I realized during the Debugging that Properties.PointerUpdateKind was changing according to mouse button. Here is the result which worked for me:
var properties = e.GetCurrentPoint(this).Properties;
if (properties.PointerUpdateKind == Windows.UI.Input.PointerUpdateKind.LeftButtonReleased)
{
}
else if (properties.PointerUpdateKind == Windows.UI.Input.PointerUpdateKind.RightButtonReleased)
{
}
else if (properties.PointerUpdateKind == Windows.UI.Input.PointerUpdateKind.MiddleButtonReleased)
{
}
There are more options in PointerUpdateKind like ButtonPressed varities of the ones in the example and XButton varities e.g. XButton1Pressed, XButton2Released etc.
I'll try and keep this generic for future refference.
Let's suppose our Form has a grid of Squares (RectangleShapes which we'll reffer to individually as "points".) Since the size of this grid can vary before the Form loads, we've create all the points in a panel when we first load our Form and can use...
foreach (Squares point in mySquares)
...when we want to change their behavior or appearance. Now, we've already developed code to change the color of each individual point when the user clicks left or right. It would look something like:
private void panelGrid_MouseDown(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left || e.Button == MouseButtons.Right)
{
foreach (Squares point in mySquares)
{
if (point.Rectangle.Contains(e.Location)) // determine which point to use
{
if (e.Button == MouseButtons.Left)
{
Pencil(point); // left-click to fill color
}
else
{
Erase(point); // right-click to erase color
}
}
}
panelGrid.Invalidate(); // refreshes grid
}
}
And this works like a charm. But suppose we need to change this code: Now we also want the color to change when a mouse button is held down, and the cursor is moved onto a new point. (Sort of like MS-Paint: Dragging the pencil tool over multiple pixels fills each one in turn.)
What confuses me is the proper way to implement this behavior properly. To my understanding, I would want the Pencil/Eraser methods to call when:
A.) The mouse enters a "point" AND a button is already held down.
OR
B.) A mouse button becomes pressed. (See above code)
Where this gets tricky for me is determining how best to implement the new checks, and how to perform them on the individual points in the grid - or even if that's necessary. Any tips?
Sounds like you want the MouseDown and MouseMove events to do the same thing:
private void MouseStuff(MouseEventArgs e) {
if (e.Button == MouseButtons.Left || e.Button == MouseButtons.Right)
{
foreach (Squares point in mySquares) {
if (point.Square.Contains(e.Location)) {
if (e.Button == MouseButtons.Left) {
Pencil(point);
} else {
Erase(point);
}
}
}
panelGrid.Invalidate();
}
}
then try calling it from both events:
private void panelGrid_MouseDown(object sender, MouseEventArgs e) {
MouseStuff(e);
}
private void panelGrid_MouseMove(object sender, MouseEventArgs e) {
MouseStuff(e);
}
Look into using a double-buffered panel to make the control less flicky since invalidating the panel on a MouseMove event can be quite intensive:
public class BufferedPanel : Panel {
public BufferedPanel() {
this.DoubleBuffered = true;
this.ResizeRedraw = true;
}
}
I need to determine if the value of a NumericUpDown control was changed by a mouseUp event.
I need to call an expensive function when the value of a numericupdown has changed. I can't just use "ValueChanged", I need to use MouseUp and KeyUp events.
Basically, I need to know:
Did the value of the numericUpDown change when the user let go of the
mouse? If any area which is not highlighted in red is clicked, the
answer is no. I need to IGNORE the mouse up event, when ANYWHERE but the red area is clicked.
How can I determine this by code? I find events a little confusing.
This will fire when the user releases the mouse button. You might want to investigate which mousebutton was released.
EDIT
decimal numvalue = 0;
private void numericUpDown1_MouseUp(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left && numvalue != numericUpDown1.Value)
{
//expensive routines
MessageBox.Show(numericUpDown1.Value.ToString());
}
numvalue = numericUpDown1.Value;
}
EDIT 2
This will determine if the left mousebutton is still down, if it is exit before performing expensive routine, doesn't help with keyboard button down.
private void numericUpDown1_ValueChanged(object sender, EventArgs e)
{
if ((Control.MouseButtons & MouseButtons.Left) == MouseButtons.Left)
{
return;
}
//expensive routines
}
Edit 3
How to detect the currently pressed key?
Will help solve the Any key down, Though I think the only ones that matter are the arrow keys
Problem - I need to IGNORE the mouse up event, when ANYWHERE but the red area is clicked.
Derive a custom numeric control as shown below. Get the TextArea of the Numeric Control and ignore the KeyUp.
class UpDownLabel : NumericUpDown
{
private Label mLabel;
private TextBox mBox;
public UpDownLabel()
{
mBox = this.Controls[1] as TextBox;
mBox.Enabled = false;
mLabel = new Label();
mLabel.Location = mBox.Location;
mLabel.Size = mBox.Size;
this.Controls.Add(mLabel);
mLabel.BringToFront();
mLabel.MouseUp += new MouseEventHandler(mLabel_MouseUp);
}
// ignore the KeyUp event in the textarea
void mLabel_MouseUp(object sender, MouseEventArgs e)
{
return;
}
protected override void UpdateEditText()
{
base.UpdateEditText();
if (mLabel != null) mLabel.Text = mBox.Text;
}
}
In the MainForm, update your designer with this control i.e. UpDownLabel:-
private void numericUpDown1_MouseUp(object sender, MouseEventArgs e)
{
MessageBox.Show("From Up/Down");
}
Referred from - https://stackoverflow.com/a/4059473/763026 & handled the MouseUp event.
Now, use this control instead of the standard one and hook on the
KeyUp event. You will always get the KeyUp event from the Up/Down button only i.e. RED AREA when you click the
spinner [Up/Down button, which is again a different control derived
from UpDownBase].
I think you should use Leave event that when the focus of NumericUpDown control gone, it would called.
int x = 0;
private void numericUpDown1_Leave(object sender, EventArgs e)
{
x++;
label1.Text = x.ToString();
}
I have a button that I trigger OnClick whenever there is a click on that button. I would like to know which Mouse button clicked on that button?
When I use the Mouse.LeftButton or Mouse.RightButton, both tell me "realsed" which is their states after the click.
I just want to know which one clicked on my button. If I change EventArgs to MouseEventArgs, I receive errors.
XAML: <Button Name="myButton" Click="OnClick">
private void OnClick(object sender, EventArgs e)
{
//do certain thing.
}
You can cast like below:
MouseEventArgs myArgs = (MouseEventArgs) e;
And then get the information with:
if (myArgs.Button == System.Windows.Forms.MouseButtons.Left)
{
// do sth
}
The solution works in VS2013 and you do not have to use MouseClick event anymore ;)
If you're just using the Button's Click event, then the only mouse button that will fire it is the primary mouse button.
If you still need to know specifically whether it was the left or right button, then you can use the SystemInformation to obtain it.
void OnClick(object sender, RoutedEventArgs e)
{
if (SystemParameters.SwapButtons) // Or use SystemInformation.MouseButtonsSwapped
{
// It's the right button.
}
else
{
// It's the standard left button.
}
}
Edit: The WPF equivalent to SystemInformation is SystemParameters, which can be used instead. Though you can include System.Windows.Forms as a reference to obtain the SystemInformation without adversely effecting the application in any way.
You're right, Jose, it's with MouseClick event. But you must add a little delegate:
this.button1.MouseDown += new System.Windows.Forms.MouseEventHandler(this.MyMouseDouwn);
And use this method in your form:
private void MyMouseDouwn(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Right)
this.Text = "Right";
if (e.Button == MouseButtons.Left)
this.Text = "Left";
}