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

1

1

I'm looking for a message like WM_NCMOUSEMOVE that represents the mouse is hovering on title bar of a form.

Currently I've put this code in child forms, but the problem is that they are many child forms and also it doesn't handle a mouse hover on title bar:

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

In fact I'm looking for a solution to show title of an MDI child in tooltip when the mouse hovers over the minimized MDI child. How can I do that?

Ultima answered 18/11, 2016 at 15:15 Comment(12)
why are you using DefWndProc instead of Form.MouseHover ?Balmung
The OP is trying to handle mouse hover on non-client area. And surely the question doesn't deserve a downvote even if they are using the wrong way.Ovariectomy
There aren't downvotes in this question.Balmung
@Reza - you are a very smart guy. Please use your talents to explain how you could hover the title bar on a minimized window or why an MDI window requires a tooltip when the title bar already displays its name. We'll need that kind of help to make sense of the question.Toscanini
in c# exists any tool similar to "AutoIt3 Window Spy" but get and dysplay current m System.Windows.Forms.Message?Ultima
I only try to clarify the question, because I think neither "DefWndProc" or "OnMouseOver" will not detect mouse events on form's caption. Time ago, there was a tool that identify HWND id, by simply hover the mouse over windows/controls. Maybe I'm wrong, but I think MdiParentForm should capture the mouse to get this messages.Balmung
Just in case you want to try, there is an article in CodeProject that maybe can help you in this task. codeproject.com/Articles/7294/…Balmung
@HansPassant The screenshot in the answer shows a sample usage of WM_NCMOUSEHOVER.Ovariectomy
MDI application are considered obsolete from long ago... Why not using a tabbed MDI interface instead and never have minimized child.Tabescent
@HansPassant After I created the example I saw the title-bar of minimized MDI child form doesn't show the title, so showing a tooltip containing the title seems reasonable, may be not the best solution. I also edited the question to be more clear for future readers. Let me know if you have any idea about it.Ovariectomy
@HansPassant By the way, I removed my comment based on your comment. Hope to see just technical feedback and debates which makes the site better and be useful for users. Regards :)Ovariectomy
@HansPassant If a minimized window is too small to show the title it could be useful to show it on hover.Kaceykachina
O
4

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

enter image description here

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.

Ovariectomy answered 18/11, 2016 at 18:12 Comment(2)
Excellent to that I was referring, is it possible add implement NonClientMouseMove event?Ultima
Yes, it's possible. Just declare public event EventHandler NonClientMouseMove; and check when m.Msg == WM_NCMOUSEMOVE then raise the event like I did for NonClientMouseHover. Also if you take a look at Bob's post you will see an implementation of NonClientMouseMove which its event args contains mouse position as well.Ovariectomy

© 2022 - 2024 — McMap. All rights reserved.