处理表单标题栏上的鼠标悬停 - 在工具提示中显示最小化 MDI 的标题 Child

Handle Mouse Hover on Titlebar of Form - Show Title of a Minimized MDI Child in ToolTip

我正在寻找类似 WM_NCMOUSEMOVE 的消息,表示鼠标悬停在表单的标题栏上。

目前我已经将此代码放入 child 表单中,但问题是它们有很多 child 表单,而且它不处理标题栏上的鼠标悬停:

Private Const WM_NCMOUSEMOVE = &HA0
Dim stado_min As Boolean

Protected Overrides Sub DefWndProc(ByRef m As System.Windows.Forms.Message)
    If stado_min AndAlso CLng(m.Msg) = WM_NCMOUSEMOVE Then 
        form_principal.ToolTipTitulo.SetToolTip(Me, Label1.Text)
    End If
    MyBase.DefWndProc(m)
End Sub

Private Sub schanged() Handles MyBase.SizeChanged
    stado_min = (Me.WindowState = FormWindowState.Minimized)
End Sub

事实上,我正在寻找一种解决方案,当鼠标悬停在最小化的 MDI child 上时,在工具提示中显示 MDI child 的标题。我该怎么做?

要处理鼠标悬停在 non-client 区域上,您可以捕获 WM_NCMOUSEHOVER in WndProc。 如文档中所述,当生成此消息时,悬停跟踪将停止。如果应用程序需要进一步跟踪鼠标悬停行为,则必须再次调用 TrackMouseEvent

NonClientMouseHover 事件实现

在下面的代码中,通过捕获 WM_NCMOUSEHOVER 引发了 NonClientMouseHover。您可以像处理任何其他形式的事件一样处理 NonClientMouseHover 事件:

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);
        }
    }
}

例子

根据您的问题,您似乎对最小化 mdi child window 的事件感兴趣。该事件还会针对最小化的 mdi child 表单引发,因此如果出于任何原因您想在鼠标悬停在最小化的 mdi child 的标题栏上时执行某些操作,您可以检查 if(((Form)sender).WindowState== FormWindowState.Minimized)。另外 ((Form)sender).Text 是引发事件的表单的文本。

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);
    }
}

注:感谢Bob for his post here。用于处理 WM_NCMOUSEHOVER 的初始代码取自那里并进行了一些更改并删除了一些部分。