2

Logitech G500 ゲーミング マウスを 5700 のフル DPI で実行しています。

マウスの水平方向の動きを物理単位で正確に測定するプログラムを C++ で作成しようとしています。センチメートルまたはインチ。

WM_INPUTメッセージを介してWindows APIとWindowsの生入力を使用して、マウスから生の動きの変化を取得しています。

次に、WM_INPUT を介して報告される移動の 1 単位が 1/5700 インチであると想定し、マウスの正味の動きを追跡しているので、単純な計算を実行して正味の物理的な動きを得ることができると考えました。

距離 (インチ) = total_movement_from_wminput / dpi; // この場合、dpi = 5700

残念ながら、計算は正確ではないようです。マウス パッドだけで物理的な測定を行うと、約 6 インチのマウスの移動で、計算により約 5.5 インチの値が得られることがわかります (1/2 インチの試合の損失)。

どこが間違っていますか?コントロール パネルでマウスを 5700DPI に設定しましたが、実際の DPI はそれよりも低い可能性がありますか? 物理的な動きの 1/dpi インチである WM_INPUT による 1 単位の変更についての私の仮定は間違っていますか?

これを正確にする方法について何か考えがある人はいますか? ありがとう!

4

1 に答える 1

2

マーク、

WM_INPUTWindows イベントが処理するよりも速くマウスを動かした場合に問題が発生する可能性があります。たとえば、マウスが 1 フレームで 2 ピクセル移動したとします。処理される1 つのイベントに対して 2ピクセルWM_INPUT移動するため、1/5700 インチの損失が発生します (この場合) 。

これを修正するには、WM_INPUT メッセージがプログラムに送信されるたびにマウスが移動するピクセル数を確認する必要があります。あなたがしなければならないことは、RAWINPUTDEVICE 変数を作成し、マウスに関する情報を持つように構造体を設定することです。

次のコードは、RAWINPUTDEVICEで使用できるように を登録しWM_INPUTます。

RAWINPUTDEVICE Rid[1];
Rid[0].usUsagePage = HID_USAGE_PAGE_GENERIC;
Rid[0].usUsage = HID_USAGE_GENERIC_MOUSE; 
Rid[0].dwFlags = RIDEV_INPUTSINK;   
Rid[0].hwndTarget = hWnd;
RegisterRawInputDevices(Rid, 1, sizeof(Rid[0]);

次のコードは、Rid変数 two を実際に使用して、前回WM_INPUT開始されてからマウスが移動したピクセル数を決定します。

case WM_INPUT: 
{
    UINT dwSize = 40;
    static BYTE lpb[40];

    GetRawInputData((HRAWINPUT)lParam, RID_INPUT, 
                    lpb, &dwSize, sizeof(RAWINPUTHEADER));

    RAWINPUT* raw = (RAWINPUT*)lpb;

    if (raw->header.dwType == RIM_TYPEMOUSE) 
    {
        int xPosRelative = raw->data.mouse.lLastX; // Could be 1, or could be more than 1
        int yPosRelative = raw->data.mouse.lLastY; // Could be 1, or could be more than 1!
    } 
    break;
}

このコードは、まさにこのトピックに関する msdn で提示されたコードと同じであることに注意してください (以下のリンク)。

マウスの x 位置と y 位置 (ピクセル単位) を持つある種のグローバル変数を使用できるようになりました。次に、これらの変数を DPI で除算するだけで、グローバル変数を 0 に設定するたびにオフセットされるインチの量が得られます。


より簡単な方法は、WM_MOUSEMOVE代わりにイベントを処理することです。これにより、マウスの正確な位置 (もちろんピクセル単位) を簡単に取得できます。これを使用して、開始位置のピクセル値からこれを減算できます。

例:

DPI = 5700。

初期位置 = (100px, 300px)。

3 秒後の位置 = (500px, 400px)。

この 3 秒間に移動したインチ数 = ((500px - 100px)/5700 インチ、(400px - 300px)/5700 インチ)

一般的な規則: S 秒後に移動したインチ数 = (inital_pixels_x - final_pixels_x)/DPI インチ

水平方向、(initial_pixels_y - final_pixels_y)/DPI インチ垂直方向

ここで、final_pixels_x は s 秒後のマウスの x 位置であり、final_pixels y は s 秒後の y 位置です。


何を間違えたかを要約すると、各WM_INPUTイベントはマウスが 1 ピクセル移動したことを意味すると誤って想定していました。

何らかの理由で質問を誤解していて、すでに正しい量のピクセルが移動されていることがわかっている場合は、コメントを残してください。回答を修正するために最善を尽くします. ただし、マウス専用であり、一番下のリンクで読むことができる「ポインターアクセラレーション」を適用するため、WM_MOUSEMOVE代わりに使用することをお勧めします.WM_INPUT

tcs08 さん、ご質問ありがとうございます。

WM_INPUT を使用したマウス入力の msdn コードと説明

WM_MOUSEMOVE を使用したマウス入力の msdn コードと説明

于 2013-07-03T23:45:36.010 に答える