5

指定されたウィンドウにマウスをクリップする非常に単純なプログラムを書いています。目に見えるウィンドウなしでシステム トレイから実行されます。同じウィンドウの複数のインスタンスが存在するため、EnumWindows()すべてのトップレベル ウィンドウを反復処理し、それらの hwnd を と比較しGetForegroundWindow()ます。true の場合、標準ClipCursor()コードを実行します。 ClipCursor()を返します。セット byは に渡されたものとまったく同じであるTRUEと断言しました。ただし、カーソルは画面上のどこにでも自由に移動できます。RECTGetClipCursor()RECTClipCursor()

の値がウィンドウの正確な値であることを確認しRECTました。プログラムをリリースモードでコンパイルし、管理者権限で実行しましたが、まだ何もありません。HWND以下のコードは、のが見つかった後に実行されるものとまったく同じですGetForegroundWindow()

// Get the window client area.
GetClientRect(hwnd, &rc);

// Convert the client area to screen coordinates.
POINT pt = { rc.left, rc.top };
POINT pt2 = { rc.right, rc.bottom };
ClientToScreen(hwnd, &pt);
ClientToScreen(hwnd, &pt2);
SetRect(&rc, pt.x, pt.y, pt2.x, pt2.y);

clipped = true;
ClipCursor(&rc);

RECT rect;
GetClipCursor(&rect);

assert(rect.bottom == rc.bottom);
assert(rect.left == rc.left);
assert(rect.right == rc.right);
assert(rect.top == rc.top);

煩わしくなったので (私はMessageBox()'s を使用していました)、多くのチェックを削除しましたが、このコードは、想定されているときに確実に実行されています。カーソルがクリップされないだけで、その理由がわかりません。

4

2 に答える 2

6

カーソルは共有リソースであるため、それをクリップしようとすると、カーソルのクリップを解除するために呼び出した他のユーザーによって上書きされClipCursorます。また、多くの操作でカーソルのクリップが自動的に解除されます (フォーカスの変更など)。バックグラウンド ウィンドウがカーソル クリップを変更するのは不適切な形式と見なされます。

于 2012-08-20T15:28:31.477 に答える
4

まあ、Cursor リソースの共有された性質にもかかわらず、プロセスが特定の状況でカーソルをクリップしている場合、まだ完全にはわかりません (プロセスがフォアグラウンドでなければならない可能性があります)。アプリケーション? またはそのようなもの...私にはよくわかりません.) その後、OS は自動的にカーソルを完全なクリッピング モード (またはあなたがそれと呼ぶもの) に戻します。

とにかく、修正は、低レベルのマウス フックを実行し、そこから clipcursor を呼び出すことです。概念コードの簡単な証明を次に示します (テスト済みで動作しますが、ウィンドウの作成やシステム トレイのセットアップなどの無関係なものは削除しました)。

// Some variables we'll use
bool clipped = false;   // Do we need to clip the mouse?
RECT rc;                // The clip rect
HHOOK hMouseHook;       // Low level mouse hook

// Low level mouse hook callback function
__declspec(dllexport) LRESULT CALLBACK MouseEvent(int nCode, WPARAM wParam, LPARAM lParam)
{
    // This part should be rewritten to make it not be a CPU-hog
    // But works as a proof of concept
    if ( clipped )
        ClipCursor(&rc);

    return CallNextHookEx(hMouseHook, nCode, wParam, lParam);
}

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
{
    // .... Blah blah blah ....

    // Low level mouse hook
    hMouseHook = SetWindowsHookEx(WH_MOUSE_LL, (HOOKPROC)MouseEvent, hInstance, 0);

    // Only included to show that you set the hook before this,
    // And unhook after this.
    while(GetMessage(&msg, NULL, 0, 0) > 0)
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }

    // Unhook the mouse
    UnhookWindowsHookEx(hMouseHook);

    return msg.wParam;
}
于 2012-08-19T14:26:37.943 に答える