tmytのらくがき

個人の日記レベルです

このクリックはマウス?ペン?タッチ?

昔はマウスしか無かったのに気がつけば入力インターフェースもマウスだとか、スタイラス(ペン)だとか、タッチだとか、ジェスチャだとか、声だとかいろいろ増えちゃいました。 最近は、タブレットPCみたいのがはやってるのでマウス以外にペンとかタッチはメジャーな入力インターフェースになってきた感じがありますね。

ところでWindows的にマウスと、ペンと、タッチってなにが違うんでしょう。C++ SDKプログラミングな普通の環境だとすべてWM_LBUTTONDOWNとしてハンドリングできます。*1でもこれって全部一緒くたにされてちょっと微妙。やっぱり入力デバイスによって使いやすいUIは違います。たとえば、Office2013なんかはタッチの場合は押しやすいサイズにUIが変化します。 こういうことをするにはどうすれば? ちなみにWindows 8以降の環境であれば次の様なコードで判別できます。

switch(uMsg){
case WM_POINTERDOWN:
    {
        POINTER_TYPE type = PT_POINTER;
        auto id = GET_POINTERID_WPARAM(wParam);
        GetPointerType(id, &type);
        switch(type){
        case PT_TOUCH:
            // 入力はタッチ
            break;
        case PT_PEN:
            // 入力はペン
            break;
        default:
            // 入力はマウス
            break;
        }
        break;
    }
}

でもこの方法はWindows 8以降でしか使えません。それより古い環境では次の様にするとそれぞれの入力デバイスを判別できます。

#define MOUSEEVENTF_FROMTOUCH 0xFF515700
 
switch(uMsg){
case WM_LBUTTONDOWN:
    {
        auto extra = GetMessageExtraInfo();
        if((extra & MOUSEEVENTF_FROMTOUCH) == MOUSEEVENTF_FROMTOUCH){
            if(extra & 0x80){
                // 入力はタッチ
            }else{
                // 入力はペン
            }
        }else{
            // 入力はマウス
        }
        break;
    }
}

これはMSDNのこのあたり http://msdn.microsoft.com/en-us/library/windows/desktop/ms703320(v=vs.85).aspx に書いてあります。 GetMessageExtraInfo関数からメッセージに関連づけられた拡張情報が取得できます。この32bitに対してマスクした値がある値であれば、タッチやペンでの入力として判別できます。また、下から8bit目が1ならタッチ、0ならペンという意味があります。 これで入力に使われたデバイスは判別できるので、あとはUIをデバイスに最適化するなどいろいろできますね。

*1:最近はWM_POINTERとかWM_TOUCHとかも使えます。