本节包含有关 Windows Touch 输入的编程参考。
本 Windows Touch API 编程参考包含以下各节。
节 | 说明 |
---|---|
函数 | 包含用于 Windows Touch 输入的函数。 |
宏 | 包含用于 Windows Touch 输入的宏。 |
消息 | 包含用于 Windows Touch 输入的消息。 |
结构 | 包含用于 Windows Touch 输入的结构。 |
函数
本节包含用于 Windows Touch 输入的函数。
下面的函数用于 Windows Touch 输入。
函数 | 说明 |
---|---|
CloseTouchInputHandle | 关闭触控输入句柄,释放与之关联的进程内存,并使句柄无效。 |
GetTouchInputInfo | 检索有关特定触控输入句柄关联的触控输入的详细信息。 |
IsTouchWindow | 检查指定的窗口是否具有触控功能,并且可以选择检索为窗口的触控功能设置的修饰符标志。 |
RegisterTouchWindow | 将窗口注册为具有触控功能。 |
UnregisterTouchWindow | 将窗口注册为不再具有触控功能。 |
SendMessage、PostMessage 和相关函数 | 包含有关转发消息的注意事项。 |
宏
下面的宏用于 Windows Touch 输入。
宏 | 说明 |
---|---|
TOUCH_COORD_TO_PIXEL | 将触控坐标转换成像素坐标。 |
消息
本节包含用于多点触控输入的消息。
下面的消息用于多点触控输入。
消息 | 说明 |
---|---|
WM_TOUCH | 指示一个或多个触控点(如手指或笔)已触摸到具有触控功能的数字化器表面。 |
结构
本节包含 Windows Touch 输入的结构。
下面的结构用于 Windows Touch 输入。
结构 | 说明 |
---|---|
TOUCHINPUT | 封装触控输入的数据。 |
CloseTouchInputHandle 函数
关闭触控输入句柄,释放与之关联的进程内存,并使句柄无效。
语法
BOOL WINAPI CloseTouchInputHandle(__in HTOUCHINPUT hTouchInput);
参数
-
hTouchInput [in]
-
在触控消息的 LPARAM 中接收到的触控输入句柄。如果该句柄无效,则函数将失败,并显示 ERROR_INVALID_HANDLE。请注意,在对CloseTouchInputHandle 的成功调用中使用该句柄之后,或者在将该句柄传递给 DefWindowProc, PostMessage, SendMessage 或它们的某个变量之后,该句柄将无效。
返回值
如果函数成功,则返回值为非零值。
如果函数失败,则返回值为零。若要获取扩展的错误信息,请使用 GetLastError 函数。
评论
调用 CloseTouchInputHandle 将不会释放在对 GetTouchInputInfo 的调用中检索的值关联的内存。传递给 GetTouchInputInfo 的结构中的值将一直有效,直至您删除它们。
GetTouchInputInfo 函数
语法
BOOL WINAPI GetTouchInputInfo( __in HTOUCHINPUT hTouchInput, __in UINT cInputs, __out PTOUCHINPUT pInputs, __in int cbSize );
参数
-
hTouchInput [in]
-
在触控消息的 LPARAM 中接收到的触控输入句柄。如果该句柄无效,则函数将失败,并显示 ERROR_INVALID_HANDLE。请注意,在对CloseTouchInputHandle 的成功调用中使用该句柄之后,或者在将该句柄传递给 DefWindowProc, PostMessage, SendMessage 或它们的某个变量之后,该句柄将无效。
cInputs [in]
-
pInputs 数组中的结构数。理想情况下,这应至少等于消息关联的触控点的数目,如消息 WPARAM 中所示。如果 cInputs 小于触控点的数目,则函数仍将成功,并且在 pInputs 缓冲区中填充有关 cInputs 触控点的信息。
pInputs [out]
-
指向一组 TOUCHINPUT 结构的指针,这些结构用于接收有关指定的触控输入句柄关联的触控点的信息。
cbSize [in]
-
单个 TOUCHINPUT 结构的大小(以字节为单位)。如果 cbSize 不是单个 TOUCHINPUT 结构的大小,则函数将失败,并显示 ERROR_INVALID_PARAMETER。
返回值
如果函数成功,则返回值为非零值。如果函数失败,则返回值为零。若要获取扩展的错误信息,请使用 GetLastError 函数。
评论
调用 CloseTouchInputHandle 将不会释放在对 GetTouchInputInfo 的调用中检索的值关联的内存。传递给 GetTouchInputInfo 的结构中的值将一直有效,直至您删除它们。
IsTouchWindow 函数
检查指定的窗口是否具有触控功能,并且可以选择检索为窗口的触控功能设置的修饰符标志。
语法
BOOL WINAPI IsTouchWindow(__in HWND hWnd, __out_opt PULONG pulFlags);
参数
-
hWnd [in]
-
窗口的句柄。如果调用的线程与指定的窗口不在同一个桌面上,则该函数将失败,并显示ERROR_ACCESS_DENIED 。
pulFlags [out, optional]
-
变量ULONG 的地址,用于接收指定窗口的触控功能的修饰符标志。
返回值
如果窗口支持 Windows Touch,则返回 TRUE;如果窗口不支持 Windows Touch,则返回 FALSE。
评论
下表列出了 pulFlags 输出参数的值。
标志 | 说明 |
---|---|
TWF_FINETOUCH | 指定 hWnd 首选非联合的触控输入。 |
TWF_WANTPALM | 清除此标志将禁用防止手掌误触功能,从而减少获取 WM_TOUCH 消息的延迟。如果您希望在用户触摸应用程序时尽可能快地做出响应,这样做非常有用。 设置此标志将启用防止手掌误触功能,并将阻止将某些 WM_TOUCH 消息发送到您的应用程序。如果您不希望接收因手掌接触而引发的WM_TOUCH 消息,这样做非常有用。 |
UnregisterTouchWindow 函数
将窗口注册为不再具有触控功能。
语法
BOOL WINAPI UnregisterTouchWindow(__in HWND hWnd);
参数
-
hWnd [in]
-
窗口的句柄。如果调用的线程不拥有指定的窗口,则该函数将失败,并显示ERROR_ACCESS_DENIED 。
返回值
如果函数成功,则返回值为非零值。
如果函数失败,则返回值为零。若要获取扩展的错误信息,请使用GetLastError 函数。
评论
即使指定的窗口之前没有注册为具有触控功能,UnregisterTouchWindow 函数也将成功。
SendMessage、PostMessage 和相关函数
如果使用 SendMessage、PostMessage 或其他某个相关函数转发触控消息,则关闭触控输入句柄。如果您已通过调用 GetTouchInputInfo 检索到触控输入句柄引用的信息,则此类数据将保持一直有效,直至您释放内存。
对于接收到通过以上机制之一转发的触控消息的应用程序,该应用程序将拥有其在消息 LPARAM 中收到的触控输入句柄并且负责关闭该句柄。如果您没有通过调用 CloseTouchInputHandle 关闭该句柄,而且将此消息传递给 DefWindowProc,或者使用 SendMessage、PostMessage 或某个相关函数转发此消息,则您将会遇到内存泄露。
注意 触控消息在转发时受常规用户界面特权隔离 (UIPI) 规则的限制。
与 SendMessage 和 PostMessage 相关的函数
下面的函数可影响触控输入句柄的状态。
TOUCH_COORD_TO_PIXEL 宏
语法
long TOUCH_COORD_TO_PIXEL(long l);
参数
-
l
-
将从触控坐标转换成像素的值。
返回值
用像素表示的坐标值。
评论
TOUCH_COORD_TO_PIXEL 宏用于从触控坐标(当前为百分之一像素)转换成像素。触控坐标比像素更加细化,因此应用程序开发人员可以针对专用的应用程序(如图形设计)使用子像素粒度。
示例
case WM_TOUCH: cInputs = LOWORD(wParam); pInputs = new TOUCHINPUT[cInputs]; if (pInputs){ if (GetTouchInputInfo((HTOUCHINPUT)lParam, cInputs, pInputs, sizeof(TOUCHINPUT))){ for (int i=0; i < static_cast<INT>(cInputs); i++){ TOUCHINPUT ti = pInputs[i]; index = GetContactIndex(ti.dwID); if (ti.dwID != 0 && index < MAXPOINTS){ // Do something with your touch input handle ptInput.x = TOUCH_COORD_TO_PIXEL(ti.x); ptInput.y = TOUCH_COORD_TO_PIXEL(ti.y); ScreenToClient(hWnd, &ptInput); if (ti.dwFlags & TOUCHEVENTF_UP){ points[index][0] = -1; points[index][1] = -1; }else{ points[index][0] = ptInput.x; points[index][1] = ptInput.y; } } } } // If you handled the message and don't want anything else done with it, you can close it CloseTouchInputHandle((HTOUCHINPUT)lParam); delete [] pInputs; }else{ // Handle the error here }
WM_TOUCH 消息
参数
-
wParam
-
低位字包含与此消息关联的触控点的数目。已保留高位字以供将来使用。
lParam
-
包含一个触控输入句柄,在调用 GetTouchInputInfo 时可以使用该句柄来接收有关与此消息关联的触控点的详细信息。
此句柄只在当前进程内有效,不应跨进程传递,除非是在 SendMessage 或 PostMessage 调用中用作 LPARAM。
当应用程序不再需要此句柄时,应用程序必须调用 CloseTouchInputHandle 以释放与此句柄关联的进程内存。若未能进行此操作,则会导致应用程序内存泄漏。
请注意,在将此消息传递给 DefWindowProc 之后,此参数中的触控输入句柄不再有效。DefWindowProc 将关闭此句柄并使其无效。
另请注意,在使用 PostMessage、SendMessage 或它们的某个变体转发此消息之后,此参数中的触摸输入句柄不再有效。这些函数将关闭此句柄并使其无效。
返回值
如果应用程序处理此消息,则它应返回 0。
如果应用程序不处理此消息,则它必须调用 DefWindowProc。若不执行此操作,则会因为未关闭触控输入句柄,并且未释放关联的进程内存,从而导致应用程序的内存泄漏。
评论
WM_TOUCH 消息与窗口的 HTTRANSPARENT 区域无关。如果某个窗口返回 HTTRANSPARENT 以响应 WM_NCHITTEST 消息,则鼠标消息转到父窗口,而WM_TOUCH 消息将直接转到该窗口。
示例
以下代码是一个有关如何获取与此消息关联的详细触控输入信息的示例。
UINT cInputs = LOWORD(wParam); PTOUCHINPUT pInputs = new TOUCHINPUT[cInputs]; if (NULL != pInputs) { if (GetTouchInputInfo((HTOUCHINPUT)lParam, cInputs, pInputs, sizeof(TOUCHINPUT))) { // process pInputs if (!CloseTouchInputHandle((HTOUCHINPUT)lParam)) { // error handling } } else { // GetLastError() and error handling } } else { // error handling, presumably out of memory } return DefWindowProc(hWnd, message, wParam, lParam);
TOUCHINPUT 结构
语法
typedef struct _TOUCHINPUT { LONG x; LONG y; HANDLE hSource; DWORD dwID; DWORD dwFlags; DWORD dwMask; DWORD dwTime; ULONG_PTR dwExtraInfo; DWORD cxContact; DWORD cyContact; } TOUCHINPUT, *PTOUCHINPUT;
成员
-
x
-
触控输入的 x 坐标(水平点)。此成员用物理屏幕坐标的像素的百分之一表示。
y
-
触控输入的 y 坐标(垂直点)。此成员用物理屏幕坐标的像素的百分之一表示。
hSource
-
源输入设备的设备句柄。触控输入提供程序在运行时为每个设备指定一个唯一的提供程序。
dwID
-
一个用于区别某个特定触控输入的触控点标识符。此值在触控点序列中从触控点下降到重新上升的整个过程中保持一致。稍后可对后续触控点重用一个 ID。
dwFlags
-
一组位标志,用于指定触控点按住、释放和移动的各个方面。此成员中的位可以是“备注”部分中的值的任何合理组合。
dwMask
-
一组位标志,用于指定结构中包含有效值的可选字段。可选字段中的有效信息的可用性是特定于设备的。应用程序应仅在 dwMask 中设置相应位时使用可选字段值。此字段可以包含“备注”部分中提到的 dwMask 标记的组合。
dwTime
-
事件的时间戳(以毫秒为单位)。使用方应用程序应通知系统不对此字段进行验证;如果未设置 TOUCHINPUTMASKF_TIMEFROMSYSTEM 标志,则此字段中的值的准确性和排序完全依赖于触控输入提供程序。
dwExtraInfo
-
与触控事件关联的其他值。
cxContact
-
触控区域的宽度用物理屏幕坐标的像素的百分之一表示。只有在 dwMask 成员设置了 TOUCHEVENTFMASK_CONTACTAREA 标记的情况下,此值才会有效。
cyContact
-
触控区域的高度用物理屏幕坐标的像素的百分之一表示。只有在 dwMask 成员设置了 TOUCHEVENTFMASK_CONTACTAREA 标记的情况下,此值才会有效。
评论
下表列出了 dwFlags 成员的标志。
标志 | 值 | 说明 |
---|---|---|
TOUCHEVENTF_MOVE | 0x0001 | 已发生移动。不能与 TOUCHEVENTF_DOWN 结合使用。 |
TOUCHEVENTF_DOWN | 0x0002 | 通过新的触控点创建了相应的触控点。不能与 TOUCHEVENTF_MOVE 或 TOUCHEVENTF_UP 结合使用。 |
TOUCHEVENTF_UP | 0x0004 | 已删除触某个触控点。 |
TOUCHEVENTF_INRANGE | 0x0008 | 触控点在范围内。此标志用于在兼容硬盘上启用触控悬停支持。不需要悬停支持的应用程序可忽略此标志。 |
TOUCHEVENTF_PRIMARY | 0x0010 | 指示此 TOUCHINPUT 结构对应于主触控点。有关主触控点的更多信息,请参见以下文本。 |
TOUCHEVENTF_NOCOALESCE | 0x0020 | 在使用 GetTouchInputInfo 接收时,未合并此输入。 |
TOUCHEVENTF_PALM | 0x0080 | 触控事件来自用户的手掌。 |
注意 如果计算机上的目标硬件不支持悬停,则在设置 TOUCHEVENTF_UP 标志时,将清除 TOUCHEVENTF_INRANGE 标志。如果计算机上的目标硬件支持悬停,则将单独设置 TOUCHEVENTF_UP 和 TOUCHEVENTF_INRANGE 标志。
下表列出了 dwMask 成员的标志。
标志 | 值 | 说明 |
---|---|---|
TOUCHINPUTMASKF_CONTACTAREA | 0x0004 | cxContact 和 cyContact 都有效。有关主触控点的更多信息,请参见以下文本。 |
TOUCHINPUTMASKF_EXTRAINFO | 0x0002 | dwExtraInfo 有效。 |
TOUCHINPUTMASKF_TIMEFROMSYSTEM | 0x0001 | 已在 TOUCHINPUT 结构中设置系统时间。 |
若某个触控点是从之前的无触控点状态创建的第一个触控点,则将其指定为主触控点。继续为主触控点的所有后续事件设置 TOUCHEVENTF_PRIMARY 标志,直到释放主触控点。请注意,主触控点上的 TOUCHEVENTF_UP 事件无需指定 Windows Touch 操作的结尾;当前的 Windows Touch 操作从创建主触控点开始执行,直到释放最后的触控点。
请注意,单独的触摸点或同步触控点集中要检测的第一个触摸点将指定为主触控点。系统鼠标位置将紧跟主触控点,并且(除生成触控消息之外)还将生成 WM_LBUTTONDOWN、WM_MOUSEMOVE 和 WM_LBUTTONUP 消息以响应主触控点上的操作。主触控点还可使用按住笔势生成 WM_RBUTTONDOWN 和 WM_RBUTTONUP 消息。
请注意,触控点标识符可能是动态的,并仅在某个给定触控点持续存在期间与其关联。如果中断接触,然后再恢复接触(例如,如果将手指从表面移开,然后再次按下),则同一触控点(同一手指、笔或其他此类设备)可能会收到不同的触控点标识符。
定义以下类型以表示指向 TOUCHINPUT 结构的常量指针。
typedef TOUCHINPUT const * PCTOUCHINPUT;
示例
注意 在以下示例中,不对 pInputs 数组进行排序。使用 dwID 值跟踪特定的触控点。
UINT cInputs = LOWORD(wParam); PTOUCHINPUT pInputs = new TOUCHINPUT[cInputs]; if (NULL != pInputs) { if (GetTouchInputInfo((HTOUCHINPUT)lParam, cInputs, pInputs, sizeof(TOUCHINPUT))) { // process pInputs if (!CloseTouchInputHandle((HTOUCHINPUT)lParam)) { // error handling } } else { // GetLastError() and error handling } } else { // error handling, presumably out of memory } return DefWindowProc(hWnd, message, wParam, lParam);
以下示例演示如何从 hSource 成员获取设备信息。该示例使用 GetRawInputDevice 检索有关设备的信息。
for (UINT i = 0; i < cInputs; i++){ TOUCHINPUT ti = pInputs[i]; RID_DEVICE_INFO info; ZeroMemory(&info, sizeof(RID_DEVICE_INFO)); info.cbSize = sizeof(RID_DEVICE_INFO); UINT size = 0; if (GetRawInputDeviceInfo(ti.hSource, RIDI_DEVICEINFO, &info, &size)){ }else{ DWORD err = GetLastError(); } }