0

I've tried using RegisterPointerInputTarget (Win32 API) to capture all PT_TOUCH messages, but my app behaves exactly as if the function was never called. I've followed all advice I could find: the app has uiAccess=true, is signed, and is installed to C:\Program Files. The windows is created as a child of HWND_MESSAGE and the RegisterPointerInputTarget returns 1. However, my WndProc is not receiving any WM_POINTER messages at all. If I instead create a normal window, my WndProc receives WM_POINTER messages as expected, only when I'm pointing over the window.

Below is the code of my program. Note that the calls to InitializeTouchInjection, ShowWindow, UpdateWindow and AccSetRunningUtilityState should be unnecessary, I've just been trying everything I've seen in any example I could find.

I'm using a Wacom Intuos, tried both with the pen and with the fingers.

#include "pch.h"
#include <iostream>
#include <Windows.h>
#include "oleacc.h"

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    switch (message)
    {
        case WM_NCPOINTERUP:
        case WM_NCPOINTERDOWN:
        case WM_NCPOINTERUPDATE:
        case WM_TOUCH:
        case WM_POINTERDOWN:
        case WM_POINTERUP:
        case WM_POINTERUPDATE:
        {
            std::cout << "TOUCH MESSAGE " << message << " WPARAM " << wParam << " LPARAM " << lParam << std::endl;
            break;
        }
    }
    std::cout << "SOME MESSAGE " << message << " HWND " << hWnd << " WPARAM " << wParam << " LPARAM " << lParam << std::endl;
    return DefWindowProc(hWnd, message, wParam, lParam);
}

int main()
{
    //InitializeTouchInjection(10, TOUCH_FEEDBACK_NONE);

    LPCSTR className = "TouchHookWindow";
    HINSTANCE hInstance = GetModuleHandle(NULL);

    WNDCLASS wc;
    memset(&wc, 0, sizeof(wc));
    wc.lpfnWndProc = WndProc;
    wc.hInstance = hInstance;
    //wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
    //wc.hIcon = LoadIcon(NULL, IDI_WINLOGO);
    //wc.hCursor = LoadCursor(NULL, IDC_ARROW);
    wc.lpszClassName = className;

    if (!RegisterClass(&wc))
    {
        std::cout << "Failed to register window class!\n";
        return -1;
    }

    DWORD dwExStyle = WS_EX_APPWINDOW | WS_EX_WINDOWEDGE;
    DWORD dwStyle = WS_OVERLAPPEDWINDOW;

    //DWORD dwExStyle = WS_EX_NOACTIVATE;// | WS_EX_TRANSPARENT;
    //DWORD dwStyle = WS_OVERLAPPEDWINDOW;

    RECT rc;
    rc.left = 0;
    rc.top = 0;
    rc.right = 100;
    rc.bottom = 100;
    AdjustWindowRectEx(&rc, dwStyle, FALSE, dwExStyle);

    //HWND hWnd = CreateWindowEx(dwExStyle, className, "Touch Hook", dwStyle, 0, 0, rc.right-rc.left, rc.bottom-rc.top, NULL, NULL, hInstance, NULL);
    HWND hWnd = CreateWindowEx(0, className, "TouchHook", 0, 0, 0, 0, 0, HWND_MESSAGE, NULL, hInstance, NULL);
    //HWND hWnd = CreateWindowEx(dwExStyle, className, "TouchHook", dwStyle, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, HWND_MESSAGE, NULL, hInstance, NULL);
    //HWND hWnd = CreateWindowEx(dwExStyle, className, "TouchHook", dwStyle, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hInstance, NULL);
    if (!hWnd)
    {
        std::cout << "Failed to create window!\n";
        return -1;
    }

    //ShowWindow(hWnd, SW_SHOW);
    //UpdateWindow(hWnd);
    //SetForegroundWindow(hWnd);
    //SetFocus(hWnd);
    {
        BOOL result = RegisterTouchWindow(hWnd, 0);
        std::cout << "RegisterTouchWindow result " << result << std::endl;
    }
    {
        BOOL result = RegisterPointerInputTarget(hWnd, PT_TOUCH);
        std::cout << "RegisterPointerInputTarget result " << result << std::endl;
    }

    {
        //HRESULT hr = AccSetRunningUtilityState(hWnd, ANRUS_TOUCH_MODIFICATION_ACTIVE, ANRUS_TOUCH_MODIFICATION_ACTIVE);
        //std::cout << "AccSetRunningUtilityState " << (FAILED(hr) ? "FAILED" : "SUCCESS") << std::endl;
    }

    {
        MSG msg;
        BOOL result;
        while (result = GetMessage(&msg, NULL, 0,0) != 0)
        {
            if (result != -1)
            {
                if (msg.message == WM_QUIT)
                {
                    break;
                }
                else
                {
                    TranslateMessage(&msg);
                    DispatchMessage(&msg);
                }
            }
        }
    }


    return 0;
}
  • Did you notice the return value of `BOOL result = RegisterPointerInputTarget(hWnd, PT_TOUCH)`? I checked through `GetLasterror` that return 5, it means `access was denied`. – Strive Sun Sep 17 '19 at 06:13
  • A similar case :https://stackoverflow.com/questions/56264636/registerpointerinputtarget-not-consuming-all-input – Strive Sun Sep 17 '19 at 06:19
  • Yes the return value is 1 which means SUCCESS. I said that in my original post. The reason you are getting access denied is you are missing the other steps like signing the app and installing it into a trusted location. I’ve done all of those steps and it still doesn’t work. Also, the other issue you linked is a different problem. I can’t even get the redirection to work at all. – user1497526 Sep 17 '19 at 09:14
  • Unfortunately, I can't replicate your question. I'm trying to set `UIAccess = true`, but failed. Besides, can you accept WM_TOUCH message events? – Strive Sun Sep 18 '19 at 10:18
  • WM_TOUCH only works within my window, if I create a normal window instead of 0-sized HWND_MESSAGE child, same as WM_POINTER. If you want to be able to run with UIAccess = true use the following steps: – user1497526 Sep 19 '19 at 13:31
  • Run this once to create and install a certificate (substitute your WinSDK path): `"C:\Program Files (x86)\Microsoft SDKs\Windows\v7.1A\Bin\makecert.exe" -r -pe -n "CN=Test Certificate" -ss PrivateCertStore testcert.cer` `"C:\Program Files (x86)\Microsoft SDKs\Windows\v7.1A\Bin\certmgr.exe" -add testcert.cer -s -r currentUser root` – user1497526 Sep 19 '19 at 13:31
  • Run this every time you rebuild the app to sign the exe (substitute your exe path): `"C:\Program Files (x86)\Microsoft SDKs\Windows\v7.1A\Bin\signtool" sign /v /s PrivateCertStore /n "Test Certificate" /t http://timestamp.verisign.com/scripts/timestamp.dll Test.exe` – user1497526 Sep 19 '19 at 13:31
  • Then move the exe into C:\Program Files\ and run it from there. RegisterPointerInputTarget should then return 1, but it still doesn't work for me. – user1497526 Sep 19 '19 at 13:32
  • hi, Thank you for the details. I have been able to reproduce the problems you have encountered.After some research, I found that a message-only window enables you to send and receive messages. It is not visible, has no z-order, cannot be enumerated, and does not receive broadcast messages. The window simply dispatches messages. Refer [this](https://stackoverflow.com/a/21141386/11128312). So I suspect that touch input events are incompatible with message windows only. Please refer [this](https://stackoverflow.com/questions/10721462/how-to-get-wm-touch-messages-in-a-message-only-window). – Strive Sun Sep 20 '19 at 09:17
  • Okay, but this doesn't work for me even if I create a normal window (not a message-only window) as I described in the OP. Have you ever been able to get RegisterPointerInputTarget to work in any way at all? When I create a normal window I still only get WM_POINTER events within my window, not everywhere else on the screen, as I would expect after calling RegisterPointerInputTarget. – user1497526 Sep 25 '19 at 12:33
  • No, It only worked in my own window after the test. I looked at the [document](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-registerpointerinputtarget). Allows the caller to register a target window to which all pointer input of the specified type is redirected. It seems work in the window which created by yourself. – Strive Sun Sep 26 '19 at 10:13
  • My colleague is able to receives WM_POINTER messages(the windows is created as a child of HWND_MESSAGE) in his Windows 10 Surface book. Because you used Wacom Intuo,we doubt whether it is related to your device.Therefore we need more details to research this issue. – Strive Sun Sep 30 '19 at 09:27
  • I used EnableMouseInPointer(true) to simulate touch behavior, so I didn't receive the WM_POINTER message because I didn't use the touch screen directly. Some behavior of this api may limit the sending of messages. – Strive Sun Sep 30 '19 at 09:44

0 Answers0