Can the hover interval be changed?

后端 未结 3 1529
失恋的感觉
失恋的感觉 2021-01-18 15:18

I have code that allows a user to hover over a control, and it will respond. However, I\'d like the hovering to fire a little quicker. Is there a way to speed up the hover r

3条回答
  •  旧巷少年郎
    2021-01-18 15:36

    Yes you can. The hover in Windows Forms is not following the global system setting and it has been set in NativeMethods.TRACKMOUSEEVENT to 100 milliseconds in the dwHoverTime field.

    Then in WndProc method of the native window of the control, WM_MOUSEMOVE has been trapped to call TrackMouseEvent which in turn cause a WM_MOUSEHOVER. You can see the source code here.

    So you can handle WM_MOUSEMOVE and call TrackMouseEvent by setting desired timeout for mouse hover as dwHoverTime field of the TRACKMOUSEEVENT. Also handle WM_MOUSEHOVER and raise a custom event like MyMouseHover.

    Then you can easily handle this custom MyMouseHover event.

    using System;
    using System.Runtime.InteropServices;
    using System.Windows.Forms;
    public class SampleControl : Control
    {
        [DllImport("user32.dll")]
        private static extern int TrackMouseEvent(ref TRACKMOUSEEVENT lpEventTrack);
        [StructLayout(LayoutKind.Sequential)]
        private struct TRACKMOUSEEVENT
        {
            public uint cbSize;
            public uint dwFlags;
            public IntPtr hwndTrack;
            public uint dwHoverTime;
            public static readonly TRACKMOUSEEVENT Empty;
        }
        private TRACKMOUSEEVENT track = TRACKMOUSEEVENT.Empty;
        const int WM_MOUSEMOVE = 0x0200;
        const int WM_MOUSEHOVER = 0x02A1;
        const int TME_HOVER = 0x1;
        const int TME_LEAVE = 0x2;
        public event EventHandler MyMouseHover;
        protected override void WndProc(ref Message m)
        {
            if (m.Msg == WM_MOUSEMOVE)
            {
                track.hwndTrack = this.Handle;
                track.cbSize = (uint)Marshal.SizeOf(track);
                track.dwFlags = TME_HOVER | TME_LEAVE;
                track.dwHoverTime = 500;
                TrackMouseEvent(ref track);
            }
            if(m.Msg == WM_MOUSEHOVER)
            {
                MyMouseHover?.Invoke(this, EventArgs.Empty);
            }
            base.WndProc(ref m);
        }
    }
    

    Notes

    • The system-wide SystemInformation.MouseHoverTime setting is used for ToolTip. But the MouseHover event is following the value of dwHoverTime field of NativeMethods.TRACKMOUSEEVENT which is set to 100 milliseconds.

    • You can find a similar implementation in my post for handling hover event on title bar of a form: Handle Mouse Hover on Titlebar of Form.

    • As another option I also tried setting value of dwHoverTime field of the private trackMouseEvent field of the control and this solution also seems to be working.

    • You can find VB version of the code here.

提交回复
热议问题