From 92acfa944e1da1d7aeb39f38bf2873a53f0f00ea Mon Sep 17 00:00:00 2001 From: dahall Date: Mon, 13 Jan 2020 11:16:07 -0700 Subject: [PATCH] Added new functions from Win10 1903 --- PInvoke/User32/WinUser.Pointer.cs | 384 +++++++++++++++++++++++++++----------- 1 file changed, 274 insertions(+), 110 deletions(-) diff --git a/PInvoke/User32/WinUser.Pointer.cs b/PInvoke/User32/WinUser.Pointer.cs index 222d1033..89e5c565 100644 --- a/PInvoke/User32/WinUser.Pointer.cs +++ b/PInvoke/User32/WinUser.Pointer.cs @@ -50,7 +50,8 @@ namespace Vanara.PInvoke // https://docs.microsoft.com/en-us/windows/desktop/api/winuser/ne-winuser-tagpointer_button_change_type typedef enum // tagPOINTER_BUTTON_CHANGE_TYPE { POINTER_CHANGE_NONE, POINTER_CHANGE_FIRSTBUTTON_DOWN, POINTER_CHANGE_FIRSTBUTTON_UP, // POINTER_CHANGE_SECONDBUTTON_DOWN, POINTER_CHANGE_SECONDBUTTON_UP, POINTER_CHANGE_THIRDBUTTON_DOWN, POINTER_CHANGE_THIRDBUTTON_UP, - // POINTER_CHANGE_FOURTHBUTTON_DOWN, POINTER_CHANGE_FOURTHBUTTON_UP, POINTER_CHANGE_FIFTHBUTTON_DOWN, POINTER_CHANGE_FIFTHBUTTON_UP } POINTER_BUTTON_CHANGE_TYPE; + // POINTER_CHANGE_FOURTHBUTTON_DOWN, POINTER_CHANGE_FOURTHBUTTON_UP, POINTER_CHANGE_FIFTHBUTTON_DOWN, POINTER_CHANGE_FIFTHBUTTON_UP + // } POINTER_BUTTON_CHANGE_TYPE; [PInvokeData("winuser.h", MSDNShortId = "DF5F60F6-8FD9-41EB-AF2A-09A17513659C")] public enum POINTER_BUTTON_CHANGE_TYPE { @@ -130,6 +131,23 @@ namespace Vanara.PInvoke POINTER_DEVICE_TYPE_TOUCH_PAD, } + /// Identifies the visual feedback behaviors available to CreateSyntheticPointerDevice. + // https://docs.microsoft.com/en-us/windows/win32/api/winuser/ne-winuser-pointer_feedback_mode typedef enum { + // POINTER_FEEDBACK_DEFAULT, POINTER_FEEDBACK_INDIRECT, POINTER_FEEDBACK_NONE } ; + [PInvokeData("winuser.h", MSDNShortId = "73D024E9-F83B-408F-BC96-6851AB4603AE")] + public enum POINTER_FEEDBACK_MODE + { + /// Visual feedback might be suppressed by the user's pen (Settings -> Devices -> Pen & Windows Ink) and touch + /// (Settings -> Ease of Access -> Cursor & pointer size) settings. + POINTER_FEEDBACK_DEFAULT = 1, + + /// Visual feedback overrides the user's pen and touch settings. + POINTER_FEEDBACK_INDIRECT, + + /// Visual feedback is disabled. + POINTER_FEEDBACK_NONE + } + /// Values that can appear in the pointerFlags field of the POINTER_INFO structure. /// /// XBUTTON1 and XBUTTON2 are additional buttons used on many mouse devices. They return the same data as standard mouse buttons. @@ -205,24 +223,24 @@ namespace Vanara.PInvoke /// /// The primary pointer is identified from all current user interactions on the system(mouse, touch, pen, and so on). As such, /// the primary pointer might not be associated with your app.The first contact in a multi-touch interaction is set as the - /// primary pointer.Once a primary pointer is identified, all contacts must be lifted before a new contact can be identified as a - /// primary pointer.For apps that don't process pointer input, only the primary pointer's events are promoted to mouse events. + /// primary pointer.Once a primary pointer is identified, all contacts must be lifted before a new contact can be identified as + /// a primary pointer.For apps that don't process pointer input, only the primary pointer's events are promoted to mouse events. /// /// POINTER_FLAG_PRIMARY = 0x00002000, /// - /// Confidence is a suggestion from the source device about whether the pointer represents an intended or accidental interaction, - /// which is especially relevant for PT_TOUCH pointers where an accidental interaction (such as with the palm of the hand) can - /// trigger input. The presence of this flag indicates that the source device has high confidence that this input is part of an - /// intended interaction. + /// Confidence is a suggestion from the source device about whether the pointer represents an intended or accidental + /// interaction, which is especially relevant for PT_TOUCH pointers where an accidental interaction (such as with the palm of + /// the hand) can trigger input. The presence of this flag indicates that the source device has high confidence that this input + /// is part of an intended interaction. /// POINTER_FLAG_CONFIDENCE = 0x000004000, /// - /// Indicates that the pointer is departing in an abnormal manner, such as when the system receives invalid input for the pointer - /// or when a device with active pointers departs abruptly. If the application receiving the input is in a position to do so, it - /// should treat the interaction as not completed and reverse any effects of the concerned pointer. + /// Indicates that the pointer is departing in an abnormal manner, such as when the system receives invalid input for the + /// pointer or when a device with active pointers departs abruptly. If the application receiving the input is in a position to + /// do so, it should treat the interaction as not completed and reverse any effects of the concerned pointer. /// POINTER_FLAG_CANCELED = 0x000008000, @@ -257,15 +275,15 @@ namespace Vanara.PInvoke } /// Identifies the pointer input types. - // https://docs.microsoft.com/en-us/windows/desktop/api/winuser/ne-winuser-tagpointer_input_type typedef enum tagPOINTER_INPUT_TYPE { - // PT_POINTER, PT_TOUCH, PT_PEN, PT_MOUSE, PT_TOUCHPAD } ; + // https://docs.microsoft.com/en-us/windows/desktop/api/winuser/ne-winuser-tagpointer_input_type typedef enum tagPOINTER_INPUT_TYPE + // { PT_POINTER, PT_TOUCH, PT_PEN, PT_MOUSE, PT_TOUCHPAD } ; [PInvokeData("winuser.h", MSDNShortId = "3334DCD0-DAE1-4AC2-AB36-23D114803100")] public enum POINTER_INPUT_TYPE { /// - /// Generic pointer type. This type never appears in pointer messages or pointer data. Some data query functions allow the caller - /// to restrict the query to specific pointer type. The PT_POINTER type can be used in these functions to specify that the query - /// is to include pointers of all types + /// Generic pointer type. This type never appears in pointer messages or pointer data. Some data query functions allow the + /// caller to restrict the query to specific pointer type. The PT_POINTER type can be used in these functions to specify that + /// the query is to include pointers of all types /// PT_POINTER, @@ -283,8 +301,8 @@ namespace Vanara.PInvoke } /// Values that can appear in the touchFlags field of the POINTER_TOUCH_INFO structure. - // https://docs.microsoft.com/en-us/previous-versions/hh454914(v%3dvs.85) typedef enum tagTOUCH_FLAGS { TOUCH_FLAGS_NONE = 0x00000000 - // } TOUCH_FLAGS; + // https://docs.microsoft.com/en-us/previous-versions/hh454914(v%3dvs.85) typedef enum tagTOUCH_FLAGS { TOUCH_FLAGS_NONE = + // 0x00000000 } TOUCH_FLAGS; [PInvokeData("Winuser.h", MSDNShortId = "")] public enum TOUCH_FLAGS { @@ -310,6 +328,36 @@ namespace Vanara.PInvoke TOUCH_MASK_PRESSURE = 0x00000004, } + /// + /// Configures the pointer injection device for the calling application, and initializes the maximum number of simultaneous pointers + /// that the app can inject. + /// + /// The pointer injection device type. Must be either PT_TOUCH or PT_PEN. + /// + /// The maximum number of contacts. + /// For PT_TOUCH this value must be greater than 0 and less than or equal to MAX_TOUCH_COUNT. + /// For PT_PEN this value must be 1. + /// + /// The contact visualization mode. + /// + /// If the function succeeds, the return value is a handle to the pointer injection device. Otherwise, it returns null. To retrieve + /// extended error information, call the GetLastError function. + /// + // https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-createsyntheticpointerdevice HSYNTHETICPOINTERDEVICE + // CreateSyntheticPointerDevice( POINTER_INPUT_TYPE pointerType, ULONG maxCount, POINTER_FEEDBACK_MODE mode ); + [DllImport(Lib.User32, SetLastError = true, ExactSpelling = true)] + [PInvokeData("winuser.h", MSDNShortId = "251F837F-DF9A-4A94-B790-73AA7196E4A9")] + public static extern SafeHSYNTHETICPOINTERDEVICE CreateSyntheticPointerDevice(POINTER_INPUT_TYPE pointerType, uint maxCount, POINTER_FEEDBACK_MODE mode); + + /// Destroys the specified pointer injection device. + /// A handle to the pointer injection device. + /// This function does not return a value. + // https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-destroysyntheticpointerdevice void + // DestroySyntheticPointerDevice( HSYNTHETICPOINTERDEVICE device ); + [DllImport(Lib.User32, SetLastError = false, ExactSpelling = true)] + [PInvokeData("winuser.h", MSDNShortId = "236484FC-D552-45CE-A968-B928D020A4C8")] + public static extern void DestroySyntheticPointerDevice(HSYNTHETICPOINTERDEVICE device); + /// Enables the mouse to act as a pointer input device and send WM_POINTER messages. /// TRUE to turn on mouse input support in WM_POINTER. /// @@ -378,8 +426,8 @@ namespace Vanara.PInvoke /// The device handle. /// The number of cursors associated with the pointer device. /// - /// An array of POINTER_DEVICE_CURSOR_INFO structures that contain info about the cursors. If NULL, cursorCount returns the number of - /// cursors associated with the pointer device. + /// An array of POINTER_DEVICE_CURSOR_INFO structures that contain info about the cursors. If NULL, cursorCount returns the number + /// of cursors associated with the pointer device. /// /// /// TRUE if the function succeeds; otherwise, FALSE. If the function fails, call the GetLastError function for more information. @@ -434,8 +482,8 @@ namespace Vanara.PInvoke /// Gets information about the pointer devices attached to the system. /// - /// If pointerDevices is NULL, deviceCount returns the total number of attached pointer devices. Otherwise, deviceCount specifies the - /// number of POINTER_DEVICE_INFO structures pointed to by pointerDevices. + /// If pointerDevices is NULL, deviceCount returns the total number of attached pointer devices. Otherwise, deviceCount specifies + /// the number of POINTER_DEVICE_INFO structures pointed to by pointerDevices. /// /// /// Array of POINTER_DEVICE_INFO structures for the pointer devices attached to the system. If NULL, the total number of attached @@ -504,9 +552,9 @@ namespace Vanara.PInvoke /// /// Having retrieved the entire frame of information, the application can then call the SkipPointerFrameMessages function to skip /// remaining pointer messages associated with this frame that are pending retrieval. This saves the application the overhead of - /// retrieving and processing the remaining messages one by one. However, the SkipPointerFrameMessages function should be used - /// with care and only when the caller can be sure that no other entity on the caller’s thread is expecting to see the remaining - /// pointer messages one by one as they are retrieved. + /// retrieving and processing the remaining messages one by one. However, the SkipPointerFrameMessages function should be + /// used with care and only when the caller can be sure that no other entity on the caller’s thread is expecting to see the + /// remaining pointer messages one by one as they are retrieved. /// /// /// Note that the information retrieved is associated with the pointer frame most recently retrieved by the calling thread. Once the @@ -540,8 +588,8 @@ namespace Vanara.PInvoke /// /// /// - /// For each update that includes a pointer contact (a POINTER_FLAG_UPDATE with POINTER_FLAG_INCONTACT), use the tracking info - /// to determine whether the input is client or non-client. + /// For each update that includes a pointer contact (a POINTER_FLAG_UPDATE with POINTER_FLAG_INCONTACT), use the tracking + /// info to determine whether the input is client or non-client. /// /// /// @@ -601,9 +649,9 @@ namespace Vanara.PInvoke /// /// Having retrieved the entire frame of information, the application can then call the SkipPointerFrameMessages function to skip /// remaining pointer messages associated with this frame that are pending retrieval. This saves the application the overhead of - /// retrieving and processing the remaining messages one by one. However, the SkipPointerFrameMessages function should be used - /// with care and only when the caller can be sure that no other entity on the caller’s thread is expecting to see the remaining - /// pointer messages one by one as they are retrieved. + /// retrieving and processing the remaining messages one by one. However, the SkipPointerFrameMessages function should be + /// used with care and only when the caller can be sure that no other entity on the caller’s thread is expecting to see the + /// remaining pointer messages one by one as they are retrieved. /// /// The frame contains only pointers that are currently owned by the same window as the specified pointer. /// @@ -646,8 +694,8 @@ namespace Vanara.PInvoke /// /// /// - /// For each update that includes a pointer contact (a POINTER_FLAG_UPDATE with POINTER_FLAG_INCONTACT), use the tracking info - /// to determine whether the input is client or non-client. + /// For each update that includes a pointer contact (a POINTER_FLAG_UPDATE with POINTER_FLAG_INCONTACT), use the tracking + /// info to determine whether the input is client or non-client. /// /// /// @@ -705,9 +753,9 @@ namespace Vanara.PInvoke /// /// Having retrieved the entire frame of information, the application can then call the SkipPointerFrameMessages function to skip /// remaining pointer messages associated with this frame that are pending retrieval. This saves the application the overhead of - /// retrieving and processing the remaining messages one by one. However, the SkipPointerFrameMessages function should be used - /// with care and only when the caller can be sure that no other entity on the caller’s thread is expecting to see the remaining - /// pointer messages one by one as they are retrieved. + /// retrieving and processing the remaining messages one by one. However, the SkipPointerFrameMessages function should be + /// used with care and only when the caller can be sure that no other entity on the caller’s thread is expecting to see the + /// remaining pointer messages one by one as they are retrieved. /// /// /// Note that the information retrieved is associated with the pointer frame most recently retrieved by the calling thread. Once the @@ -742,8 +790,8 @@ namespace Vanara.PInvoke /// /// /// - /// For each update that includes a pointer contact (a POINTER_FLAG_UPDATE with POINTER_FLAG_INCONTACT), use the tracking info - /// to determine whether the input is client or non-client. + /// For each update that includes a pointer contact (a POINTER_FLAG_UPDATE with POINTER_FLAG_INCONTACT), use the tracking + /// info to determine whether the input is client or non-client. /// /// /// @@ -754,8 +802,8 @@ namespace Vanara.PInvoke /// /// /// - // https://docs.microsoft.com/en-us/windows/desktop/api/winuser/nf-winuser-getpointerframepeninfo BOOL GetPointerFramePenInfo( UINT32 - // pointerId, UINT32 *pointerCount, POINTER_PEN_INFO *penInfo ); + // https://docs.microsoft.com/en-us/windows/desktop/api/winuser/nf-winuser-getpointerframepeninfo BOOL GetPointerFramePenInfo( + // UINT32 pointerId, UINT32 *pointerCount, POINTER_PEN_INFO *penInfo ); [DllImport(Lib.User32, SetLastError = true, ExactSpelling = true)] [PInvokeData("winuser.h", MSDNShortId = "52db9b96-7f9e-41d7-88f7-b9c7691a6511")] [return: MarshalAs(UnmanagedType.Bool)] @@ -804,9 +852,9 @@ namespace Vanara.PInvoke /// /// Having retrieved the entire frame of information, the application can then call the SkipPointerFrameMessages function to skip /// remaining pointer messages associated with this frame that are pending retrieval. This saves the application the overhead of - /// retrieving and processing the remaining messages one by one. However, the SkipPointerFrameMessages function should be used - /// with care and only when the caller can be sure that no other entity on the caller’s thread is expecting to see the remaining - /// pointer messages one by one as they are retrieved. + /// retrieving and processing the remaining messages one by one. However, the SkipPointerFrameMessages function should be + /// used with care and only when the caller can be sure that no other entity on the caller’s thread is expecting to see the + /// remaining pointer messages one by one as they are retrieved. /// /// The frame contains only pointers that are currently owned by the same window as the specified pointer. /// @@ -850,8 +898,8 @@ namespace Vanara.PInvoke /// /// /// - /// For each update that includes a pointer contact (a POINTER_FLAG_UPDATE with POINTER_FLAG_INCONTACT), use the tracking info - /// to determine whether the input is client or non-client. + /// For each update that includes a pointer contact (a POINTER_FLAG_UPDATE with POINTER_FLAG_INCONTACT), use the tracking + /// info to determine whether the input is client or non-client. /// /// /// @@ -909,9 +957,9 @@ namespace Vanara.PInvoke /// /// Having retrieved the entire frame of information, the application can then call the SkipPointerFrameMessages function to skip /// remaining pointer messages associated with this frame that are pending retrieval. This saves the application the overhead of - /// retrieving and processing the remaining messages one by one. However, the SkipPointerFrameMessages function should be used - /// with care and only when the caller can be sure that no other entity on the caller’s thread is expecting to see the remaining - /// pointer messages one by one as they are retrieved. + /// retrieving and processing the remaining messages one by one. However, the SkipPointerFrameMessages function should be + /// used with care and only when the caller can be sure that no other entity on the caller’s thread is expecting to see the + /// remaining pointer messages one by one as they are retrieved. /// /// /// Note that the information retrieved is associated with the pointer frame most recently retrieved by the calling thread. Once the @@ -946,8 +994,8 @@ namespace Vanara.PInvoke /// /// /// - /// For each update that includes a pointer contact (a POINTER_FLAG_UPDATE with POINTER_FLAG_INCONTACT), use the tracking info - /// to determine whether the input is client or non-client. + /// For each update that includes a pointer contact (a POINTER_FLAG_UPDATE with POINTER_FLAG_INCONTACT), use the tracking + /// info to determine whether the input is client or non-client. /// /// /// @@ -966,8 +1014,8 @@ namespace Vanara.PInvoke public static extern bool GetPointerFrameTouchInfo(uint pointerId, ref uint pointerCount, [In, Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] POINTER_TOUCH_INFO[] touchInfo); /// - /// Gets the entire frame of touch-based information (including coalesced input frames) for the specified pointers (of type PT_TOUCH) - /// associated with the current message. + /// Gets the entire frame of touch-based information (including coalesced input frames) for the specified pointers (of type + /// PT_TOUCH) associated with the current message. /// /// An identifier of the pointer for which to retrieve frame information. /// @@ -1008,9 +1056,9 @@ namespace Vanara.PInvoke /// /// Having retrieved the entire frame of information, the application can then call the SkipPointerFrameMessages function to skip /// remaining pointer messages associated with this frame that are pending retrieval. This saves the application the overhead of - /// retrieving and processing the remaining messages one by one. However, the SkipPointerFrameMessages function should be used - /// with care and only when the caller can be sure that no other entity on the caller’s thread is expecting to see the remaining - /// pointer messages one by one as they are retrieved. + /// retrieving and processing the remaining messages one by one. However, the SkipPointerFrameMessages function should be + /// used with care and only when the caller can be sure that no other entity on the caller’s thread is expecting to see the + /// remaining pointer messages one by one as they are retrieved. /// /// The frame contains only pointers that are currently owned by the same window as the specified pointer. /// @@ -1054,8 +1102,8 @@ namespace Vanara.PInvoke /// /// /// - /// For each update that includes a pointer contact (a POINTER_FLAG_UPDATE with POINTER_FLAG_INCONTACT), use the tracking info - /// to determine whether the input is client or non-client. + /// For each update that includes a pointer contact (a POINTER_FLAG_UPDATE with POINTER_FLAG_INCONTACT), use the tracking + /// info to determine whether the input is client or non-client. /// /// /// @@ -1113,8 +1161,8 @@ namespace Vanara.PInvoke /// /// Gets the information associated with the individual inputs, if any, that were coalesced into the current message for the - /// specified pointer. The most recent input is included in the returned history and is the same as the most recent input returned by - /// the GetPointerInfo function. + /// specified pointer. The most recent input is included in the returned history and is the same as the most recent input returned + /// by the GetPointerInfo function. /// /// An identifier of the pointer for which to retrieve information. /// @@ -1123,7 +1171,8 @@ namespace Vanara.PInvoke /// structures available is the same as the historyCount field of the POINTER_INFO structure returned by a call to GetPointerInfo. /// /// - /// Address of an array of POINTER_INFO structures to receive the pointer information. This parameter can be NULL if *entriesCount is zero. + /// Address of an array of POINTER_INFO structures to receive the pointer information. This parameter can be NULL if *entriesCount + /// is zero. /// /// /// If the function succeeds, the return value is non-zero. @@ -1191,8 +1240,8 @@ namespace Vanara.PInvoke /// /// /// If a transform is applied on the message consumer, use GetPointerInputTransform to retrieve the transform on the message - /// consumer at the time the input occurred. The inverse of this transform can then be used to convert pointer input coordinates from - /// screen coordinates to the client coordinates of the message consumer. + /// consumer at the time the input occurred. The inverse of this transform can then be used to convert pointer input coordinates + /// from screen coordinates to the client coordinates of the message consumer. /// /// /// If an input transform is not associated with the input, the GetPointerInputTransform function fails with the last error @@ -1214,12 +1263,13 @@ namespace Vanara.PInvoke /// /// /// If an application calls GetPointerFrameInfo, it can call GetPointerInputTransform with the same pointer Id and a single - /// INPUT_TRANSFORM output buffer to get the input transform associated with the data. The same input transform applies to the entire frame. + /// INPUT_TRANSFORM output buffer to get the input transform associated with the data. The same input transform applies to the + /// entire frame. /// /// - /// If an application calls GetPointerInfoHistory, it can call GetPointerInputTransform with the same pointer Id and an output - /// buffer to hold the entries retrieved using GetPointerInfoHistory. Each input transform in the returned array can be used - /// with the corresponding entry in the array returned by GetPointerInfoHistory. + /// If an application calls GetPointerInfoHistory, it can call GetPointerInputTransform with the same pointer Id and an + /// output buffer to hold the entries retrieved using GetPointerInfoHistory. Each input transform in the returned array can + /// be used with the corresponding entry in the array returned by GetPointerInfoHistory. /// /// /// If an application calls GetPointerFrameInfoHistory, it can call GetPointerInputTransform with the same pointer Id and an @@ -1303,8 +1353,8 @@ namespace Vanara.PInvoke /// If the application does not process pointer input messages as fast as they are generated, some moves may be coalesced. When an /// application receives a coalescable pointer (of type PT_PEN) message, it can use the GetPointerPenInfoHistory function to /// retrieve information for all the individual inputs, if any, that were coalesced into the message. Note that the information - /// retrieved is associated with the pointer message most recently retrieved by the calling thread. Once the calling thread retrieves - /// its next message, the information associated with the previous message may no longer be available. + /// retrieved is associated with the pointer message most recently retrieved by the calling thread. Once the calling thread + /// retrieves its next message, the information associated with the previous message may no longer be available. /// /// /// The information retrieved appears in reverse chronological order, with the most recent entry in the first row of the returned @@ -1379,9 +1429,9 @@ namespace Vanara.PInvoke /// An identifier of the pointer for which to retrieve information. /// /// A pointer to a variable that specifies the count of structures in the buffer to which touchInfo points. If - /// GetPointerTouchInfoHistory succeeds, entriesCount is updated with the total count of structures available. The total count - /// of structures available is the same as the historyCount field in the POINTER_INFO structure returned by a call to GetPointerInfo - /// or GetPointerTouchInfo. + /// GetPointerTouchInfoHistory succeeds, entriesCount is updated with the total count of structures available. The total + /// count of structures available is the same as the historyCount field in the POINTER_INFO structure returned by a call to + /// GetPointerInfo or GetPointerTouchInfo. /// /// /// Address of an array of POINTER_TOUCH_INFO structures to receive the pointer information. This parameter can be NULL if @@ -1396,8 +1446,8 @@ namespace Vanara.PInvoke /// If the application does not process pointer input messages as fast as they are generated, some moves may be coalesced. When an /// application receives a coalescable pointer (of type PT_TOUCH) message, it can use the GetPointerTouchInfoHistory function /// to retrieve information for all the individual inputs, if any, that were coalesced into the message. Note that the information - /// retrieved is associated with the pointer message most recently retrieved by the calling thread. Once the calling thread retrieves - /// its next message, the information associated with the previous message may no longer be available. + /// retrieved is associated with the pointer message most recently retrieved by the calling thread. Once the calling thread + /// retrieves its next message, the information associated with the previous message may no longer be available. /// /// /// The information retrieved appears in reverse chronological order, with the most recent entry in the first row of the returned @@ -1472,6 +1522,29 @@ namespace Vanara.PInvoke [PInvokeData("winuser.h", MSDNShortId = "5BE2748B-0124-4647-A77E-EA2937C7B1AD")] public static extern uint GetUnpredictedMessagePos(); + /// Simulates pointer input (pen or touch). + /// A handle to the pointer injection device created by CreateSyntheticPointerDevice. + /// + /// Array of injected pointers. + /// The type must match the pointerType parameter of the CreateSyntheticPointerDevice call that created the injection device. + /// The ptPixelLocation for each POINTER_TYPE_INFO is specified relative to top left of the virtual screen: + /// + /// + /// The number of contacts. + /// For PT_TOUCH this value must be greater than 0 and less than or equal to MAX_TOUCH_COUNT. + /// For PT_PEN this value must be 1. + /// + /// + /// If this function succeeds, it returns TRUE. + /// Otherwise, it returns FALSE. To retrieve extended error information, call the GetLastError function. + /// + // https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-injectsyntheticpointerinput BOOL + // InjectSyntheticPointerInput( HSYNTHETICPOINTERDEVICE device, const POINTER_TYPE_INFO *pointerInfo, UINT32 count ); + [DllImport(Lib.User32, SetLastError = true, ExactSpelling = true)] + [PInvokeData("winuser.h", MSDNShortId = "9F7FC5E2-F4B8-42C2-A4BE-240E36AFC13B")] + [return: MarshalAs(UnmanagedType.Bool)] + public static extern bool InjectSyntheticPointerInput(HSYNTHETICPOINTERDEVICE device, [In, MarshalAs(UnmanagedType.LPArray)] POINTER_TYPE_INFO[] pointerInfo, uint count); + /// /// Indicates whether EnableMouseInPointer is set for the mouse to act as a pointer input device and send WM_POINTER messages. /// @@ -1487,8 +1560,8 @@ namespace Vanara.PInvoke /// /// On the first call to EnableMouseInPointer in the process lifetime, the state is changed as specified and the call succeeds. /// - /// On subsequent calls to EnableMouseInPointer, the state will not change. If the current state is not equal to the specified state, - /// the call fails. + /// On subsequent calls to EnableMouseInPointer, the state will not change. If the current state is not equal to the specified + /// state, the call fails. /// /// Call IsMouseInPointerEnabled to verify the mouse-in-pointer state. /// @@ -1523,13 +1596,13 @@ namespace Vanara.PInvoke /// /// The window to register as a global redirection target. /// - /// Redirection can cause the foreground window to lose activation (focus). To avoid this, ensure the window is a message-only window - /// or has the WS_EX_NOACTIVATE style set. + /// Redirection can cause the foreground window to lose activation (focus). To avoid this, ensure the window is a message-only + /// window or has the WS_EX_NOACTIVATE style set. /// /// /// - /// Type of pointer input to be redirected to the specified window. This is any valid and supported value from the POINTER_INPUT_TYPE - /// enumeration. Note that the generic PT_POINTER type and the PT_MOUSE type are not valid in this parameter. + /// Type of pointer input to be redirected to the specified window. This is any valid and supported value from the + /// POINTER_INPUT_TYPE enumeration. Note that the generic PT_POINTER type and the PT_MOUSE type are not valid in this parameter. /// /// /// If the function succeeds, the return value is non-zero. @@ -1607,18 +1680,19 @@ namespace Vanara.PInvoke /// /// /// When an application sees a pointer message, it can use the GetPointerFrameInfo function to retrieve the entire pointer input - /// frame to which the pointer message belongs, hence obtaining an updated view of all of the pointers currently owned by the window. - /// Note that the returned frame contains only pointers that are currently owned by the same window as the specified pointer. + /// frame to which the pointer message belongs, hence obtaining an updated view of all of the pointers currently owned by the + /// window. Note that the returned frame contains only pointers that are currently owned by the same window as the specified pointer. /// /// /// Having retrieved the entire frame of information, the application can then call the SkipPointerFrameMessages function to - /// skip remaining pointer messages associated with this frame that are pending retrieval. This saves the application the overhead of - /// retrieving and processing the remaining messages one by one. + /// skip remaining pointer messages associated with this frame that are pending retrieval. This saves the application the overhead + /// of retrieving and processing the remaining messages one by one. /// /// /// Warning The SkipPointerFrameMessages function should be used only when the caller can be sure that no other entity /// on the caller’s thread (such as Direct Manipulation) is expecting to retrieve pending pointer messages. For this reason, - /// SkipPointerFrameMessages should not be used in conjunction with Direct Manipulation when processing multiple, simultaneous interactions. + /// SkipPointerFrameMessages should not be used in conjunction with Direct Manipulation when processing multiple, + /// simultaneous interactions. /// /// /// Note that the information retrieved is associated with the pointer frame most recently retrieved by the calling thread. Once the @@ -1661,8 +1735,8 @@ namespace Vanara.PInvoke /// If the specified pointer input type is not valid, this function fails with the last error set to ERROR_INVALID_PARAMETER. /// If the calling thread does not own the specified window, this function fails with the last error set to ERROR_ACCESS_DENIED. /// - /// If the specified window is not the registered global redirection target for the specified pointer input type on its desktop, this - /// function takes no action and returns success. + /// If the specified window is not the registered global redirection target for the specified pointer input type on its desktop, + /// this function takes no action and returns success. /// /// // https://docs.microsoft.com/en-us/windows/desktop/api/winuser/nf-winuser-unregisterpointerinputtarget BOOL @@ -1672,6 +1746,54 @@ namespace Vanara.PInvoke [return: MarshalAs(UnmanagedType.Bool)] public static extern bool UnregisterPointerInputTarget(HWND hwnd, POINTER_INPUT_TYPE pointerType); + /// Provides a handle to a synthetic pointer device. + [StructLayout(LayoutKind.Sequential)] + public struct HSYNTHETICPOINTERDEVICE : IHandle + { + private IntPtr handle; + + /// Initializes a new instance of the struct. + /// An object that represents the pre-existing handle to use. + public HSYNTHETICPOINTERDEVICE(IntPtr preexistingHandle) => handle = preexistingHandle; + + /// Returns an invalid handle by instantiating a object with . + public static HSYNTHETICPOINTERDEVICE NULL => new HSYNTHETICPOINTERDEVICE(IntPtr.Zero); + + /// Gets a value indicating whether this instance is a null handle. + public bool IsNull => handle == IntPtr.Zero; + + /// Performs an explicit conversion from to . + /// The handle. + /// The result of the conversion. + public static explicit operator IntPtr(HSYNTHETICPOINTERDEVICE h) => h.handle; + + /// Performs an implicit conversion from to . + /// The pointer to a handle. + /// The result of the conversion. + public static implicit operator HSYNTHETICPOINTERDEVICE(IntPtr h) => new HSYNTHETICPOINTERDEVICE(h); + + /// Implements the operator !=. + /// The first handle. + /// The second handle. + /// The result of the operator. + public static bool operator !=(HSYNTHETICPOINTERDEVICE h1, HSYNTHETICPOINTERDEVICE h2) => !(h1 == h2); + + /// Implements the operator ==. + /// The first handle. + /// The second handle. + /// The result of the operator. + public static bool operator ==(HSYNTHETICPOINTERDEVICE h1, HSYNTHETICPOINTERDEVICE h2) => h1.Equals(h2); + + /// + public override bool Equals(object obj) => obj is HSYNTHETICPOINTERDEVICE h ? handle == h.handle : false; + + /// + public override int GetHashCode() => handle.GetHashCode(); + + /// + public IntPtr DangerousGetHandle() => handle; + } + /// /// Defines the matrix that represents a transform on a message consumer. This matrix can be used to transform pointer input data /// from client coordinates to screen coordinates, while the inverse can be used to transform pointer input data from screen @@ -1880,10 +2002,10 @@ namespace Vanara.PInvoke /// Type: POINT /// The predicted screen coordinates of the pointer, in pixels. /// - /// The predicted value is based on the pointer position reported by the digitizer and the motion of the pointer. This correction - /// can compensate for visual lag due to inherent delays in sensing and processing the pointer location on the digitizer. This is - /// applicable to pointers of type PT_TOUCH. For other pointer types, the predicted value will be the same as the non-predicted - /// value (see ptPixelLocationRaw). + /// The predicted value is based on the pointer position reported by the digitizer and the motion of the pointer. This + /// correction can compensate for visual lag due to inherent delays in sensing and processing the pointer location on the + /// digitizer. This is applicable to pointers of type PT_TOUCH. For other pointer types, the predicted value will be the same as + /// the non-predicted value (see ptPixelLocationRaw). /// /// public System.Drawing.Point ptPixelLocation; @@ -1892,10 +2014,10 @@ namespace Vanara.PInvoke /// Type: POINT /// The predicted screen coordinates of the pointer, in HIMETRIC units. /// - /// The predicted value is based on the pointer position reported by the digitizer and the motion of the pointer. This correction - /// can compensate for visual lag due to inherent delays in sensing and processing the pointer location on the digitizer. This is - /// applicable to pointers of type PT_TOUCH. For other pointer types, the predicted value will be the same as the non-predicted - /// value (see ptHimetricLocationRaw). + /// The predicted value is based on the pointer position reported by the digitizer and the motion of the pointer. This + /// correction can compensate for visual lag due to inherent delays in sensing and processing the pointer location on the + /// digitizer. This is applicable to pointers of type PT_TOUCH. For other pointer types, the predicted value will be the same as + /// the non-predicted value (see ptHimetricLocationRaw). /// /// public System.Drawing.Point ptHimetricLocation; @@ -1916,11 +2038,11 @@ namespace Vanara.PInvoke /// Type: DWORD /// 0 or the time stamp of the message, based on the system tick count when the message was received. /// - /// The application can specify the input time stamp in either dwTime or PerformanceCount. The value cannot be more - /// recent than the current tick count or QueryPerformanceCount (QPC) value of the injection thread. Once a frame is - /// injected with a time stamp, all subsequent frames must include a timestamp until all contacts in the frame go to an UP state. - /// The custom timestamp value must also be provided for the first element in the contacts array. The time stamp values after the - /// first element are ignored. The custom timestamp value must increment in every injection frame. + /// The application can specify the input time stamp in either dwTime or PerformanceCount. The value cannot be + /// more recent than the current tick count or QueryPerformanceCount (QPC) value of the injection thread. Once a frame is + /// injected with a time stamp, all subsequent frames must include a timestamp until all contacts in the frame go to an UP + /// state. The custom timestamp value must also be provided for the first element in the contacts array. The time stamp values + /// after the first element are ignored. The custom timestamp value must increment in every injection frame. /// /// /// When PerformanceCount is specified, the time stamp will be converted to the current time in .1 millisecond resolution @@ -1933,9 +2055,9 @@ namespace Vanara.PInvoke /// InjectTouchInput cannot switch between dwTime and PerformanceCount once injection has started. /// /// If neither dwTime and PerformanceCount are specified, InjectTouchInput allocates the timestamp based on the - /// timing of the call. If InjectTouchInput calls are repeatedly less than 0.1 millisecond apart, ERROR_NOT_READY might be - /// returned. The error will not invalidate the input immediately, but the injection application needs to retry the same frame - /// again for injection to succeed. + /// timing of the call. If InjectTouchInput calls are repeatedly less than 0.1 millisecond apart, ERROR_NOT_READY might + /// be returned. The error will not invalidate the input immediately, but the injection application needs to retry the same + /// frame again for injection to succeed. /// /// public uint dwTime; @@ -2044,9 +2166,9 @@ namespace Vanara.PInvoke } /// Defines basic touch information common to all pointer types. - // https://docs.microsoft.com/en-us/windows/desktop/api/winuser/ns-winuser-tagpointer_touch_info 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; + // https://docs.microsoft.com/en-us/windows/desktop/api/winuser/ns-winuser-tagpointer_touch_info 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; [PInvokeData("winuser.h", MSDNShortId = "fee176ba-ad07-3141-ab4d-1b8c335fd102")] [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)] public struct POINTER_TOUCH_INFO @@ -2066,8 +2188,8 @@ namespace Vanara.PInvoke /// /// Type: Touch Mask /// - /// Indicates which of the optional fields contain valid values. The member can be zero or any combination of the values from the - /// Touch Mask constants. + /// Indicates which of the optional fields contain valid values. The member can be zero or any combination of the values from + /// the Touch Mask constants. /// /// public TOUCH_MASK touchMask; @@ -2079,9 +2201,9 @@ namespace Vanara.PInvoke /// this field defaults to a 0-by-0 rectangle centered around the pointer location. /// /// - /// The predicted value is based on the pointer position reported by the digitizer and the motion of the pointer. This correction - /// can compensate for visual lag due to inherent delays in sensing and processing the pointer location on the digitizer. This is - /// applicable to pointers of type PT_TOUCH. + /// The predicted value is based on the pointer position reported by the digitizer and the motion of the pointer. This + /// correction can compensate for visual lag due to inherent delays in sensing and processing the pointer location on the + /// digitizer. This is applicable to pointers of type PT_TOUCH. /// /// public RECT rcContact; @@ -2095,8 +2217,8 @@ namespace Vanara.PInvoke /// /// Type: UINT32 /// - /// 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. + /// 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. /// @@ -2109,6 +2231,48 @@ namespace Vanara.PInvoke public uint pressure; } + /// Contains information about the pointer input type. + // https://docs.microsoft.com/en-us/windows/win32/api/winuser/ns-winuser-pointer_type_info typedef struct tagPOINTER_TYPE_INFO { + // POINTER_INPUT_TYPE type; union { POINTER_TOUCH_INFO touchInfo; POINTER_PEN_INFO penInfo; } DUMMYUNIONNAME; } POINTER_TYPE_INFO, *PPOINTER_TYPE_INFO; + [PInvokeData("winuser.h", MSDNShortId = "5EA8012C-CF0C-4771-9A9C-A9DC218DC9AB")] + [StructLayout(LayoutKind.Explicit)] + public struct POINTER_TYPE_INFO + { + /// The pointer input device. + [FieldOffset(0)] + public POINTER_INPUT_TYPE type; + + /// Basic touch information common to all pointer types. + [FieldOffset(4)] + public POINTER_TOUCH_INFO touchInfo; + + /// Basic pen information common to all pointer types. + [FieldOffset(4)] + public POINTER_PEN_INFO penInfo; + } + + /// Provides a for that is disposed using . + public class SafeHSYNTHETICPOINTERDEVICE : SafeHANDLE + { + /// Initializes a new instance of the class and assigns an existing handle. + /// An object that represents the pre-existing handle to use. + /// + /// to reliably release the handle during the finalization phase; otherwise, (not recommended). + /// + public SafeHSYNTHETICPOINTERDEVICE(IntPtr preexistingHandle, bool ownsHandle = true) : base(preexistingHandle, ownsHandle) { } + + /// Initializes a new instance of the class. + private SafeHSYNTHETICPOINTERDEVICE() : base() { } + + /// Performs an implicit conversion from to . + /// The safe handle instance. + /// The result of the conversion. + public static implicit operator HSYNTHETICPOINTERDEVICE(SafeHSYNTHETICPOINTERDEVICE h) => h.handle; + + /// + protected override bool InternalReleaseHandle() { DestroySyntheticPointerDevice(handle); return true; } + } + /* GET_POINTERID_WPARAM macro HAS_POINTER_CONFIDENCE_WPARAM macro