When exactly is the MouseLeave event triggered? - c#

According to this MSDN Article : "The MouseLeave event is raised in response to a touch event occurring outside the object's bounding area.". But in implementation am finding it being triggered while releasing a tap on the object's bounding area (precisely like OnMouseLeave).
So how do I get it to fire while tapping outside the UI Object's boundary?

I am new to C# and StackOverflow, but I thought I might contribute what I found. I did a quick Google search of "" and found this article about detecting clicks outside of a GUI.
Here is a quick method/description (found in link) which detects the clicks outside of a rectangle drawn over the GUI. "When you use a GUI window or group / area, you can use its Rect to check if the mouse is inside."
Rect windowPos = new Rect(10,10,200,150);
void OnGUI()
{
Event e = Event.current;
windowPos = GUI.Window(0, windowPos, drawWindow, "MyWindow");
if (e.type == EventType.MouseDown && !windowPos.Contains(e.mousePosition))
{
// Click was outside of the GUI window
}
}
void drawWindow(int aID)
{
// draw the window content
}
Just go read on that page. It seemed to answer their question before.
Good luck!

Related

How to get coordinates of a Mouse when it's Clicked

I'm beginner in c# and need some help. After loading Form I want to display on Form coordinates of a Mouse when it's Clicked. Click can be made outside of the Form. For example in Browser. Can someone help me with this.
Maybe the most simple way is setting Capture property of a form to true, then handle click event and convert the position (that is position related to top left point of form) to screen position using PointToScreen method of form.
For example you can put a button on form and do:
private void button1_Click(object sender, EventArgs e)
{
//Key Point to handle mouse events outside the form
this.Capture = true;
}
private void MouseCaptureForm_MouseDown(object sender, MouseEventArgs e)
{
this.Activate();
MessageBox.Show(this.PointToScreen(new Point(e.X, e.Y)).ToString());
//Cursor.Position works too as RexGrammer stated in his answer
//MessageBox.Show(this.PointToScreen(Cursor.Position).ToString());
//if you want form continue getting capture, Set this.Capture = true again here
//this.Capture = true;
//but all clicks are handled by form now
//and even for closing application you should
//right click on task-bar icon and choose close.
}
But more correct (and slightly difficult) way is using global hooks.
If you really need to do it, you can take a look at this links:
Processing Global Mouse and Keyboard Hooks in C#
Low-Level Mouse Hook in C#
Application and Global Mouse and Keyboard Hooks .Net Libary in C#
I think you can't handle the mouse click outside your Form at least easily.
inside the form using MouseEventArgs it can simply be handled.
private void Form1_MouseClick(object sender, MouseEventArgs e)
{
// e.Location.X & e.Location.Y
}
Learn more about this topic at Mouse Events in Windows Forms.
I hope it helps.
Cursor.Position and Control.MousePosition both return the position of the mouse cursor in screen coordinates.
The following articles deal with capturing Global mouse click events:
Processing Global Mouse and Keyboard Hooks in C#
Global Windows Hooks
You need a global mouse hook.
See this question

Event "While Button is Pressed"

I made Event for Grid in WPF C#.
The MouseMove Event.
I want to Trigger MouseMove event When mouse Left button is Pressed and Keep the Event even when mouse is Out of Grid Or even out of the main Window.
When Button is Pressed Keep the Mousemove event for the Grid All over the screen Until Button is Releasd.
consider this is Mouse move event Method for the Grid
private void Grid_MouseMove(object sender, MouseEventArgs e)
{
if (e.LeftButton == MouseButtonState.Pressed) // Only When Left button is Pressed.
{
// Perform operations And Keep it Until mouse Button is Released.
}
}
The Goal is to Rotate 3D model When User Hold Left button and to rotate Model while he is moving the mouse until button releases.
This is for To make the Program and Rotation Eeasier for the user. Especialy performing Long rotations cause mouse get out of the grid.
I tried to use while but it fails and you know its because of single threaded.
so the way im thinking is to somehow expand a new Grid all over the screen when button is pressed inside the original Grid and to keep it until release.
And of course Dummy Grid witch is Hidden.
What are you trying to do is to work with the stream of events. As far as I understand your flow supposed to be the following:
Left mouse button pressed
Mouse moved1 (rotate model)
Mouse moved2 (rotate model)
...
N. Left mouse up (stop rotation)
There is an interesting concept which is called Reactive Programming.
http://rxwiki.wikidot.com/101samples
There is a library for C# (Reactive-Extensions)
Your code could look like this one:
// create event streams for mouse down/up/move using reflection
var mouseDown = from evt in Observable.FromEvent<MouseButtonEventArgs>(image, "MouseDown")
select evt.EventArgs.GetPosition(this);
var mouseUp = from evt in Observable.FromEvent<MouseButtonEventArgs>(image, "MouseUp")
select evt.EventArgs.GetPosition(this);
var mouseMove = from evt in Observable.FromEvent<MouseEventArgs>(image, "MouseMove")
select evt.EventArgs.GetPosition(this);
// between mouse down and mouse up events
// keep taking pairs of mouse move events and return the change in X, Y positions
// from one mouse move event to the next as a new stream
var q = from start in mouseDown
from pos in mouseMove.StartWith(start).TakeUntil(mouseUp)
.Let(mm => mm.Zip(mm.Skip(1), (prev, cur) =>
new { X = cur.X - prev.X, Y = cur.Y - prev.Y }))
select pos;
// subscribe to the stream of position changes and modify the Canvas.Left and Canvas.Top
// property of the image to achieve drag and drop effect!
q.ObserveOnDispatcher().Subscribe(value =>
{
//rotate your model here. The new mouse coordinates
//are stored in value object
RotateModel(value.X, value.Y);
});
Actually building a stream of mouse events is a very classical example of using RX.
http://theburningmonk.com/2010/02/linq-over-events-playing-with-the-rx-framework/
You can subscribe on this stream of events in the Windows constructor, so you don't depend on the Grid, and you don't have to draw fake Grid!
Some nice links to start with:
The Rx Framework by example
Rx. Introduction

Moving Borderless Forms

I need your help with some code I found on the web a long time ago. Sadly I don't remember from where it is :( To move the borderless forms in my project I use this code snipped:
protected override void OnMouseDown(MouseEventArgs e)
{
base.OnMouseDown(e);
if (e.Button == System.Windows.Forms.MouseButtons.Left)
{
this.Capture = false;
Message msg = Message.Create(this.Handle, 0XA1, new IntPtr(2), IntPtr.Zero);
this.WndProc(ref msg);
}
}
My problem is that I don't completely understand how the code works. As far as I understand the event gets activated when a mouse button is clicked on the forms. Then follows the query, if the mouse click is a left click. And from there I don't know what the following code does :(
The this.Capture=false tells the OS to stop capturing mouse events. The Message.Create creates a new message to be send to the message loop of the current application. 0xA1 is WM_NCLBUTTONDOWN; which is a non-client left-button down message. Meaning it simulated clicking the left mouse button on the missing border.
Windows then picks up the rest of the process.
At a basic level, you are sending a message to your window and having it handle it.
You are giving it a 0xA1 (WM_NCLBUTTONDOWN) and by sending a 0x02 as the parameter (HTCAPTION) you fool the process into thinking you are on the caption bar. Drags on a caption bar move the window around, hence you can drag the window by using your code.
Samples of doing this at:
C#: How to drag a from by the form and it's controls?
http://www.catch22.net/tuts/win32-tips-tricks
You're basically posting a message to the window. A little MSDN research uncovers that the message you're posting is WM_NCLBUTTONDOWN. Basically, you're telling the underlying window that the left mouse button is being held down and it needs to respond to that. That response typically happens to be dragging the window about.

Moving buttons in a Canvas

The following code is supposed to move UIElements in a canvas, when the mouse hovers over them, and the user hits Ctrl.
void keydown(Object sender, KeyEventArgs e)
{
if (e.Key == Key.LeftCtrl || e.Key == Key.RightCtrl)
{
control++;
if (control == 1)
{
drag = true;
elem = (UIElement)Mouse.DirectlyOver;
}
else
drag = false;
control %= 2;
}
}
void mousemove(object sender, MouseEventArgs e)
{
Point p = e.GetPosition(canvas);
if (drag)
{
if (elem == null) return;
//Canvas.SetLeft(myButton, p.X); <-- this works, but then why doesn't it work when I generalize it?
Canvas.SetLeft(elem, p.X);
Canvas.SetTop(elem, p.Y);
}
}
Any Shapes component, e.g. Rectangles will move when I hover the mouse over them, and hit control..But it doesn't work with Buttons, TextBoxes, TextViews, etc. Can anyone explain?
The documentation for Mouse.DirectlyOver says:
Controls can be composed of multiple elements. DirectlyOver reports the specific element in the composite control the mouse pointer is over and not the control itself. For example, depending on which part of a Button the pointer is over, the DirectlyOver property could report the TextBox of the Content property or the ButtonChrome.
In other words: A Button is made up of several sub-elements, like a ButtonChrome and a TextBlock (usually not a TextBox -- I think that's a typo on the MSDN page). When you call Mouse.DirectlyOver, you're probably getting one of those elements, rather than the Button.
Since those elements are not parented to a Canvas (they're parented to something in the Button's control template, most likely a Grid), setting the Canvas.Left and Canvas.Top attached properties will have no effect.
You probably want to walk up the visual tree (using VisualTreeHelper.GetParent) until you find something you're interested in dragging. How you determine whether you're interested in any given element is up to you. You could go until you find something that's parented to your Canvas, or you could just go until you find something that's one of a given set of types (stopping when you find something that descends from Control might be a decent place to start).
My guess is that those events are swallowed by the implementation of the controls that don't work.
I'm not in front of my computer now, but isn't there a previewmousemove event? Try using that?
Update: scratch that!
Just use e.Souce. The event source is designed to be the element your likely to be interested in. You'll need to cast to UIElement, but I'm pretty sure that'll work.

WPF drag distance threshold

I have a program with two WPF treeviews that allow dragging and dropping between the two. The problem is, it can be annoying to open / close items on the treeviews because moving the mouse just one pixel while holding the left mouse button triggers the drag / drop functionality. Is there some way to specify how far the mouse should move before it's considered a drag / drop?
There's a system parameter for this. If you have
Point down = {where mouse down event happened}
Point current = {position in the MouseMove eventargs}
then the mouse has moved the minimum drag distance if
Math.Abs(current.X - down.X) >= SystemParameters.MinimumHorizontalDragDistance ||
Math.Abs(current.Y - down.Y) >= SystemParameters.MinimumVerticalDragDistance
Just build a little buffer into your code that determines when the drag starts.
flag mouse down
on mouse move - check for mouse down.. if yes, check to see if its moved farther than whatever buffer you specify (3 pixels is probably good)
if it has, start the drag.
Following this article for Drag and Drop implementation, you would have to handle 2 mouse events in order to delay the dragging until the mouse has moved a certain distance. First, add a handler for PreviewMouseDown which stores the initial mouse position relative to your control. Don't use the MouseDown event because it is a bubbling event and may have been handled by a child control before reaching your control.
public class DraggableControl : UserControl
{
private Point? _initialMousePosition;
public DraggableControl()
{
PreviewMouseDown += OnPreviewMouseDown;
}
private void OnPreviewMouseDown(object sender, MouseButtonEventArgs e) {
_initialMousePosition = e.GetPosition(this);
}
Additionally, handle MouseMove to check the moved distance and eventually initiate the drag operation:
...
public DraggableControl()
{
...
MouseMove += OnMouseMove;
}
...
private void OnMouseMove(object sender, MouseEventArgs e)
{
// Calculate distance between inital and updated mouse position
var movedDistance = (_initialMousePosition - e.GetPosition(this)).Length;
if (movedDistance > yourThreshold)
{
DragDrop.DoDragDrop(...);
}
}
}

Categories