none
Hooking WM_GESTURE and WM_GESTURENOTIFY messages. RRS feed

  • Question

  • I have been unable to capture GESTURE messages for all threads in the desktop. 

    Here is my code in my DLL, but the only window that gets hooked is the window that initially opens the DLL and calls this function, and I seem to get WM_GESTURE messages just fine. I do not seem to be getting WM_GESTURENOTIFY messages. How can I register for them? I'm missing something basic here.

    So, I have two problems: 1) I am unable to hook messages for all threads in the desktop, and 2), I don't seem to be able to get WM_GESTURENOTIFY messeages at all. (anyone have the source to the Visual Studio Spy++ tool :) )

     

        __declspec(dllexport) bool setGestureHook(void)
        {
            g_hookGesture = SetWindowsHookEx(
                WH_GETMESSAGE,
                HookGestures,
                g_hModule,
                0);
            if (g_hookGesture) OutputDebugString(L"Gestures Hooked\n");
            return g_hookGesture != 0;
        }


    Joe Waclawski

    • Edited by Joe Wac Tuesday, January 17, 2012 5:20 PM
    Monday, January 16, 2012 3:10 PM

Answers

  • That should set a global hook. Remember that the hook is called in the thread that is receiving the message, so if you're looking at debug output for only your main app you won't see the hook being called elsewhere. You will need to set up some sort of shared memory and IPC system to let your central app know about the messages received elsewhere.

    That said, I wouldn't expect that hook to see either WM_GESTURE or WM_GESTURENOTIFY. These are both sent rather than posted and so won't show up in a WH_GETMESSAGE hook. You would need a WH_CALLWNDPROC or WH_CALLWNDPROCRET hook.

    Spy++ sets all three of these hook types and you can see which type saw a specific message by if it is flagged P (posted - WH_GETMESSAGE), S (sent - WH_CALLWNDPROC), or R (returned - WH_CALLWNDPROCRET).

    As far as hooking gestures go, what is your goal? There isn't any good way to capture gesture information globally. Not all windows will get gesture information (some get touch information) and your hook cannot get the gesture information without interfering with windows which are trying to handle the gesture information itself.

    --Rob

     

    • Marked as answer by Joe Wac Wednesday, January 18, 2012 2:42 PM
    Wednesday, January 18, 2012 2:13 AM

All replies

  • That should set a global hook. Remember that the hook is called in the thread that is receiving the message, so if you're looking at debug output for only your main app you won't see the hook being called elsewhere. You will need to set up some sort of shared memory and IPC system to let your central app know about the messages received elsewhere.

    That said, I wouldn't expect that hook to see either WM_GESTURE or WM_GESTURENOTIFY. These are both sent rather than posted and so won't show up in a WH_GETMESSAGE hook. You would need a WH_CALLWNDPROC or WH_CALLWNDPROCRET hook.

    Spy++ sets all three of these hook types and you can see which type saw a specific message by if it is flagged P (posted - WH_GETMESSAGE), S (sent - WH_CALLWNDPROC), or R (returned - WH_CALLWNDPROCRET).

    As far as hooking gestures go, what is your goal? There isn't any good way to capture gesture information globally. Not all windows will get gesture information (some get touch information) and your hook cannot get the gesture information without interfering with windows which are trying to handle the gesture information itself.

    --Rob

     

    • Marked as answer by Joe Wac Wednesday, January 18, 2012 2:42 PM
    Wednesday, January 18, 2012 2:13 AM
  • Rob,

    Thanks for the response. I am now setting a global hook of WH_CALLWNDPROC, and getting the results I need. That is, I am hooking the Gesture messages. The ultimate goal is to sniff these messages, record them, and re-inject them into an application on a remote machine in real time, or at a later time. This will allow the record/playback of user input, for multiple purposes. One of which is laying the ground work for automated testing. Another is the ability to use user input devices across multiple computers. Thus far, I have keyboard and mouse working. I am now working on Touch (Gestures).

    Since we are working in a controlled environment, we know the behavior of the applications of interest, and we can control whether they receive Touch or Gestures (usually). But we still will have to deal with applications that register for touch. Currently, I am working on Gestures. Being able to do Touch would be much better, but I think Touch is a bit more complicated. I have found no way of injecting Touch messages back into the system to allow them to cause the Gesture engine to create Gestures. Can you provide any incite into that?

    Thanks

    Joe Wac

    • Edited by Joe Wac Wednesday, January 18, 2012 2:43 PM
    Wednesday, January 18, 2012 2:42 PM
  • Hi Joe,

    Windows 7 doesn't provide any way to inject touch or gesture messages. They can only be generated from the driver level. Windows 8 does provide an InjectTouchInput function for testing or accessibility apps, but there's no equivalent on Windows 7.

    --Rob

    Saturday, January 21, 2012 3:36 AM
  • Hi,

    could you tell me please how you finally hook the gesture messages?

    Do you filter the messages from the WH_CALLWNDPROC hook?

    Thanks

    Alexander

    Friday, March 16, 2012 9:39 AM
  • Alexander,

    Sorry it's been so long. But just to close the loop:


        __declspec(dllexport) bool setTouchHook(DWORD threadID)
        {
            g_hookTouch = SetWindowsHookEx(
                WH_CALLWNDPROC,
                HookTouch,
                g_hModule,
                threadID);
            if (g_hookTouch) OutputDebugString(L"Touch Hooked\n");
            return g_hookTouch != 0;
       

    LRESULT CALLBACK HookTouch(int nCode, WPARAM wParam, LPARAM lParam)
    {
        // per documentation, must pass on without handling
        if (nCode < 0) return CallNextHookEx(0,nCode, wParam, lParam);

        if (nCode == HC_ACTION)
        {
            wsprintf(debugString,L"Received Message: 0x%x\n",((PCWPSTRUCT)lParam)->message);
            OutputDebugString(debugString);
            switch(((PCWPSTRUCT)lParam)->message)
            {
            case WM_TOUCH:
                OutputDebugString(L"Hooked WM_TOUCH message\n");

                // do something useful with the data

               break;

            case WM_GESTURENOTIFY:
                OutputDebugString(L"Hooked WM_GESTURENOTIFY message\n");   

                // do something usefule with the data

                break;
      

         //case WM_GESTURE:
                ZeroMemory(&g_gestureInfo, sizeof(GESTUREINFO));
                g_gestureInfo.cbSize = sizeof(GESTUREINFO);
                BOOL result = GetGestureInfo((HGESTUREINFO)((PCWPSTRUCT)lParam)->lParam,&g_gestureInfo);
                if (!result)
                {
                    // could not get details of gesture
                    OutputDebugString(L"GetTouchInfo() failed\n");
                }
                else
                {
                    wsprintf(debugString,L"WM_GESTURE: instanceID=%d sequenceID=%d x=%d y=%d\n",
                        g_gestureInfo.dwInstanceID,
                        g_gestureInfo.dwSequenceID,
                        g_gestureInfo.ptsLocation.x,
                        g_gestureInfo.ptsLocation.y);
                     OutputDebugString((LPCWSTR)debugString);

                     // do something useful with the data

                }
                break;
            }
        }
        return CallNextHookEx(0,nCode, wParam, lParam);
    }




    Joe Waclawski

    Monday, May 7, 2012 7:25 PM
  • Hi , Joe:

         Do you use those codes to hook touch/gesture message successfully? 

    Why can't I sniff  touch/gesture message?

    Monday, October 21, 2013 6:27 AM
  • Hello Will,

    It will not work because to getting the touch messages you need to install the hook for WH_MOUSE_LL.

    Please refer the below code.

    extern "C" __declspec(dllexport) void install()
    {
    g_hTouchHook = SetWindowsHookEx(WH_MOUSE_LL, GetMsgProc, g_hModule, 0);
    }

    extern "C" __declspec(dllexport) void uninstall()
    {
    UnhookWindowsHookEx(g_hTouchHook);
    }

    LRESULT CALLBACK GetMsgProc(int nCode, WPARAM wParam, LPARAM lParam)
    {
    static int iCallCounter = { 0 };

    if (0 > nCode)
    {
    return CallNextHookEx(NULL, nCode, wParam, lParam);
    }

    if (nCode == HC_ACTION || nCode > HC_ACTION)
    {
    if (IsTouchMessage(lParam))
    {
    if (0 == ((++iCallCounter) % 3))
    {
    g_TouchCounter++;
    WriteTouchCounterToFile(g_hTouchFile, g_TouchCounter);
    WCHAR szBuffer[MAX_PATH] = { 0 };
    wsprintf(szBuffer, L"Touch counder is %u", g_TouchCounter);
    OutputDebugString(szBuffer);
    iCallCounter = 0;
    }

    }
    }

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

    BOOL IsTouchMessage(LPARAM lParam)
    {
    BOOL bRetVal = FALSE;
    PMSLLHOOKSTRUCT pInfo = (PMSLLHOOKSTRUCT)lParam;
    ULONG ulExtraInfo = pInfo->dwExtraInfo;
    ULONG value = (pInfo->dwExtraInfo & MOUSEEVENTF_FROMTOUCH);


    if ((pInfo->dwExtraInfo & MOUSEEVENTF_FROMTOUCH) == MOUSEEVENTF_FROMTOUCH)
    bRetVal = TRUE;

    return bRetVal;
    }


    Tuesday, February 5, 2019 4:54 PM