I registered Hotkey: Ctrl + Space. Hotkey message is sent to:
private void Hotkey_press()
{
... // I want to show tooltip "Hello" at current mouse location.
}
Is there any way to show this tooltip even the mouse doesnt point to any control and it is outside my Window.Form1?
Edit: That ToolTip can show even the form lost focus or hide
You want something like
ToolTip tt = new ToolTip();
IWin32Window win = this;
tt.Show("String", win, mousePosition);
Where the MousePosition can be obtained from the MouseEventArgs via
private SomeMouseEventHandler(object sender, MouseEventArgs e)
{
System.Drawing.Point mousePosition = e.Location;
...
}
or using
System.Drawing.Point mousePosition = Cursor.Position;
also, you may want to set a longer duration for which the ToolTip is displayed, well just use the overloads available for the Show method, tt.Show("String", win, mousePosition, 5000); will display the tool tip for 5 seconds.
I hope this helps.
Tooltip tip = new ToolTip();
tip.ShowAlways = true;
tip.Show("My tooltip",this,Cursor.Position.X,Cursor.Position.Y);
http://msdn.microsoft.com/en-us/library/system.windows.forms.tooltip.aspx
http://msdn.microsoft.com/en-us/library/system.windows.forms.tooltip.showalways.aspx
http://msdn.microsoft.com/en-us/library/system.windows.forms.cursor.aspx
As this answer suggests, there is no managed way to accomplish this. If you want to show a tool tip control when your program is not in focus then the "right" way to do it is to PInvoke Win32 and use CreateWindowEx. The answer linked above given by gideon shows some pointers on how to do it, but nonetheless it is very complicated.
If you don't mind using thrid party libraries, AutoIt provides a way to create tool tips easily without having to deal with Win32 yourself.
Here is a very simple example demonstrating use:
//make sure AutoItX3.dll is referenced in your project
using AutoItX3Lib;
private AutoItX3 myAutoIt = new AutoItX3();
private async void ShowToolTipAtMouse(string message)
{
//default position is bottom right of mouse pointer,
//but you can set the x and y positions yourself
myAutoIt.ToolTip(message);
//call the function again with an empty argument to close
await Task.Delay(1000);
myAutoIt.ToolTip(String.Empty);
}
This will work as long as your program is running; doesn't matter if it is in/out of focus or even hidden. Downside is you don't get the regular fade out animation (it just vanishes). Also, if you need multiple tool tips at once you need to have multiple AutoItX3 objects.
You need Show/Hide it in the mouse events, also converting mouse location from Screen coordinate to your control coordinate. the little problem is if you put tooltip exactly on mous pointer location toolTip will catch mouseEnter event and unintended mouseLeave event on your control will be triggered so my solution was adding a little offset to final location.
private void pictureBox1_MouseMove(object sender, MouseEventArgs e)
{
Point p = pictureBox3.PointToClient(Cursor.Position);
p.X += 5;
p.Y += 5;
toolTip1.Show("My tooltip" ,
pictureBox1, p);
}
private void pictureBox1_MouseLeave(object sender, EventArgs e)
{
toolTip1.ShowAlways = false;
Text = ("Leave");
}
private void pictureBox1_MouseEnter(object sender, EventArgs e)
{
toolTip1.ShowAlways = true;
Text=("Enter");
}
It is a shame Winforms does not have a position property for tooltips.
The easiest thing I found is to add your own mouse-over and mouse-leave handlers and then use the Show() function to set the location (x and y), in pixels, relative to the upper left corner of the second argument of the Show() function.
The second argument can be any control, but probably makes most sense to use the control containing the tooltip itself (this), the parent the control, or a child control inside the control.
You can use a Point instead of two arguments (x and y) for the position, but remember Show() will take the point's x coordinate and y coordinate and add them to the x and y coordinates of the upper left corner of the control you chose as the second argument.
private void UserControl1_MouseHover(object sender, EventArgs e)
{
toolTip1.Show("this text is so new", this, 10, 10);
}
private void UserControl1_MouseLeave(object sender, EventArgs e)
{
toolTip1.Hide(this);
}
Related
I think that must be only a little problem, but I can't get a clear thought on that. Someone an idea?
I have some borders on a canvas (filled with images) and i want to click the border (i do this with the OnMouseLeftButtonDown) where the border gets red (so the user knows for sure which object he had clicked) and then, after 1 or 2 seconds, when the mousebutton is still pushed down, a drag'n'drop should start.
At first I had the borders inside buttons, but the clickevent seems to conflict with the dragevent. So I got rid of the buttons and did everything inside the borders directly, which works well also. But how can I start the drag after the mousebuttondown and stop it when the mousebuttonup happens before the time runs out.
Someone an idea for a clean solution?
private void OnMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
_source = sender as Border;
Mouse.Capture(_source);
}
private void OnMouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
_source = null;
Mouse.Capture(null);
}
and in event OnMouseMove you can modify border margins depends on mouse position but after checking if _source is type of Border.
var position = e.GetPosition(Canvas);
EDIT:
For that time you can add property Stopwatch _watch, and inside OnMouseLeftButtonDown event handler you can do it:
_watch = Stopwatch.StartNew();
in OnMouseLeftButtonUp:
_watch.Stop();
and in OnMouseMove before your code:
while (_watch.ElapsedMilliseconds < 2000 && _watch.IsRunning)
{
Thread.Sleep(100);
}
For the record: I'm new to Silverlight and XAML.
I'm trying to simply display the mouse coordinates relative in my canvas (or any other element).
After reading a lot on the subject, unfortunantly I havn't figured this our yet.
My Silverlight 5 project uses MVVM with Caliburn micro.
How can this be done?
Would Appreciate help on implementing this.
Thanks,
Guy.
You need to be a little more specific with what control you're trying to get this with, but have you tried wiring something up to the MouseMove event? Like MouseMove="Handle_MouseMove"
public void Handle_MouseMove(object sender, MouseEventArgs args)
{
mouseVerticalPosition = args.GetPosition(null).Y;
mouseHorizontalPosition = args.GetPosition(null).X;
}
Is that what you're looking for?
If you want this to happen on the entire canvas, you can instead wire it up to PointerMoved
See MouseEventArgs. This can get you the X and Y position and it can be used with the MouseUp, MouseDown, and MouseMove events.
To complete tnw Answer : You have to start mouse capture on object : MyElement.CaptureMouse()
In the handler method, you can use GetPosition on MouseEventArgs with an UIElement in parameter for relative coordinates...
public void Handle_MouseMove(object e, MouseEventArgs f)
{
var point = f.GetPosition(MyElement);
}
you have to catch the mouse click event and there are some event handlers you can use it to capture the position.
private void CadLayoutRoot_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
double point1 = e.GetPosition(bitmapCadView.UIElement).X;
double point2 = e.GetPosition(bitmapCadView.UIElement).Y;
}
It is very easy to get the position of cursor out side the form's boundary by just dragaging the mouse it sends many values to the form when ever the position changes, form the following line of code.
MessageBox.Show(Cursor.Position.ToString());
But I need to get the mouse position when user clicked out side the forms boundary.
Not by just hovering the mouse. I used the following line of Code to do this:
private void Form1_Deactivate(object sender, EventArgs e)
{
MessageBox.Show(Cursor.Position.ToString());
}
I placed MessageBox.Show(Cursor.Position.ToString()); into forms Deactivate event. When user click outside the form this event definitely occures. But it also sends wrong values when user does not click outside but changes the program by using ALT + TAB key combination.
Actually I have to capture screen shot of the area starting from the position of first click. Therefore I need the position of the cursor when it is clicked outside the form.
like:
This might help some one.
Here I am using Windows.Forms.Timer and two text boxes for displaying [X and Y] cursor positions. On timer tick calling the API GetCursorPos and getting the cursor position.
public partial class Form1 : Form
{
[DllImport("user32.dll")]
static extern bool GetCursorPos(ref Point lpPoint);
public Form1()
{
InitializeComponent();
timer1.Start();
}
private void timer1_Tick(object sender, EventArgs e)
{
var pt = new Point();
GetCursorPos(ref pt);
textBox1.Text = pt.X.ToString();
textBox2.Text = pt.Y.ToString();
}
}
Regards,
Ranjeet.
You should use Global Mouse Hook logic to do this.
Here is a good article that will help you: Processing Global Mouse and Keyboard Hooks in C#
The solution to this problem is simple. All what you need is a System.Windows.Forms.Timer, and use System.Runtime.InteropService.DllImport to extern the method GetKeyState from user32.dll.
This function has one parameter of any type of integer, and it returns short (Int16). This function can tell you if some keys were pressed or not at every moment and everywhere, not depending on the form. While the Timer is Enabled, you can check if the mouse position is out of the form bounds. There are many ways to get the mouse position.
One way is Cursor.Position, or Control.MousePosition, or you can use the bool GetCursorPos(ref Point lpPoint), an extern method, that you can DllImport it from "user32.dll". form.Bounds or form.ClientRectangle, or form.Location and form.Size or form.Left and form.Top and form.Width and form.Height, all these bring you the form bounds. In the timer_Tick function event, you write the following code for example:
var mp = Cursor.Position;
var fb = form.ClientRectangle; // Or form.Bounds
if (mp.X < fb.X || mp.Y < fb.Y || mp.X > fb.X + fb.Width || mp.Y > fb.Y + fb.Height)
{
// Use GetKeyState from user32.dll to detect if at least 1 key is pressed
// (look at internet how to do it exactly)
// If yes MessageBox.Show("Clicked outside");
}
If at least 1 key was pressed, and then Show your message with the MessageBox. You can read on the Internet how to do all these stuff I was talking about before, and if you succeed, it will work!
Try this:
// Form1.cs
private Point pos1;
private Point pos2;
private bool b = true;
private double diffx;
private double diffy;
private double area;
private void Form1_Deactivate(object sender, EventArgs e)
{
if (b) (pos1, b) = (Cursor.Position, false);
else
{
pos2 = Cursor.Position;
if (pos1.x >= pos2.x) diffx = pos1.x - pos2.x;
else diffx = pos2.x - pos1.x;
if (pos1.y >= pos2.y) diffy = pos1.y - pos2.y;
else diffy = pos2.y - pos1.y;
area = diffx * diffy;
MessageBox.Show(area.ToString());
}
}
But you will have to click on the program again after clicking outside it in the start point and then click outside it in the end point to make the program work
Deactivate event notifies your form that it's not active any more. It could happen because of many reasons.
Usually a Window gets mouse events only when mouse is over this window. SetCapture function lets you grab all mouse events (I don't know .NET counterpart). Because only one window can capture mouse events, you should not capture mouse events when there's no need for it. The question does not have enough details on what you really want to do and why you need to know when user clicked outside your form.
As long as the mouse is over a specific control, we show some form. When the mouse leaves the control, we hide the control after a small timeout. This is standard hover behavior.
However, when a control (for example a Treeview) has a scrollbar, and the mouse is ON or OVER the scrollbar, the events don't fire ...
If we could get a reference to the scrollbar control, this would solve our problem, as we would add the same listener events to the scrollbar. However, the scrollbar isn't accessible as far as I know ...
How can we solve this problem ?
The scrollbar is in the tree view's non-client area. When the mouse moves there, it starts generating non-client messages like WM_NCMOUSEMOVE and WM_NCMOUSELEAVE. You would have to sub-class the TreeView and override WndProc() to detect these message.
This doesn't really solve your problem though, you'll still have a hard time with edge cases. A low-tech approach with a Timer always works:
private Form frmPopup;
private void treeView1_MouseEnter(object sender, EventArgs e) {
timer1.Enabled = true;
if (frmPopup == null) {
frmPopup = new Form2();
frmPopup.StartPosition = FormStartPosition.Manual;
frmPopup.Location = PointToScreen(new Point(treeView1.Right + 20, treeView1.Top));
frmPopup.FormClosed += (o, ea) => frmPopup = null;
frmPopup.Show();
}
}
private void timer1_Tick(object sender, EventArgs e) {
Rectangle rc = treeView1.RectangleToScreen(new Rectangle(0, 0, treeView1.Width, treeView1.Height));
if (!rc.Contains(Control.MousePosition)) {
timer1.Enabled = false;
if (frmPopup != null) frmPopup.Close();
}
}
I think there are several different ways to do this, but the key is your desire to have a timeout on the action. I think a combination of two techniques might work:
Put the control on a panel, docked to fill, and use the MouseEnter of the panel to turn on your behavior -- this will include the control's scrollbar. You can use the MouseLeave event of the panel as well, but you'll have to check the cursor's position to ensure it hasn't moved into the contained control. This method is mostly reliable, but moving the mouse quickly can confuse it.
If you combine this with a timer that starts when your shown/hidden control is shown and check the cursor position periodically. This will work, but your timeout before hiding the control won't necessarily be consistent (because the timer starts when they enter the control). You could stop/start the timer on mousemoves in the control to alleviate this somewhat.
I put together a project of the different methods I tried here: http://lovethedot.s3.amazonaws.com/100609StackoverflowScrollbarQuestion.zip
By docking the control you want to track in the panel, it essentially wraps it and you'll get MouseEnter at the very edge of the tracked control:
private void panel1_MouseEnter(object sender, EventArgs e)
{
this.Text = "in";
}
private void panel1_MouseLeave(object sender, EventArgs e)
{
if (!new Rectangle(new Point(0, 0), panel1.Size).Contains(panel1.PointToClient(Control.MousePosition)))
this.Text = "out";
}
You're tracking entry into the panel surrounding the control, and exit from that panel provided the cursor isn't inside the tracked control.
To get a better "leave" experience, it's combined with a Timer that checks to see where the cursor is as well:
private void listBox3_MouseEnter(object sender, EventArgs e)
{
button1.Visible = true;
visibleTimer.Stop();
visibleTimer.Start();
}
void visibleTimer_Tick(object sender, EventArgs e)
{
if (!new Rectangle(new Point(0, 0), listBox3.Size).Contains(listBox3.PointToClient(Control.MousePosition)))
{
visibleTimer.Stop();
button1.Visible = false;
}
}
My form doesn't have a title bar, so I am implementing the code to drag
the entire form around the screen. I am using the below code to do it, which works fine.
I have two panels in my form, PanelA and PanelB. During the startup I show
PanelA where the dragging works perfectly. Later when the user clicks
the button in PanelA, I need to make PanelA invisible and show PanelB
However, the dragging does not work when PanelB is shown. What's the
problem here?
private void SerialPortScanner_MouseUp(object sender, MouseEventArgs e)
{
this.drag = false;
}
private void SerialPortScanner_MouseDown(object sender, MouseEventArgs e)
{
this.drag = true;
this.start_point = new Point(e.X, e.Y);
}
private void SerialPortScanner_MouseMove(object sender, MouseEventArgs e)
{
if (this.drag)
{
Point p1 = new Point(e.X, e.Y);
Point p2 = this.PointToScreen(p1);
Point p3 = new Point(p2.X - this.start_point.X,
p2.Y - this.start_point.Y);
this.Location = p3;
}
}
Edit: I've realized that you're not asking about drag and drop, but rather about moving your form around the screen. (Thanks to #Veer.) I've edited your question to help clarify this. Drag and drop is a completely different thing, since it is dragging information from one control to another.
The same principle of my answer still applies though, since mouse events are also handled at the Control level - you might need to handle the mouse events from PanelB as well.