WM_GESTURE メッセージ受信時、GESTUREINFO 構造体の ullArguments パラメータ―が不正となる

こんにちは、Platform SDK (Windows SDK) サポートチームです。

今回は、WM_GESTURE メッセージ受信時、GESTUREINFO 構造体の ullArguments パラメータ―が不正となる問題についてお知らせします。

 

前提

Windows 7 以降の OS では、マルチタッチ ジェスチャを実行した場合、WM_GESTURE メッセージが発生します。

この際、lParam を GetGestureInfo 関数に渡すことにより、GESTUREINFO 構造体から、ジェスチャに関する情報を取得することが可能です。

ジェスチャそれぞれには、ジェスチャ ID が割り当てられており、GESTUREINFO 構造体のメンバーである ullArguments パラメーターでは、以下の情報が取得できます。

sheet1.png

現象

ジェスチャ ID が、GID_ZOOM、GID_PAN、GID_TWOFINGERTAP、または GID_PRESSANDTAP の場合、上記 ullArguments パラメーターが、不正な値になることがあります。

たとえば、GID_ZOOM の場合、ullArguments パラメーターは 2 点間の距離を示すため、通常、100 や 200 等となりますが、現象発生時には 19xx や -18xx 等の極端に大きな数値やマイナスの値が返されてしまいます。

発生条件は、以下の二点であり、これらの条件をすべて満たした場合、100% 発生します。

  • マルチ モニタ環境であること
  • プライマリ モニタがタッチ スクリーンではないこと

 

原因

本現象は、Windows 7 以降の OS における不具合です。

現象発生時には、2 点間の位置を示すベクトルに加え、ジェスチャが発生したモニタの原点座標が誤って加算されてしまうことに起因します。

ご不便をおかけし恐れ入りますが、本動作を変更する OS の設定や修正プログラムは、現時点ではありません。

 

対処方法

アプリケーションにおける対処方法としては、加算されたモニタの原点座標をマイナスすることにより対処可能です。

たとえば、GID_PRESSANDTAP の場合、ullArguments パラメーターは、2 点間の相対位置を示しますが、以下のサンプル コードにより、正常な値を取得できます。

----- サンプル コード -----

GESTUREINFO gi;

ZeroMemory(&gi, sizeof(GESTUREINFO));

gi.cbSize = sizeof(gi);

BOOL bResult = GetGestureInfo((HGESTUREINFO)lParam, &gi);

 

if (bResult) {

        /*----- 対処方法 ここから -----*/

        POINT ptMonitor;

        POINTSTOPOINT(ptMonitor, gi.ptsLocation);  // ジェスチャに関連付けられた座標

        MONITORINFO mi;

        mi.cbSize = sizeof(mi);

        GetMonitorInfo(MonitorFromPoint(ptMonitor, MONITOR_DEFAULTTONEAREST), &mi);  // ジェスチャが発生したモニタの情報を取得

        /*----- 対処方法 ここまで -----*/

 

        switch (gi.dwID) {

        case GID_ZOOM:

        case GID_PAN:

        case GID_TWOFINGERTAP:

        {

                // 2 点間の距離を取得

                DWORD dwDistance = LODWORD(gi.ullArguments);

                /*----- 対処方法 ここから -----*/

                // モニタの原点座標を引く

                dwDistance -= mi.rcMonitor.left;

                /*----- 対処方法 ここまで -----*/

               

                break;

        }

        case GID_PRESSANDTAP:

        {

                // 2 点間の相対位置を取得

                DWORD ptsDelta = LODWORD(gi.ullArguments);

                POINT ptDelta;

                POINTSTOPOINT(ptDelta, ptsDelta);    // ptDelta.x, ptDelta.y が相対位置を示す

 

                /*----- 対処方法 ここから -----*/

                // モニタの原点座標を引く

                ptDelta.x -= mi.rcMonitor.left;

                ptDelta.y -= mi.rcMonitor.top;

                /*----- 対処方法 ここまで -----*/

               

                break;

        }

        default:

                break;

        }

        CloseGestureInfoHandle((HGESTUREINFO)lParam);

}

----- サンプル コード -----

 

対象製品

Windows 7 以降の OS

 

参考情報

ご参考までに、今回ご案内した情報に関するドキュメントを以下にご紹介します。

WM_GESTURE メッセージ
<https://msdn.microsoft.com/ja-jp/library/windows/desktop/dd353242.aspx>

GetGestureInfo 関数
<https://msdn.microsoft.com/ja-jp/library/windows/desktop/dd353235.aspx>

GESTUREINFO 構造体
<https://msdn.microsoft.com/ja-jp/library/windows/desktop/dd353232.aspx>