none
How to use InjectTouchInput function of User32.dll of Windows 8 in C#? RRS feed

  • Question

  • I have the following code and it does not work. I think it is mainly because I do not know how to write the following structure in C# properly. It's all about managed and unmanaged interoperability. I do not know whether to use Explicit option or Sequential. It might be noteworthy that this is all new in User32.dll of Windows 8 and it is still under beta and the documentation is due to change.

    This is the structure I think I might have misinterpreted in C#...

    typedef struct tagPOINTER_INFO {
      POINTER_INPUT_TYPE pointerType;
      UINT32             pointerId;
      UINT32             frameId;
      HANDLE             sourceDevice;
      HWND               hwndTarget;
      POINT              ptPixelLocation;
      POINT              ptHimetricLocation;
      POINT              ptPixelLocationPredicted;
      POINT              ptHimetricLocationPredicted;
      POINTER_FLAGS      pointerFlags;
      DWORD              dwTime;
      UINT32 {
        UINT32 inputData;
      }            historyCount;
      DWORD              dwKeyStates;
      ULONGLONG          Reserved;
    } POINTER_INFO;

    As you can see in my comment the call to InjectTouchInput returns false which means the injection has failed. I have looked around and I have found a C++ sample that is doing the same thing but I wonna do it in C#. Even though I couldn't get the C++ sample to compile yet. It is under Visual Studio 11 and when I open it, VS11 says you need to install .NET Framework 4 and surprisingly I already have .NET Framework 4 installed !!!

    Any thoughts would be appreciated. The C++ sample code from Microsoft is here:

    http://code.msdn.microsoft.com/windowsdesktop/Touch-Injection-Sample-444d9bf7

    And this is my code in C#:

    I'm using C# and allocating memory doesn't make sense! But this is what I'm trying to do:

    I'm trying to use the new InjectTouchInput function in win32.dll of windows 8 to inject touch input. This is the whole code. The documentation in msdn for POINTER_INFO struct looks faulty. I wish I could look at it inside the Windows.h file but I can't find the header file!!! Any thoughts?

                            

    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Linq;
    using System.Text;
    using System.Windows.Forms;


    using System.Runtime.InteropServices;


    namespace InjectingTouchInputs
    {
        [StructLayout(LayoutKind.Explicit)]
        public struct Rect
        {
            [FieldOffset(0)]
            public int left;
            [FieldOffset(4)]
            public int top;
            [FieldOffset(8)]
            public int right;
            [FieldOffset(12)]
            public int bottom;
        }


        public enum TOUCH_FLAGS { TOUCH_FLAGS_NONE = 0x00000000/*Indicates that no flags are set.*/ }


        public enum POINTER_FLAGS
        {
            POINTER_FLAG_NONE           = 0x00000000,
            POINTER_FLAG_NEW            = 0x00000001,
            POINTER_FLAG_INRANGE        = 0x00000002,
            POINTER_FLAG_INCONTACT      = 0x00000004,
            POINTER_FLAG_FIRSTBUTTON    = 0x00000010,
            POINTER_FLAG_SECONDBUTTON   = 0x00000020,
            POINTER_FLAG_THIRDBUTTON    = 0x00000040,
            POINTER_FLAG_OTHERBUTTON    = 0x00000080,
            POINTER_FLAG_PRIMARY        = 0x00000100,
            POINTER_FLAG_CONFIDENCE     = 0x00000200,
            POINTER_FLAG_CANCELLED      = 0x00000400,
            POINTER_FLAG_DOWN           = 0x00010000,
            POINTER_FLAG_UPDATE         = 0x00020000,
            POINTER_FLAG_UP             = 0x00040000,
            POINTER_FLAG_WHEEL          = 0x00080000,
            POINTER_FLAG_HWHEEL         = 0x00100000
        }


        [StructLayout(LayoutKind.Sequential)]
        public struct POINT 
        {
          public int x;
          public int y;
        }


        public enum POINTER_INPUT_TYPE 
        {
          PT_POINTER   = 0x00000001,
          PT_TOUCH     = 0x00000002,
          PT_PEN       = 0x00000003,
          PT_MOUSE     = 0x00000004 
        };


        [StructLayout(LayoutKind.Sequential)]
        public struct POINTER_INFO 
        {
            public POINTER_INPUT_TYPE pointerType;
            public uint pointerId;
            public uint frameId;
            public IntPtr sourceDevice;
            public IntPtr hwndTarget;
            public POINT ptPixelLocation;
            public POINT ptHimetricLocation;
            public POINT ptPixelLocationPredicted;
            public POINT ptHimetricLocationPredicted;
            public POINTER_FLAGS pointerFlags;
            public uint dwTime;
            public uint historyCount;
            public uint inputData;
            public uint dwKeyStates;
            public ulong Reserved;
        }


        [StructLayout(LayoutKind.Sequential)]
        public struct POINTER_TOUCH_INFO 
        {
            /*
             * Contains basic pointer information common to all pointer types.
             */
            public POINTER_INFO pointerInfo;


            /*
             * Lists the touch flags.
             */
            public TOUCH_FLAGS touchFlags;

    public uint touchMasks;

            /*
             * Pointer contact area in pixel screen coordinates. 
             * By default, if the device does not report a contact area, 
             * this field defaults to a 0-by-0 rectangle centered around the pointer location.
             */
            public Rect rcContact;


            /*
             * A pointer orientation, with a value between 0 and 359, where 0 indicates a touch pointer 
             * aligned with the x-axis and pointing from left to right; increasing values indicate degrees
             * of rotation in the clockwise direction.
             * This field defaults to 0 if the device does not report orientation.
             */
            public uint orientation;


            /*
             * Pointer pressure normalized in a range of 0 to 256.
             */
            public uint pressure;
        }


        public partial class Form1 : Form
        {
            const int MAX_TOUCH_COUNT = 256;


            //Specifies default touch visualizations.
            const int TOUCH_FEEDBACK_DEFAULT = 0x1;


            //Specifies indirect touch visualizations.
            const int TOUCH_FEEDBACK_INDIRECT = 0x2;


            //Specifies no touch visualizations.
            const int TOUCH_FEEDBACK_NONE = 0x3;


            [DllImport("User32.dll")]
            static extern bool InitializeTouchInjection(uint maxCount, int dwMode);


            [DllImport("User32.dll")]
            static extern bool InjectTouchInput(int count, ref POINTER_TOUCH_INFO contacts);


            public Form1()
            {
                InitializeComponent();
            }




            private void button1_Click(object sender, EventArgs e)
            {
                bool flag = false;
                flag = InitializeTouchInjection(10, TOUCH_FEEDBACK_NONE);


                POINTER_TOUCH_INFO contacts = new POINTER_TOUCH_INFO();

                Rect touchArea = new Rect();
                touchArea.left = 200 - 2;
                touchArea.right = 200 + 2;
                touchArea.top = 200 + 2;
                touchArea.bottom = 200 - 2;


                contacts.pointerInfo.pointerType = POINTER_INPUT_TYPE.PT_TOUCH;
                contacts.touchFlags = TOUCH_FLAGS.TOUCH_FLAGS_NONE;
                contacts.rcContact = touchArea;
                contacts.orientation = 90;
                contacts.pressure = 32000;
                contacts.pointerInfo.pointerFlags = POINTER_FLAGS.POINTER_FLAG_UP | POINTER_FLAGS.POINTER_FLAG_INRANGE | POINTER_FLAGS.POINTER_FLAG_INCONTACT;
                contacts.pointerInfo.ptPixelLocation.x = 200;
                contacts.pointerInfo.ptPixelLocation.y = 200;
                contacts.pointerInfo.pointerId = 1;


                flag = InjectTouchInput(1, ref contacts);//returned flag is false which means the injection fails!

                contacts.pressure = 0;

                if (flag)
                {
                    contacts.pointerInfo.pointerFlags = POINTER_FLAGS.POINTER_FLAG_UP;
                    InjectTouchInput(1, ref contacts);
                }


            }
        }
    }

    • Moved by Rob Caplan [MSFT]Microsoft employee Monday, March 19, 2012 8:58 PM desktop app question, not about writing a Metro style app (From:Building Metro style apps with C# or VB )
    Sunday, March 18, 2012 11:09 PM

All replies

  • I tried an almost identical program with equally no joy. If anyone has an answer to this issue I'd be thrilled to hear from you. Getting this to work with windows 8 is a real necessity for me atm.

    I got the Initialize to return true, its the inject thats returning false but I have no idea how to debug it, or wether the above in its entirety is correct. Mine is virtually the same with a few semantic differences. I wonder if its possible to do most of this work in a c++ program and access that from a c# dll import. I don't know c++ very well so I don't know the possibilities

    The internal code for Windows.h is this but I don't think it helps

    #include <winapifamily.h>
    
    /*++ BUILD Version: 0001    Increment this if a change has global effects
    
    Copyright (c) Microsoft Corporation. All rights reserved.
    
    Module Name:
    
    
        windows.h
    
    Abstract:
    
        Master include file for Windows applications.
    
    --*/
    
    #ifndef _WINDOWS_
    #define _WINDOWS_
    
    #if defined(_SAL_VERSION_CHECK) && !defined(_SAL2_STRICT)
    #undef _SAL_VERSION_CHECK
    #define _WINDOWS_H_SAL2
    #define _SAL2_STRICT
    #define _SAL_VERSION_CHECK(_A) _SAL_VERSION_SAL2(_A)
    #endif
    
    
    #include <sdkddkver.h>
    
    #ifndef _INC_WINDOWS
    #define _INC_WINDOWS
    
    #if defined (_MSC_VER) && (_MSC_VER >= 1020)
    #pragma once
    #endif
    
    #pragma region Application Family
    #if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP)
    
    
    /*  If defined, the following flags inhibit definition
     *     of the indicated items.
     *
     *  NOGDICAPMASKS     - CC_*, LC_*, PC_*, CP_*, TC_*, RC_
     *  NOVIRTUALKEYCODES - VK_*
     *  NOWINMESSAGES     - WM_*, EM_*, LB_*, CB_*
     *  NOWINSTYLES       - WS_*, CS_*, ES_*, LBS_*, SBS_*, CBS_*
     *  NOSYSMETRICS      - SM_*
     *  NOMENUS           - MF_*
     *  NOICONS           - IDI_*
     *  NOKEYSTATES       - MK_*
     *  NOSYSCOMMANDS     - SC_*
     *  NORASTEROPS       - Binary and Tertiary raster ops
     *  NOSHOWWINDOW      - SW_*
     *  OEMRESOURCE       - OEM Resource values
     *  NOATOM            - Atom Manager routines
     *  NOCLIPBOARD       - Clipboard routines
     *  NOCOLOR           - Screen colors
     *  NOCTLMGR          - Control and Dialog routines
     *  NODRAWTEXT        - DrawText() and DT_*
     *  NOGDI             - All GDI defines and routines
     *  NOKERNEL          - All KERNEL defines and routines
     *  NOUSER            - All USER defines and routines
     *  NONLS             - All NLS defines and routines
     *  NOMB              - MB_* and MessageBox()
     *  NOMEMMGR          - GMEM_*, LMEM_*, GHND, LHND, associated routines
     *  NOMETAFILE        - typedef METAFILEPICT
     *  NOMINMAX          - Macros min(a,b) and max(a,b)
     *  NOMSG             - typedef MSG and associated routines
     *  NOOPENFILE        - OpenFile(), OemToAnsi, AnsiToOem, and OF_*
     *  NOSCROLL          - SB_* and scrolling routines
     *  NOSERVICE         - All Service Controller routines, SERVICE_ equates, etc.
     *  NOSOUND           - Sound driver routines
     *  NOTEXTMETRIC      - typedef TEXTMETRIC and associated routines
     *  NOWH              - SetWindowsHook and WH_*
     *  NOWINOFFSETS      - GWL_*, GCL_*, associated routines
     *  NOCOMM            - COMM driver routines
     *  NOKANJI           - Kanji support stuff.
     *  NOHELP            - Help engine interface.
     *  NOPROFILER        - Profiler interface.
     *  NODEFERWINDOWPOS  - DeferWindowPos routines
     *  NOMCX             - Modem Configuration Extensions
     */
    
    #if defined(RC_INVOKED) && !defined(NOWINRES)
    
    #include <winresrc.h>
    
    #else
    
    #if defined(RC_INVOKED)
    /* Turn off a bunch of stuff to ensure that RC files compile OK. */
    #define NOATOM
    #define NOGDI
    #define NOGDICAPMASKS
    #define NOMETAFILE
    #define NOMINMAX
    #define NOMSG
    #define NOOPENFILE
    #define NORASTEROPS
    #define NOSCROLL
    #define NOSOUND
    #define NOSYSMETRICS
    #define NOTEXTMETRIC
    #define NOWH
    #define NOCOMM
    #define NOKANJI
    #define NOCRYPT
    #define NOMCX
    #endif
    
    #if !defined(_68K_) && !defined(_MPPC_) && !defined(_X86_) && !defined(_IA64_) && !defined(_AMD64_) && !defined(_ARM_) && defined(_M_IX86)
    #define _X86_
    #endif
    
    #if !defined(_68K_) && !defined(_MPPC_) && !defined(_X86_) && !defined(_IA64_) && !defined(_AMD64_) && !defined(_ARM_) && defined(_M_AMD64)
    #define _AMD64_
    #endif
    
    #if !defined(_68K_) && !defined(_MPPC_) && !defined(_X86_) && !defined(_IA64_) && !defined(_AMD64_) && !defined(_ARM_) && defined(_M_ARM)
    #define _ARM_
    #endif
    
    #if !defined(_68K_) && !defined(_MPPC_) && !defined(_X86_) && !defined(_IA64_) && !defined(_AMD64_) && !defined(_ARM_) && defined(_M_M68K)
    #define _68K_
    #endif
    
    #if !defined(_68K_) && !defined(_MPPC_) && !defined(_X86_) && !defined(_IA64_) && !defined(_AMD64_) && !defined(_ARM_) && defined(_M_MPPC)
    #define _MPPC_
    #endif
    
    #if !defined(_68K_) && !defined(_MPPC_) && !defined(_X86_) && !defined(_M_IX86) && !defined(_AMD64_) && !defined(_ARM_) && defined(_M_IA64)
    #if !defined(_IA64_)
    #define _IA64_
    #endif /* !_IA64_ */
    #endif
    
    #ifndef _MAC
    #if defined(_68K_) || defined(_MPPC_)
    #define _MAC
    #endif
    #endif
    
    #if defined (_MSC_VER)
    #if ( _MSC_VER >= 800 )
    #ifndef __cplusplus
    #pragma warning(disable:4116)       /* TYPE_ALIGNMENT generates this - move it */
                                        /* outside the warning push/pop scope. */
    #endif
    #endif
    #endif
    
    #ifndef RC_INVOKED
    #if     ( _MSC_VER >= 800 )
    #pragma warning(disable:4514)
    #ifndef __WINDOWS_DONT_DISABLE_PRAGMA_PACK_WARNING__
    #pragma warning(disable:4103)
    #endif
    #if _MSC_VER >= 1200
    #pragma warning(push)
    #endif
    #pragma warning(disable:4001)
    #pragma warning(disable:4201)
    #pragma warning(disable:4214)
    #endif
    #include <excpt.h>
    #include <stdarg.h>
    #endif /* RC_INVOKED */
    
    #include <windef.h>
    #include <winbase.h>
    #include <wingdi.h>
    #include <winuser.h>
    #if !defined(_MAC) || defined(_WIN32NLS)
    #include <winnls.h>
    #endif
    #ifndef _MAC
    #include <wincon.h>
    #include <winver.h>
    #endif
    #if !defined(_MAC) || defined(_WIN32REG)
    #include <winreg.h>
    #endif
    #ifndef _MAC
    #include <winnetwk.h>
    #endif
    
    #ifndef WIN32_LEAN_AND_MEAN
    #include <cderr.h>
    #include <dde.h>
    #include <ddeml.h>
    #include <dlgs.h>
    #ifndef _MAC
    #include <lzexpand.h>
    #include <mmsystem.h>
    #include <nb30.h>
    #include <rpc.h>
    #endif
    #include <shellapi.h>
    #ifndef _MAC
    #include <winperf.h>
    #include <winsock.h>
    #endif
    #ifndef NOCRYPT
    #include <wincrypt.h>
    #include <winefs.h>
    #include <winscard.h>
    #endif
    
    #ifndef NOGDI
    #ifndef _MAC
    #include <winspool.h>
    #ifdef INC_OLE1
    #include <ole.h>
    #else
    #include <ole2.h>
    #endif /* !INC_OLE1 */
    #endif /* !MAC */
    #include <commdlg.h>
    #endif /* !NOGDI */
    #endif /* WIN32_LEAN_AND_MEAN */
    
    #include <stralign.h>
    
    #ifdef _MAC
    #include <winwlm.h>
    #endif
    
    
    #ifdef INC_OLE2
    #include <ole2.h>
    #endif /* INC_OLE2 */
    
    #ifndef _MAC
    #ifndef NOSERVICE
    #include <winsvc.h>
    #endif
    
    #if(WINVER >= 0x0400)
    #ifndef NOMCX
    #include <mcx.h>
    #endif /* NOMCX */
    
    #ifndef NOIME
    #include <imm.h>
    #endif
    #endif /* WINVER >= 0x0400 */
    #endif
    
    #ifndef RC_INVOKED
    #if     ( _MSC_VER >= 800 )
    #if _MSC_VER >= 1200
    #pragma warning(pop)
    #else
    #pragma warning(default:4001)
    #pragma warning(default:4201)
    #pragma warning(default:4214)
    /* Leave 4514 disabled.  It's an unneeded warning anyway. */
    #endif
    #endif
    #endif /* RC_INVOKED */
    
    #endif /* RC_INVOKED */
    
    #endif /* WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP) */
    #pragma endregion
    
    #endif /* _INC_WINDOWS */
    
    #if defined(_WINDOWS_H_SAL2)
    #undef _SAL2_STRICT
    #undef _WINDOWS_H_SAL2
    #undef _SAL_VERSION_CHECK
    #define _SAL_VERSION_CHECK(_A)
    #endif
    
    #endif /* _WINDOWS_ */
    


    Saturday, April 14, 2012 8:44 PM
  • In addition here is some of the relevant definitions lifted from the WinUser.h file:

    #if(WINVER >= 0x0602)
    
    #pragma region Desktop Family
    #if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
    
    enum tagPOINTER_INPUT_TYPE {
        PT_POINTER  = 0x00000001,   // Generic pointer
        PT_TOUCH    = 0x00000002,   // Touch
        PT_PEN      = 0x00000003,   // Pen
        PT_MOUSE    = 0x00000004,   // Mouse
    };
    typedef DWORD POINTER_INPUT_TYPE;
    
    typedef UINT32 POINTER_FLAGS;
    
    #endif /* WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) */
    #pragma endregion
    
    #define POINTER_FLAG_NONE               0x00000000 // Default
    #define POINTER_FLAG_NEW                0x00000001 // New pointer
    #define POINTER_FLAG_INRANGE            0x00000002 // Pointer has not departed
    #define POINTER_FLAG_INCONTACT          0x00000004 // Pointer is in contact
    #define POINTER_FLAG_FIRSTBUTTON        0x00000010 // Primary action
    #define POINTER_FLAG_SECONDBUTTON       0x00000020 // Secondary action
    #define POINTER_FLAG_OTHERBUTTON        0x00000040 // Other buttons
    #define POINTER_FLAG_THIRDBUTTON        0x00000080 // Third button
    #define POINTER_FLAG_PRIMARY            0x00000100 // Pointer is primary
    #define POINTER_FLAG_CONFIDENCE         0x00000200 // Pointer is considered unlikely to be accidental
    #define POINTER_FLAG_CANCELED           0x00000400 // Pointer is departing in an abnormal manner
    #define POINTER_FLAG_DOWN               0x00010000 // Pointer transitioned to down state (made contact)
    #define POINTER_FLAG_UPDATE             0x00020000 // Pointer update
    #define POINTER_FLAG_UP                 0x00040000 // Pointer transitioned from down state (broke contact)
    #define POINTER_FLAG_WHEEL              0x00080000 // Vertical wheel
    #define POINTER_FLAG_HWHEEL             0x00100000 // Horizontal wheel
    #define POINTER_FLAG_CAPTURECHANGED     0x00200000 // Lost capture
    
    /*
     * Pointer info key states defintions.
     */
    #define POINTER_MOD_SHIFT   (0x0004)    // Shift key is held down.
    #define POINTER_MOD_CTRL    (0x0008)    // Ctrl key is held down.
    
    #pragma region Desktop Family
    #if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
    
    typedef struct tagPOINTER_INFO {
        POINTER_INPUT_TYPE    pointerType;
        UINT32          pointerId;
        UINT32          frameId;
        POINTER_FLAGS   pointerFlags;
        HANDLE          sourceDevice;
        HWND            hwndTarget;
        POINT           ptPixelLocation;
        POINT           ptHimetricLocation;
        POINT           ptPixelLocationRaw;
        POINT           ptHimetricLocationRaw;
        DWORD           dwTime;
        UINT32          historyCount;
        INT32           InputData;
        DWORD           dwKeyStates;
        UINT64          PerformanceCount;
    } POINTER_INFO;
    
    typedef UINT32 TOUCH_FLAGS;
    #define TOUCH_FLAG_NONE                 0x00000000 // Default
    
    typedef UINT32 TOUCH_MASK;
    #define TOUCH_MASK_NONE                 0x00000000 // Default - none of the optional fields are valid
    #define TOUCH_MASK_CONTACTAREA          0x00000001 // The rcContact field is valid
    #define TOUCH_MASK_ORIENTATION          0x00000002 // The orientation field is valid
    #define TOUCH_MASK_PRESSURE             0x00000004 // The pressure field is valid
    
    typedef struct tagPOINTER_TOUCH_INFO {
        POINTER_INFO    pointerInfo;
        TOUCH_FLAGS     touchFlags;
        TOUCH_MASK      touchMask;
        RECT            rcContact;
        RECT            rcContactRaw;
        UINT32          orientation;
        UINT32          pressure;
    } POINTER_TOUCH_INFO;
    
    typedef UINT32 PEN_FLAGS;
    #define PEN_FLAG_NONE                   0x00000000 // Default
    #define PEN_FLAG_BARREL                 0x00000001 // The barrel button is pressed
    #define PEN_FLAG_INVERTED               0x00000002 // The pen is inverted
    #define PEN_FLAG_ERASER                 0x00000004 // The eraser button is pressed
    
    typedef UINT32 PEN_MASK;
    #define PEN_MASK_NONE                   0x00000000 // Default - none of the optional fields are valid
    #define PEN_MASK_PRESSURE               0x00000001 // The pressure field is valid
    #define PEN_MASK_ROTATION               0x00000002 // The rotation field is valid
    #define PEN_MASK_TILT_X                 0x00000004 // The tiltX field is valid
    #define PEN_MASK_TILT_Y                 0x00000008 // The tiltY field is valid
    
    typedef struct tagPOINTER_PEN_INFO {
        POINTER_INFO    pointerInfo;
        PEN_FLAGS       penFlags;
        PEN_MASK        penMask;
        UINT32          pressure;
        UINT32          rotation;
        INT32           tiltX;
        INT32           tiltY;
    } POINTER_PEN_INFO;
    
    #endif /* WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) */
    #pragma endregion
    
    /*
     * Flags that appear in pointer input message parameters
     */
    #define POINTER_MESSAGE_FLAG_NEW                0x00000001 // New pointer
    #define POINTER_MESSAGE_FLAG_INRANGE            0x00000002 // Pointer has not departed
    #define POINTER_MESSAGE_FLAG_INCONTACT          0x00000004 // Pointer is in contact
    #define POINTER_MESSAGE_FLAG_FIRSTBUTTON        0x00000010 // Primary action
    #define POINTER_MESSAGE_FLAG_SECONDBUTTON       0x00000020 // Secondary action
    #define POINTER_MESSAGE_FLAG_OTHERBUTTON        0x00000040 // Other actions
    #define POINTER_MESSAGE_FLAG_THIRDBUTTON        0x00000080 // Third button
    #define POINTER_MESSAGE_FLAG_PRIMARY            0x00000100 // Pointer is primary
    #define POINTER_MESSAGE_FLAG_CONFIDENCE         0x00000200 // Pointer is considered unlikely to be accidental
    #define POINTER_MESSAGE_FLAG_CANCELED           0x00000400 // Pointer is departing in an abnormal manner
    
    /*
     * Macros to retrieve information from pointer input message parameters
     */
    #define GET_POINTERID_WPARAM(wParam)                (LOWORD(wParam))
    #define IS_POINTER_FLAG_SET_WPARAM(wParam, flag)    (((DWORD)HIWORD(wParam) & (flag)) == (flag))
    #define IS_POINTER_NEW_WPARAM(wParam)               IS_POINTER_FLAG_SET_WPARAM(wParam, POINTER_MESSAGE_FLAG_NEW)
    #define IS_POINTER_INRANGE_WPARAM(wParam)           IS_POINTER_FLAG_SET_WPARAM(wParam, POINTER_MESSAGE_FLAG_INRANGE)
    #define IS_POINTER_INCONTACT_WPARAM(wParam)         IS_POINTER_FLAG_SET_WPARAM(wParam, POINTER_MESSAGE_FLAG_INCONTACT)
    #define IS_POINTER_FIRSTBUTTON_WPARAM(wParam)       IS_POINTER_FLAG_SET_WPARAM(wParam, POINTER_MESSAGE_FLAG_FIRSTBUTTON)
    #define IS_POINTER_SECONDBUTTON_WPARAM(wParam)      IS_POINTER_FLAG_SET_WPARAM(wParam, POINTER_MESSAGE_FLAG_SECONDBUTTON)
    #define IS_POINTER_OTHERBUTTON_WPARAM(wParam)       IS_POINTER_FLAG_SET_WPARAM(wParam, POINTER_MESSAGE_FLAG_OTHERBUTTON)
    #define IS_POINTER_PRIMARY_WPARAM(wParam)           IS_POINTER_FLAG_SET_WPARAM(wParam, POINTER_MESSAGE_FLAG_PRIMARY)
    #define HAS_POINTER_CONFIDENCE_WPARAM(wParam)       IS_POINTER_FLAG_SET_WPARAM(wParam, POINTER_MESSAGE_FLAG_CONFIDENCE)
    #define IS_POINTER_CANCELED_WPARAM(wParam)          IS_POINTER_FLAG_SET_WPARAM(wParam, POINTER_MESSAGE_FLAG_CANCELED)
    
    /*
     * WM_POINTERACTIVATE return codes
     */
    #define PA_ACTIVATE                     MA_ACTIVATE
    #define PA_NOACTIVATE                   MA_NOACTIVATE
    
    
    #define MAX_TOUCH_COUNT 256
    
    #define TOUCH_FEEDBACK_DEFAULT 0x1
    #define TOUCH_FEEDBACK_INDIRECT 0x2
    #define TOUCH_FEEDBACK_NONE 0x3
    
    #pragma region Desktop Family
    #if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
    
    WINUSERAPI
    BOOL
    WINAPI
    InitializeTouchInjection(
        _In_ UINT32 maxCount,
        _In_ DWORD dwMode);
    
    
    WINUSERAPI
    BOOL
    WINAPI
    InjectTouchInput(
        _In_ UINT32 count,
        _In_reads_(count) CONST POINTER_TOUCH_INFO *contacts);
    
    WINUSERAPI
    BOOL
    WINAPI
    GetPointerType(
        _In_ UINT32 pointerId,
        _Out_ POINTER_INPUT_TYPE *pointerType);
    
    WINUSERAPI
    BOOL
    WINAPI
    GetPointerCursorId(
        _In_ UINT32 pointerId,
        _Out_ UINT32 *cursorId);
    
    WINUSERAPI
    BOOL
    WINAPI
    GetPointerInfo(
        _In_ UINT32 pointerId,
        _Out_writes_(1) POINTER_INFO *pointerInfo);
    
    WINUSERAPI
    BOOL
    WINAPI
    GetPointerInfoHistory(
        _In_ UINT32 pointerId,
        _Inout_ UINT32 *entriesCount,
        _Out_writes_opt_(*entriesCount) POINTER_INFO *pointerInfo);
    
    WINUSERAPI
    BOOL
    WINAPI
    GetPointerFrameInfo(
        _In_ UINT32 pointerId,
        _Inout_ UINT32 *pointerCount,
        _Out_writes_opt_(*pointerCount) POINTER_INFO *pointerInfo);
    
    WINUSERAPI
    BOOL
    WINAPI
    GetPointerFrameInfoHistory(
        _In_ UINT32 pointerId,
        _Inout_ UINT32 *entriesCount,
        _Inout_ UINT32 *pointerCount,
        _Out_writes_opt_(*entriesCount * *pointerCount) POINTER_INFO *pointerInfo);
    
    WINUSERAPI
    BOOL
    WINAPI
    GetPointerTouchInfo(
        _In_ UINT32 pointerId,
        _Out_writes_(1) POINTER_TOUCH_INFO *touchInfo);
    
    WINUSERAPI
    BOOL
    WINAPI
    GetPointerTouchInfoHistory(
        _In_ UINT32 pointerId,
        _Inout_ UINT32 *entriesCount,
        _Out_writes_opt_(*entriesCount) POINTER_TOUCH_INFO *touchInfo);
    
    WINUSERAPI
    BOOL
    WINAPI
    GetPointerFrameTouchInfo(
        _In_ UINT32 pointerId,
        _Inout_ UINT32 *pointerCount,
        _Out_writes_opt_(*pointerCount) POINTER_TOUCH_INFO *touchInfo);
    
    WINUSERAPI
    BOOL
    WINAPI
    GetPointerFrameTouchInfoHistory(
        _In_ UINT32 pointerId,
        _Inout_ UINT32 *entriesCount,
        _Inout_ UINT32 *pointerCount,
        _Out_writes_opt_(*entriesCount * *pointerCount) POINTER_TOUCH_INFO *touchInfo);
    
    WINUSERAPI
    BOOL
    WINAPI
    GetPointerPenInfo(
        _In_ UINT32 pointerId,
        _Out_writes_(1) POINTER_PEN_INFO *penInfo);
    
    WINUSERAPI
    BOOL
    WINAPI
    GetPointerPenInfoHistory(
        _In_ UINT32 pointerId,
        _Inout_ UINT32 *entriesCount,
        _Out_writes_opt_(*entriesCount) POINTER_PEN_INFO *penInfo);
    
    WINUSERAPI
    BOOL
    WINAPI
    GetPointerFramePenInfo(
        _In_ UINT32 pointerId,
        _Inout_ UINT32 *pointerCount,
        _Out_writes_opt_(*pointerCount) POINTER_PEN_INFO *penInfo);
    
    WINUSERAPI
    BOOL
    WINAPI
    GetPointerFramePenInfoHistory(
        _In_ UINT32 pointerId,
        _Inout_ UINT32 *entriesCount,
        _Inout_ UINT32 *pointerCount,
        _Out_writes_opt_(*entriesCount * *pointerCount) POINTER_PEN_INFO *penInfo);
    
    WINUSERAPI
    BOOL
    WINAPI
    SkipPointerFrameMessages(
        _In_ UINT32 pointerId);
    
    WINUSERAPI
    BOOL
    WINAPI
    RegisterPointerInputTarget(
        _In_ HWND hwnd,
        _In_ POINTER_INPUT_TYPE pointerType);
    
    WINUSERAPI
    BOOL
    WINAPI
    UnregisterPointerInputTarget(
        _In_ HWND hwnd,
        _In_ POINTER_INPUT_TYPE pointerType);
    
    
    WINUSERAPI
    BOOL
    WINAPI
    EnableMouseInPointer(
        _In_ BOOL fEnable);
    
    WINUSERAPI
    BOOL
    WINAPI
    IsMouseInPointerEnabled(
        VOID);

    Saturday, April 14, 2012 8:59 PM
  • I made some serious progress on this since posting the junk above. I went ahead and create some custom functions in c++ based on the sample Microsoft provided and then went and imported that into C# using alot of the same definitions as above but without farting about with all the type checking, pointers and arguments that were causing headaches before.

    The DLL file that I've used is TouchInjectionDriver.dll and can be found here. Below is the C# code I used to implement it.

                public enum TOUCH_MASK : uint
                {
                    TOUCH_MASK_NONE = 0x00000000,
                    TOUCH_MASK_CONTACTAREA = 0x00000001,
                    TOUCH_MASK_ORIENTATION = 0x00000002,
                    TOUCH_MASK_PRESSURE = 0x00000004
                }
                public enum POINTER_INPUT_TYPE : uint
                {
                    PT_POINTER = 0x00000001,
                    PT_TOUCH = 0x00000002,
                    PT_PEN = 0x00000003,
                    PT_MOUSE = 0x00000004
                }
    
                public enum POINTER_FLAGS : uint
                {
                    POINTER_FLAG_NONE = 0x00000000,
                    POINTER_FLAG_NEW = 0x00000001,
                    POINTER_FLAG_INRANGE = 0x00000002,
                    POINTER_FLAG_INCONTACT = 0x00000004,
                    POINTER_FLAG_FIRSTBUTTON = 0x00000010,
                    POINTER_FLAG_SECONDBUTTON = 0x00000020,
                    POINTER_FLAG_THIRDBUTTON = 0x00000040,
                    POINTER_FLAG_OTHERBUTTON = 0x00000080,
                    POINTER_FLAG_PRIMARY = 0x00000100,
                    POINTER_FLAG_CONFIDENCE = 0x00000200,
                    POINTER_FLAG_CANCELLED = 0x00000400,
                    POINTER_FLAG_DOWN = 0x00010000,
                    POINTER_FLAG_UPDATE = 0x00020000,
                    POINTER_FLAG_UP = 0x00040000,
                    POINTER_FLAG_WHEEL = 0x00080000,
                    POINTER_FLAG_HWHEEL = 0x00100000
                }
                public enum TOUCH_FEEDBACK : uint
                {
                    TOUCH_FEEDBACK_DEFAULT = 0x1,
                    TOUCH_FEEDBACK_INDIRECT = 0x2,
                    TOUCH_FEEDBACK_NONE = 0x3
                }
                
                [DllImport("TouchInjectionDriver.dll", CallingConvention = CallingConvention.Cdecl)]
                private static extern bool InjectTouch(int x, int y, POINTER_INPUT_TYPE pt_input, int pressure, int orientation, int id, int rcContactTop, int rcContactBottom, int rcContactLeft, int rcContactRight, POINTER_FLAGS pointerFlags, TOUCH_MASK touchMask);
                [DllImport("TouchInjectionDriver.dll", CallingConvention = CallingConvention.Cdecl)]
                private static extern void setTouchFeedback(TOUCH_FEEDBACK fb);
                [DllImport("TouchInjectionDriver.dll", CallingConvention = CallingConvention.Cdecl)]
                private static extern void setDefaultRectSize(int size);
                [DllImport("TouchInjectionDriver.dll", CallingConvention = CallingConvention.Cdecl)]
                private static extern void setDefaultPressure(int pres);
                [DllImport("TouchInjectionDriver.dll", CallingConvention = CallingConvention.Cdecl)]
                private static extern void setDefaultOrientation(int or);
    
                [DllImport("User32.dll")]
                static extern Boolean MessageBeep(UInt32 beepType);
    
                public static void mouseclick(int x, int y)
                {
                    bool ret;
                    setTouchFeedback(TOUCH_FEEDBACK.TOUCH_FEEDBACK_INDIRECT);
                    ret = InjectTouch(x, y, POINTER_INPUT_TYPE.PT_TOUCH, 3200, 0, 0, x - 4, x + 4, y - 4, y + 4,POINTER_FLAGS.POINTER_FLAG_DOWN|POINTER_FLAGS.POINTER_FLAG_INCONTACT|POINTER_FLAGS.POINTER_FLAG_INRANGE,TOUCH_MASK.TOUCH_MASK_CONTACTAREA|TOUCH_MASK.TOUCH_MASK_ORIENTATION|TOUCH_MASK.TOUCH_MASK_PRESSURE);
                    if (ret)
                    {
                        ret = InjectTouch(x, y, POINTER_INPUT_TYPE.PT_TOUCH, 3200, 0, 0, x - 4, x + 4, y - 4, y + 4, POINTER_FLAGS.POINTER_FLAG_UP, TOUCH_MASK.TOUCH_MASK_CONTACTAREA | TOUCH_MASK.TOUCH_MASK_ORIENTATION | TOUCH_MASK.TOUCH_MASK_PRESSURE);
                    }
                    else
                    {
                        MessageBeep(0);
                    }
                }


    • Proposed as answer by ChevronTango Sunday, April 15, 2012 9:34 PM
    • Edited by ChevronTango Sunday, April 15, 2012 11:05 PM
    Sunday, April 15, 2012 9:34 PM
  • That's great! how did you reference the TouchInjectionDriver.dll into your C# project? for me when I try adding the reference in Visual Studio, I get "A reference to... could not be added. Please make sure that the file is accessible, and that it is a valid assembly or COM component". Any idea?

    I also tried "regsvr32 TouchInjectionDriver.dll" in command prompt, but got similar error!

    Thank you!



    • Edited by ance Monday, April 16, 2012 12:02 PM
    Monday, April 16, 2012 12:01 PM
  • The sample C# code in my previous post is exactly what I used to call the functions and simulate touch inputs from within my C# program. I didn't bother adding it as a referance, I just used the DLLImport and placed the dll in my build folder. I did find that Visual Studio didn't play fair with the DLL and got a not found error, but that was because I hadn't put the dll in the AppX subfolder of my build (not sure if you'll get that). If you get a Access Denied error then likely your UAC isn't playing fair either, but if youre building a Metro Style App you can't turn it off, so place the entire build (including the new DLL) into a UAC exempt folder. Mine for example is in Program Files.

    I'm probably going to rework that dll some more in the coming weeks so its as easy as possible to use, and has more functionality such as sending more than one input at once. At the moment it works fine for me but if other people are wanting to use it it will need redoing.

    Monday, April 16, 2012 12:17 PM
  • Excellent! thank you for your response. It simply worked by just placing the DLL inside Bin\Debug directory!

    Would you please be able to share the C++ code that you used to build "TouchInjectionDriver.dll"? I can probably help in extending it to allow multi-touch and other touch gestures as I'm currently working on using Kinect as touch input for Windows 8. 

    Greatly appreciating your help!

    Monday, April 16, 2012 12:41 PM
  • Believe it or not, thats exactly what I'm doing. Its a group project for Uni. I can package and send you the Visual Basic Source File but I need to play with it a bit more before I do that. Its a best a hack at the moment anyway. If you have seen the C++ sample that microsoft released its virtually identical to that but packaged as a DLL.


    I'll be using this as a referance guide and I'll throw the second version of the DLL your way on this thread.

    Monday, April 16, 2012 1:05 PM
  • Hi,

        Its always better to use P-Invoke library to get auto-generated structure, In your case i can see you are missing with some wrong marshaling type.. ;) .better try with any or these tools to get the correct structure.

    http://www.pinvoker.com/

    http://clrinterop.codeplex.com

    http://www.paulyao.com/res/pinvoke/pinvoke.aspx

    Thanks

    sanjay sinha

    Monday, April 23, 2012 8:21 AM
  • I ran into similar issues before I got this working and thought I would post my findings.

    My C# code looks very similar to the first post, except for some difference in POINTER_TOUCH_INFO and POINTER_INFO which is very similar to WinUser.h.

    And, API call, is as follows:

    [DllImport("User32.dll")]
    static extern bool InjectTouchInput(int count, [MarshalAs(UnmanagedType.LPArray), In] POINTER_TOUCH_INFO[] contacts)

    • Proposed as answer by Neelofar Monday, April 23, 2012 9:55 PM
    Monday, April 23, 2012 9:55 PM
  • The following C# code worked well for me

    public class TouchController
        {
    
            POINTER_TOUCH_INFO contact = new POINTER_TOUCH_INFO();
    
            public static void Touch(int x, int y)
            {
                bool flag = false;
                flag = InitializeTouchInjection(10, TOUCH_FEEDBACK_DEFAULT);
    
                POINTER_TOUCH_INFO contacts = new POINTER_TOUCH_INFO();
    
    
                contacts.pointerInfo.pointerType = POINTER_INPUT_TYPE.PT_TOUCH;
                contacts.touchFlags = TOUCH_FLAGS.TOUCH_FLAGS_NONE;
    
                contacts.orientation = 90;
                contacts.pressure = 32000;
                contacts.pointerInfo.pointerFlags = POINTER_FLAGS.POINTER_FLAG_DOWN | POINTER_FLAGS.POINTER_FLAG_INRANGE | POINTER_FLAGS.POINTER_FLAG_INCONTACT;
                contacts.touchMasks = TOUCH_MASK.TOUCH_MASK_CONTACTAREA | TOUCH_MASK.TOUCH_MASK_ORIENTATION | TOUCH_MASK.TOUCH_MASK_PRESSURE;
                contacts.pointerInfo.ptPixelLocation.x = x;
                contacts.pointerInfo.ptPixelLocation.y = y;
                contacts.pointerInfo.pointerId = 1;
    
                Rect touchArea = new Rect();
                touchArea.left = x - 2;
                touchArea.right = x + 2;
                touchArea.top = y - 2;
                touchArea.bottom = y + 2;
                contacts.rcContact = touchArea;
    
                flag = InjectTouchInput(1, ref contacts);
    
                contacts.pressure = 0;
                if (flag)
                {
                    contacts.pointerInfo.pointerFlags = POINTER_FLAGS.POINTER_FLAG_UP;
                    InjectTouchInput(1, ref contacts);
                }
            }
    
            public bool TouchDown(int x, int y)
            {
                bool flag = false;
                flag = InitializeTouchInjection(10, TOUCH_FEEDBACK_DEFAULT);
    
                contact.pointerInfo.pointerType = POINTER_INPUT_TYPE.PT_TOUCH;
                contact.touchFlags = TOUCH_FLAGS.TOUCH_FLAGS_NONE;
    
                contact.orientation = 90;
                contact.pressure = 32000;
                contact.pointerInfo.pointerFlags = POINTER_FLAGS.POINTER_FLAG_DOWN | POINTER_FLAGS.POINTER_FLAG_INRANGE | POINTER_FLAGS.POINTER_FLAG_INCONTACT;
                contact.touchMasks = TOUCH_MASK.TOUCH_MASK_CONTACTAREA | TOUCH_MASK.TOUCH_MASK_ORIENTATION | TOUCH_MASK.TOUCH_MASK_PRESSURE;
                contact.pointerInfo.ptPixelLocation.x = x;
                contact.pointerInfo.ptPixelLocation.y = y;
                contact.pointerInfo.pointerId = 1;
    
                Rect touchArea = new Rect();
                touchArea.left = x - 2;
                touchArea.right = x + 2;
                touchArea.top = y - 2;
                touchArea.bottom = y + 2;
                contact.rcContact = touchArea;
    
                flag = InjectTouchInput(1, ref contact);
    
                return flag;
            }
    
            public void TouchHold()
            {
                contact.pointerInfo.pointerFlags = POINTER_FLAGS.POINTER_FLAG_UPDATE | POINTER_FLAGS.POINTER_FLAG_INRANGE | POINTER_FLAGS.POINTER_FLAG_INCONTACT;
                for (int i = 0; i < 100000; i++)
                {        //loops for approx. 1 second causing 1 second HOLD effect
                    InjectTouchInput(1, ref contact);
                }
            }
    
            public void TouchDrag(int x, int y)
            {
                //Setting the Pointer Flag to Drag
                contact.pointerInfo.pointerFlags = POINTER_FLAGS.POINTER_FLAG_UPDATE | POINTER_FLAGS.POINTER_FLAG_INRANGE | POINTER_FLAGS.POINTER_FLAG_INCONTACT;
    
                contact.pointerInfo.ptPixelLocation.x = x; // updating the X Co-ordinate to x-100 pixels
                contact.pointerInfo.ptPixelLocation.y = y;
    
                InjectTouchInput(1, ref contact);
            }
    
            public bool TouchUp()
            {
                //contacts.pressure = 0;
                contact.pointerInfo.pointerFlags = POINTER_FLAGS.POINTER_FLAG_UP;
                return InjectTouchInput(1, ref contact);
            }
    
            #region Types
    
            [DllImport("User32.dll")]
            static extern bool InitializeTouchInjection(uint maxCount, int dwMode);
    
            [DllImport("User32.dll")]
            static extern bool InjectTouchInput(int count, ref POINTER_TOUCH_INFO contacts);
    
            const int MAX_TOUCH_COUNT = 256;
    
            //Specifies default touch visualizations.
            const int TOUCH_FEEDBACK_DEFAULT = 0x1;
    
            //Specifies indirect touch visualizations.
            const int TOUCH_FEEDBACK_INDIRECT = 0x2;
    
            //Specifies no touch visualizations.
            const int TOUCH_FEEDBACK_NONE = 0x3;
    
            [StructLayout(LayoutKind.Explicit)]
            public struct Rect
            {
                [FieldOffset(0)]
                public int left;
                [FieldOffset(4)]
                public int top;
                [FieldOffset(8)]
                public int right;
                [FieldOffset(12)]
                public int bottom;
            }
    
    
            public enum TOUCH_FLAGS { TOUCH_FLAGS_NONE = 0x00000000/*Indicates that no flags are set.*/ }
    
            public enum TOUCH_MASK
            {
                TOUCH_MASK_NONE = 0x00000000 // Default - none of the optional fields are valid
                ,
                TOUCH_MASK_CONTACTAREA = 0x00000001 // The rcContact field is valid
                ,
                TOUCH_MASK_ORIENTATION = 0x00000002 // The orientation field is valid
                ,
                TOUCH_MASK_PRESSURE = 0x00000004 // The pressure field is valid
    
            }
    
            public enum POINTER_FLAGS
            {
                POINTER_FLAG_NONE = 0x00000000,
                POINTER_FLAG_NEW = 0x00000001,
                POINTER_FLAG_INRANGE = 0x00000002,
                POINTER_FLAG_INCONTACT = 0x00000004,
                POINTER_FLAG_FIRSTBUTTON = 0x00000010,
                POINTER_FLAG_SECONDBUTTON = 0x00000020,
                POINTER_FLAG_THIRDBUTTON = 0x00000040,
                POINTER_FLAG_OTHERBUTTON = 0x00000080,
                POINTER_FLAG_PRIMARY = 0x00000100,
                POINTER_FLAG_CONFIDENCE = 0x00000200,
                POINTER_FLAG_CANCELLED = 0x00000400,
                POINTER_FLAG_DOWN = 0x00010000,
                POINTER_FLAG_UPDATE = 0x00020000,
                POINTER_FLAG_UP = 0x00040000,
                POINTER_FLAG_WHEEL = 0x00080000,
                POINTER_FLAG_HWHEEL = 0x00100000
            }
    
    
            [StructLayout(LayoutKind.Sequential)]
            public struct POINT
            {
                public int x;
                public int y;
            }
    
    
            public enum POINTER_INPUT_TYPE
            {
                PT_POINTER = 0x00000001,
                PT_TOUCH = 0x00000002,
                PT_PEN = 0x00000003,
                PT_MOUSE = 0x00000004
            };
    
    
            [StructLayout(LayoutKind.Sequential)]
            public struct POINTER_INFO
            {
                public POINTER_INPUT_TYPE pointerType;
                public uint pointerId;
                public uint frameId;
                public POINTER_FLAGS pointerFlags;
    
                public IntPtr sourceDevice;
                public IntPtr hwndTarget;
    
                public POINT ptPixelLocation;
                public POINT ptHimetricLocation;
    
                public POINT ptPixelLocationRaw;
                public POINT ptHimetricLocationRaw;
    
                public uint dwTime;
                public uint historyCount;
    
                public uint inputData;
                public uint dwKeyStates;
                public ulong PerformanceCount;
            }
    
    
            [StructLayout(LayoutKind.Sequential)]
            public struct POINTER_TOUCH_INFO
            {
                /*
                 * Contains basic pointer information common to all pointer types.
                 */
                public POINTER_INFO pointerInfo;
    
                /*
                 * Lists the touch flags.
                 */
                public TOUCH_FLAGS touchFlags;
    
                public TOUCH_MASK touchMasks;
    
                /*
                 * Pointer contact area in pixel screen coordinates. 
                 * By default, if the device does not report a contact area, 
                 * this field defaults to a 0-by-0 rectangle centered around the pointer location.
                 */
                public Rect rcContact;
    
                public Rect rcContactRaw;
    
                /*
                 * A pointer orientation, with a value between 0 and 359, where 0 indicates a touch pointer 
                 * aligned with the x-axis and pointing from left to right; increasing values indicate degrees
                 * of rotation in the clockwise direction.
                 * This field defaults to 0 if the device does not report orientation.
                 */
                public uint orientation;
    
                /*
                 * Pointer pressure normalized in a range of 0 to 256.
                 */
                public uint pressure;
            } 
            #endregion



    • Edited by ance Sunday, May 6, 2012 8:16 PM
    Sunday, May 6, 2012 12:24 PM
  • Hi ance, could you give an full example, i can't launch metro application by using your Touch() method, snip code as below:

    static void Main(string[] args)
            {
                sendWinkey();// from Retro desktop to metro screen
                Thread.Sleep(5000);
                
                AutomationElement startMenuWindow = FindStartMenuWindow();
                AutomationElement ieIcon= startMenuWindow.FindFirst(TreeScope.Subtree,
                    new PropertyCondition(AutomationElement.AutomationIdProperty, "Microsoft.InternetExplorer.Default"));
               
                Rectangle rect;
                rect = ieIcon.Current.BoundingRectangle;
                int x, y;
                x = (rect.Left + rect.Width);
                y = (rect.Top + rect.Height);
                Touch(x,y);
            }
          

               
    Saturday, June 16, 2012 5:17 AM
  • After some trouble I got it working. This is my C#code: http://dl.dropbox.com/u/7813771/Blog/CodeSamples/TouchInjection.cs

    As Neelofar pointed out, the POINTER_TOUCH_INFO structure was missing a property..

    I added all the IntelliSense descriptions and published my library on NuGet : https://nuget.org/packages/TCD.System.TouchInjection/

    This is a sample application: http://dl.dropbox.com/u/7813771/Blog/TCD%20-%20Desktop/TouchInjectorSample.zip

    Hope this helps =)


    Life is unsure - always eat the dessert first!

    Sunday, August 19, 2012 10:40 AM
  • Hello, hope can helpme.
    I test TCD.System.Touchinjection and work perfect, but i found a little problem, I cant send a simple press and hold gestures.
    After few a short time, touch up is sent! ;(

    I only found this info
    For press and hold gestures, multiple frames must be sent to ensure input is not cancelled. For a press and hold at point (x,y), send WM_POINTERDOWN at point (x,y) followed by WM_POINTERUPDATE messages at point(x,y).
    https://msdn.microsoft.com/en-us/library/windows/desktop/hh454923(v=vs.85).aspx


    Please can somebody help me with this?

    Friday, December 29, 2017 10:24 AM