The Scene: A (smallish) Form hosting a UserControl.
The Plot: Whenever UserControl raises a hover event, display some (graphical) information in a tool tip fashion. When the user moves the mouse, fade them away again.
Notes: I'd like to display more than one "tooltip", with each tooltip being a UserControl displaying information in a graphical manner. Not just text in a yellow box! Also, I'm using the Windows.Forms library.
This is what I have so far:
private void myControl_Hovered(object sender, MyEventArgs e)
{
var tooltip = new MyToolTip();
Controls.Add(tooltip);
tooltip.UpdateDisplay(e.Data);
tooltip.Show();
}
But it shows up in the background (I can handle that) and, sadly, is confined to the window...
EDIT: Here is what I ended up doing...
I could not get the ToolTip
control provided with .NET to work. This is mainly, because I'm trying to show tooltips for "hot spots" in a user drawn control (think a plot of function points, show additional items for the points). The ToolTip control would really like to only show when a user first enters a control - manually showing it does not seem to work. I tried. Long and hard.
So, this ToolTipWindow
class can be used to show a control in a frameless window. I have added an Offset
property, so it can be shown at an offset to the current mouse position.
/// <summary>
/// A tooltip class to display some information from a control.
/// </summary>
internal class ToolTipWindow: Form
{
/// <summary>
/// The offset from the mouse pointer to show the window at.
/// </summary>
public Point Offset { get; set;}
internal ToolTipWindow(Control controlToDisplay)
{
FormBorderStyle = FormBorderStyle.None;
TopMost = true;
ShowInTaskbar = false;
Opacity = 0.9;
Width = controlToDisplay.Width;
Height = controlToDisplay.Height;
Controls.Add(controlToDisplay);
controlToDisplay.Show();
}
/// <summary>
/// Move the window to an offset of mouse pointer.
/// </summary>
protected override void OnShown(EventArgs e)
{
base.OnShown(e);
Location = new Point(MousePosition.X + Offset.X, MousePosition.Y + Offset.Y);
}
/// <summary>
/// Move the window to an offset of mouse pointer.
/// </summary>
protected override void OnVisibleChanged(EventArgs e)
{
base.OnVisibleChanged(e);
if (Visible)
{
Location = new Point(MousePosition.X + Offset.X, MousePosition.Y + Offset.Y);
}
}
}
To show the tooltip, you can catch the MouseHover
and MouseMove
events. Check first, if you are above a "hot spot" and show the tooltip. In MouseMove
, hide the tooltips if you are not above a "hot spot". Also, on closing the window, make sure you also close all tooltip windows!
Note: The MouseHover
event will only show up the first time the mouse enters a control. If you want it to show up repeatedly (as in the case of detecting "hot spots"), you should add code like the following to the control containing the "hot spots":
#region AddReHoverExperience
// ReSharper disable InconsistentNaming
// found this code here: http://www.pinvoke.net/default.aspx/user32.TrackMouseEvent
[DllImport("user32.dll")]
static extern int TrackMouseEvent(ref TRACKMOUSEEVENT lpEventTrack);
[StructLayout(LayoutKind.Sequential)]
public struct TRACKMOUSEEVENT
{
public UInt32 cbSize;
public UInt32 dwFlags;
public IntPtr hwndTrack;
public UInt32 dwHoverTime;
}
TRACKMOUSEEVENT tme;
private const uint TME_HOVER = 0x1;
protected override void OnMouseHover(EventArgs e)
{
base.OnMouseHover(e);
OnMouseEnter(e);
}
protected override void OnMouseEnter(EventArgs e)
{
base.OnMouseEnter(e);
tme = new TRACKMOUSEEVENT
{
hwndTrack = Handle,
dwFlags = TME_HOVER,
dwHoverTime = 500
};
tme.cbSize = (uint)Marshal.SizeOf(tme);
TrackMouseEvent(ref tme);
}
// ReSharper restore InconsistentNaming
#endregion AddReHoverExperience