Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Trap cursor in Window

I wrote my own cameraclass in C++ using DX11. At the moment I use WM_MOUSEMOVE events to look around in the scene. To prevent the cursur to get out of the window, I call the function SetCursorPos to center the mouse whenever a WM_MOUSEMOVE event occurs. But if I move my mouse very fast, the cursor gets out of the window. A solution to that was using the function ClipCursor, but this leads to falter the rotation of the camera when the cursor hits the border of the rect. So ClipCursor solved the original problem, but ended in another.

Do you guys have any solution to that?

like image 456
user1655806 Avatar asked Feb 26 '26 05:02

user1655806


1 Answers

For a Windows desktop app, just use ClipCursor giving the rectangle of your window:

    RECT rect;
    GetClientRect(mWindow, &rect);

    POINT ul;
    ul.x = rect.left;
    ul.y = rect.top;

    POINT lr;
    lr.x = rect.right;
    lr.y = rect.bottom;

    MapWindowPoints(mWindow, nullptr, &ul, 1);
    MapWindowPoints(mWindow, nullptr, &lr, 1);

    rect.left = ul.x;
    rect.top = ul.y;

    rect.right = lr.x;
    rect.bottom = lr.y;

    ClipCursor(&rect);

Be sure to have a way to escape this mode so that users can choose to interact with other windows if desired. Typically you call ClipCursor(nullptr); when you go to a 'pause' menu to get out of 'mouse-look' behavior like this.

You can use "raw" input in desktop apps as well, see Taking Advantage of High-Definition Mouse Movement. Keep in mind that raw input works pretty well for relative-movement 'mouse-look' behavior, but (a) it won't work over remote desktop, and (b) you won't get 'pointer-ballistics' which is a non-linear movement rate that makes a mouse more agile so you should generally stick with traditional WM_MOUSE messages when dealing with absolute-movement.

For Universal Windows Platform, you can't use "raw" input as there's no equivalent to WM_INPUT, but you do get high-precision data out of the MouseDevice.MouseMoved event via the MouseDelta property. You don't need to use ClipCursor for relative movement in UWP, just turning off the cursor by setting the CoreWindow.PointerCursor property to nullptr will prevent the system mouse position from being tracked. Again, you should restore the system cursor when you are in a 'pause' menu. See Developing mouse controls (DirectX and C++).

See DirectX Tool Kit Mouse helper class and more importantly the implementation file. For relative mode, it makes use of both ClipCursor and WM_INPUT for the Windows desktop Win32 implementation.

like image 90
Chuck Walbourn Avatar answered Feb 28 '26 19:02

Chuck Walbourn