0
public class InputHook
{
    #region Windows function imports

    [DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall, SetLastError = true)]
    private static extern int SetWindowsHookEx(int idHook, HookProc lpfn, IntPtr hMod, int dwThreadId);

    [DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall, SetLastError = true)]
    private static extern int UnhookWindowsHookEx(int idHook);

    [DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
    private static extern int CallNextHookEx(int idHook, int nCode, int wParam, IntPtr lParam);

    [DllImport("kernel32.dll", CharSet = CharSet.Auto)]
    public static extern IntPtr GetModuleHandle(string lpModuleName);

    [DllImport("user32.dll")]
    internal static extern IntPtr GetActiveWindow();
    [DllImport("user32.dll", EntryPoint = "TrackMouseEvent", CallingConvention = CallingConvention.StdCall)]
    private extern static bool Win32TrackMouseEvent(ref TRACKMOUSEEVENT tme);

    private delegate int HookProc(int nCode, int wParam, IntPtr lParam);

    #endregion

    #region Windows constants

    // ReSharper disable InconsistentNaming
    private const int WH_MOUSE_LL = 14;
    private const int WH_MOUSE = 7;
    private const int WH_GETMESSAGE = 3;
    private const int WM_MOUSEMOVE = 0x200;
    private const int WM_MOUSEHOVER = 0x2A1;
    private const int GWL_WNDPROC = -4;
    private const int WM_IME_SETCONTEXT = 0x281;
    private const int WM_INPUTLANGCHANGE = 0x51;
    private const int WM_GETDLGCODE = 0x87;
    private const int WM_IME_COMPOSITION = 0x10F;
    private const int DLGC_WANTALLKEYS = 4;

    private const int TID_POLLMOUSE = 100;
    private const int MOUSE_POLL_DELAY = 500;
    private const int WM_TIMER = 0x0113;
    private const int WM_MOUSEENTER = 0x41E;
    private const int WM_MOUSELEAVE = 0x41F;
    // ReSharper restore InconsistentNaming

    #endregion

    #region Events

    /// <summary>Event raised when the mouse has hovered in the same location for a short period of time.</summary>
    public event MouseEventHandler MouseHover;

    #endregion

    public InputHook(bool installMouseHook = true)
    {
        Start(installMouseHook);
    }

    ~InputHook()
    {
        Stop(true, false);
    }

    private int m_hMouseHook;

    private static HookProc s_mouseHookProcedure;

    private void Start(bool installMouseHook)
    {
        // install Mouse hook only if it is not installed and must be installed
        if(m_hMouseHook == 0 && installMouseHook)
        {
            s_mouseHookProcedure = MouseHookProc;
            m_hMouseHook = SetWindowsHookEx(WH_MOUSE, s_mouseHookProcedure, (IntPtr)0, AppDomain.GetCurrentThreadId());

            if(m_hMouseHook == 0)
            {
                var errorCode = Marshal.GetLastWin32Error();
                Stop(true, false);
                throw new Win32Exception(errorCode);
            }
        }
    }

    public void Stop(bool uninstallMouseHook = true, bool throwExceptions = true)
    {
        if(m_hMouseHook != 0 && uninstallMouseHook)
        {
            var retMouse = UnhookWindowsHookEx(m_hMouseHook);
            m_hMouseHook = 0;
            if(retMouse == 0 && throwExceptions)
            {
                var errorCode = Marshal.GetLastWin32Error();
                throw new Win32Exception(errorCode);
            }
        }
    }

    #region Mouse Input

    private int MouseHookProc(int nCode, int wParam, IntPtr lParam)
    {
        if((nCode >= 0) && (MouseHover != null))
        {
            short x, y;
            MouseLocationFromLParam(lParam.ToInt32(), out x, out y);

            switch(wParam)
            {
                case WM_MOUSEMOVE:
                    TRACKMOUSEEVENT tme = new TRACKMOUSEEVENT();
                    tme.cbSize = Marshal.SizeOf(tme);
                    tme.dwFlags = TMEFlags.TME_HOVER;
                    tme.dwHoverTime = 100;
                    tme.hwndTrack = lParam;
                    Win32TrackMouseEvent(ref tme);
                    break;
                case WM_MOUSEHOVER:
                    if(MouseHover != null)
                        MouseHover(null, new MouseEventArgs(MouseButtons.None, 0, x, y, 0));
                    break;
            }
        }

        return CallNextHookEx(m_hMouseHook, nCode, wParam, lParam);
    }

    #endregion

    #region Mouse Message Helpers

    private static void MouseLocationFromLParam(int lParam, out short x, out short y)
    {
        // Cast to signed shorts to get sign extension on negative coordinates (of course this would only be possible if mouse capture was enabled).
        x = (short)(lParam & 0xFFFF);
        y = (short)(lParam >> 16);
    }

    #endregion

    [StructLayout(LayoutKind.Sequential)]
    private struct TRACKMOUSEEVENT
    {
        internal int cbSize;
        internal TMEFlags dwFlags;
        internal IntPtr hwndTrack;
        internal int dwHoverTime;
    }

    [Flags]
    private enum TMEFlags
    {
        TME_HOVER = 0x00000001,
        TME_LEAVE = 0x00000002,
        TME_NONCLIENT = 0x00000010,
        TME_QUERY = unchecked((int)0x40000000),
        TME_CANCEL = unchecked((int)0x80000000)
    }
}

マウスホバーイベントにこのクラスを使用しています。しかし、どういうわけかこれは機能していません。移動やその他のマウスイベントでは完全に機能しますが、マウスホバーではとにかく使用できません。オンラインのすべてを試しましたが、何もしませんでした。これのどこが間違っているのですか?

これを手伝ってくれてありがとう。

4

2 に答える 2

1

WM_MOUSEHOVERは真のマウス メッセージではなく、呼び出し時に確立される内部タイマー プロシージャによって生成されますTrackMouseEvent(マウスが移動したかどうかを確認し、指定された時間静止している場合はウィンドウにメッセージを送信します)。したがって、WH_MOUSEフックはそれをトラップしません。

WH_CALLWNDPROCまたはWH_GETMESSAGEフックでキャッチできる可能性があります。

于 2013-07-02T00:09:40.997 に答える
0

MouseHookProc()( )の最後のパラメーターlParamは実際にはHWNDポインターではなく、MOUSEHOOKSTRUCT無効な有効なものをに渡しますtme.hwndTrack

関連する MSDN ページを参照してください。

それが唯一のバグかどうかはわかりません。

于 2013-07-01T16:47:50.983 に答える