To handle a mouse hover over non-client area, you can trap WM_NCMOUSEHOVER
in WndProc
.
As mentioned in documentations hover tracking stops when this message is generated. The application must call TrackMouseEvent
again if it requires further tracking of mouse hover behavior.
NonClientMouseHover Event Implementation
In below code, a NonClientMouseHover
has been raised by trapping WM_NCMOUSEHOVER
. You can handle NonClientMouseHover
event like any other events of the form:
using System;
using System.Runtime.InteropServices;
using System.Windows.Forms;
public class SampleForm : Form
{
[DllImport("user32.dll")]
private static extern int TrackMouseEvent(ref TRACK_MOUSE_EVENT lpEventTrack);
[StructLayout(LayoutKind.Sequential)]
private struct TRACK_MOUSE_EVENT {
public uint cbSize;
public uint dwFlags;
public IntPtr hwndTrack;
public uint dwHoverTime;
public static readonly TRACK_MOUSE_EVENT Empty;
}
private TRACK_MOUSE_EVENT track = TRACK_MOUSE_EVENT.Empty;
const int WM_NCMOUSEMOVE = 0xA0;
const int WM_NCMOUSEHOVER = 0x2A0;
const int TME_HOVER = 0x1;
const int TME_NONCLIENT = 0x10;
public event EventHandler NonClientMouseHover;
protected override void WndProc(ref Message m)
{
base.WndProc(ref m);
if (m.Msg == WM_NCMOUSEMOVE) {
track.hwndTrack = this.Handle;
track.cbSize = (uint)Marshal.SizeOf(track);
track.dwFlags = TME_HOVER | TME_NONCLIENT;
track.dwHoverTime = 500;
TrackMouseEvent(ref track);
}
if (m.Msg == WM_NCMOUSEHOVER) {
var handler = NonClientMouseHover;
if (handler != null)
NonClientMouseHover(this, EventArgs.Empty);
}
}
}
Example
Based on your question it seems you are interested to the event for a minimized mdi child window. The event also raises for a minimized mdi child form, so if for any reason you want to do something when the mouse hover title bar of a minimized mdi child, you can check if(((Form)sender).WindowState== FormWindowState.Minimized)
. Also ((Form)sender).Text
is text of the form which raised the event.
public partial class Form1 : Form
{
ToolTip toolTip1 = new ToolTip();
public Form1()
{
//InitializeComponent();
this.Text = "Form1";
this.IsMdiContainer = true;
var f1 = new SampleForm() { Text = "Some Form", MdiParent = this };
f1.NonClientMouseHover += child_NonClientMouseHover;
f1.Show();
var f2 = new SampleForm() { Text = "Some Other Form", MdiParent = this };
f2.NonClientMouseHover += child_NonClientMouseHover;
f2.Show();
}
void child_NonClientMouseHover(object sender, EventArgs e)
{
var f = (Form)sender;
var p = f.PointToClient(f.Parent.PointToScreen(f.Location));
p.Offset(0, -24);
toolTip1.Show(f.Text, f, p, 2000);
}
protected override void OnFormClosed(FormClosedEventArgs e)
{
toolTip1.Dispose();
base.OnFormClosed(e);
}
}
Note: Thanks to Bob for his post here. The initial code for handling WM_NCMOUSEHOVER
has taken from there and made working with some changes and removing some parts.