What’s the opposite of Clip­Cursor that lets me exclude the cursor from a region?

The Old New Thing (Raymond Chen) News

Summary

A Windows developer asks how to exclude the cursor from a region, the opposite of ClipCursor. The article explains a technique to avoid flicker by not moving the cursor but instead snapping the object's position to the nearest legal location.

<p>A customer wanted to prevent the user from dragging an object into a specific region of their window. Their current implementation detects that the mouse is an in illegal location and uses <code>Set­Cursor­Pos</code> to move it to a nearby legal location. However, this creates flicker because the cursor actually does enter the illegal region and then jumps out.</p> <p>Let&#8217;s illustrate this with <a title="The scratch program" href="https://devblogs.microsoft.com/oldnewthing/20030723-00/?p=43073"> our scratch program</a>.</p> <pre>POINT g_pt; const RECT g_rcExclude = { 100, 100, 200, 200 }; RECT ItemRect(POINT pt) { return RECT{ pt.x - 10, pt.y - 10, pt.x + 10, pt.y + 10 }; } </pre> <p>The <code>g_pt</code> variable holds the location of our object, and the <code>g_rcExclude</code> is the rectangle in which the object is forbidden. The <code>ItemRect</code> function produces a bounding rectangle for our object so we can draw something there.</p> <pre>void PaintContent(HWND hwnd, PAINTSTRUCT* pps) { FillRect(pps-&gt;hdc, &amp;g_rcExclude, (HBRUSH)(COLOR_WINDOWTEXT + 1)); RECT rcItem = ItemRect(g_pt); FillRect(pps-&gt;hdc, &amp;rcItem, (HBRUSH)(COLOR_APPWORKSPACE + 1)); } </pre> <p>Painting our content is a straightforward matter of drawing the forbidden rectangle in the text color and drawing the object in the app workspace color.</p> <pre>void OnMouseMove(HWND hwnd, int x, int y, UINT keyFlags) { POINT ptNew = { x, y }; if (PtInRect(&amp;g_rcExclude, ptNew)) { // Clamp to nearest legal position int leftMargin = ptNew.x - g_rcExclude.left; int topMargin = ptNew.y - g_rcExclude.top; int rightMargin = g_rcExclude.right - ptNew.x; int bottomMargin = g_rcExclude.bottom - ptNew.y; int dx, dy; int x, y; if (leftMargin &lt; rightMargin) { x = g_rcExclude.left; dx = leftMargin; } else { x = g_rcExclude.right; dx = rightMargin; } if (topMargin &lt; bottomMargin) { y = g_rcExclude.top; dy = topMargin; } else { y = g_rcExclude.bottom; dy = bottomMargin; } if (dx &lt; dy) { ptNew.x = x; } else { ptNew.y = y; } POINT ptScreen = ptNew; ClientToScreen(hwnd, &amp;ptScreen); SetCursorPos(ptScreen.x, ptScreen.y); } if (g_pt.x != ptNew.x || g_pt.y != ptNew.y) { RECT rcItem = ItemRect(g_pt); InvalidateRect(hwnd, &amp;rcItem, TRUE); g_pt = ptNew; rcItem = ItemRect(g_pt); InvalidateRect(hwnd, &amp;rcItem, TRUE); } } // Add to WndProc HANDLE_MSG(hwnd, WM_MOUSEMOVE, OnMouseMove); </pre> <p>When the mouse moves, we take the mouse position and see if it is in the forbidden rectangle. If so, we update the coordinates to the nearest legal position and move the mouse there with <code>Set­Cursor­Pos</code>.</p> <p>Whether or not we had to update the coordinates, if the result produces a new location, then invalidate the object&#8217;s old location (so it will be erased at the next paint cycle), update the object position, and then invalidate the object&#8217;s new position (so it will be drawn at the next paint cycle).</p> <p>When you run this program, you can try to move the mouse into the forbidden rectangle, but the program will shove the mouse back out. However, it flickers a lot bcause the mouse briefly enters the forbidden rectangle before it is expelled from it.</p> <p>The customer saw that there is a <code>Clip­Cursor</code> function to constrain the mouse to remain <i>inside</i> a rectangle, but is there an inverse version that forces the mouse to remain <i>outside</i> a rectangle?</p> <p>There is no such function, but that&#8217;s okay.</p> <p>What you can do when the mouse is in an illegal position is just pretend that it&#8217;s in a legal position. Let the user move the mouse into a illegal position, but show the feedback at the nearest legal position, and if they drop the object, let it drop at the nearest legal position.</p> <p>In the above program, that means we remove the call to <code>Set­Cursor­Pos</code>.</p> <pre>void OnMouseMove(HWND hwnd, int x, int y, UINT keyFlags) { POINT ptNew = { x, y }; if (PtInRect(&amp;g_rcExclude, ptNew)) { // Clamp to nearest legal position int leftMargin = ptNew.x - g_rcExclude.left; int topMargin = ptNew.y - g_rcExclude.top; int rightMargin = g_rcExclude.right - ptNew.x; int bottomMargin = g_rcExclude.bottom - ptNew.y; int dx, dy; int x, y; if (leftMargin &lt; rightMargin) { x = g_rcExclude.left; dx = leftMargin; } else { x = g_rcExclude.right; dx = rightMargin; } if (topMargin &lt; bottomMargin) { y = g_rcExclude.top; dy = topMargin; } else { y = g_rcExclude.bottom; dy = bottomMargin; } if (dx &lt; dy) { ptNew.x = x; } else { ptNew.y = y; } <span style="border: dashed 1px currentcolor; border-bottom: none;">// <span style="text-decoration: line-through;">POINT ptScreen = ptNew;</span> </span> <span style="border: 1px currentcolor; border-style: none dashed;">// <span style="text-decoration: line-through;">ClientToScreen(hwnd, &amp;ptScreen);</span> </span> <span style="border: dashed 1px currentcolor; border-top: none;">// <span style="text-decoration: line-through;">SetCursorPos(ptScreen.x, ptScreen.y);</span></span> } if (g_pt.x != ptNew.x || g_pt.y != ptNew.y) { RECT rcItem = ItemRect(g_pt); InvalidateRect(hwnd, &amp;rcItem, TRUE); g_pt = ptNew; rcItem = ItemRect(g_pt); InvalidateRect(hwnd, &amp;rcItem, TRUE); } } </pre> <p>This time, we don&#8217;t try to punish you for moving the mouse into the forbidden rectangle. But the object won&#8217;t follow the mouse into a forbidden region.</p> <p>The post <a href="https://devblogs.microsoft.com/oldnewthing/20260610-00/?p=112412">What&#8217;s the opposite of &lt;CODE&gt;Clip&shy;Cursor&lt;/CODE&gt; that lets me &lt;I&gt;exclude&lt;/I&gt; the cursor from a region?</a> appeared first on <a href="https://devblogs.microsoft.com/oldnewthing">The Old New Thing</a>.</p>
Original Article

Similar Articles

Don't hijack my mouse pointer

Hacker News Top

The author criticizes the trend of replacing standard web cursors with custom animated effects, arguing that these decorations severely harm usability. They urge developers to prioritize functional UX over flashy visuals enabled by modern AI-assisted coding tools.

Why the Cursor Acquisition Should Concern Every Software Developer

Reddit r/AI_Agents

The article expresses concern about the acquisition of the Cursor coding assistant, highlighting the unique trust required for tools that have access to proprietary source code and the risks when ownership shifts to a large entity with diverse interests.