惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

AWS News Blog
AWS News Blog
T
Tenable Blog
Project Zero
Project Zero
T
The Exploit Database - CXSecurity.com
L
LINUX DO - 热门话题
T
Threat Research - Cisco Blogs
T
Threatpost
Security Latest
Security Latest
C
Cisco Blogs
L
Lohrmann on Cybersecurity
S
Security @ Cisco Blogs
Google Online Security Blog
Google Online Security Blog
NISL@THU
NISL@THU
AI
AI
V
Vulnerabilities – Threatpost
Google DeepMind News
Google DeepMind News
C
Cyber Attacks, Cyber Crime and Cyber Security
C
CXSECURITY Database RSS Feed - CXSecurity.com
The Last Watchdog
The Last Watchdog
G
GRAHAM CLULEY
Cloudbric
Cloudbric
H
Hackread – Cybersecurity News, Data Breaches, AI and More
H
Hacker News: Front Page
U
Unit 42
A
Arctic Wolf
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
MyScale Blog
MyScale Blog
O
OpenAI News
Scott Helme
Scott Helme
V2EX - 技术
V2EX - 技术
P
Proofpoint News Feed
博客园 - 叶小钗
Hugging Face - Blog
Hugging Face - Blog
云风的 BLOG
云风的 BLOG
V
Visual Studio Blog
Application and Cybersecurity Blog
Application and Cybersecurity Blog
Cyberwarzone
Cyberwarzone
博客园 - 【当耐特】
H
Heimdal Security Blog
S
Schneier on Security
阮一峰的网络日志
阮一峰的网络日志
Help Net Security
Help Net Security
D
DataBreaches.Net
Y
Y Combinator Blog
Hacker News - Newest:
Hacker News - Newest: "LLM"
TaoSecurity Blog
TaoSecurity Blog
K
Kaspersky official blog
N
News and Events Feed by Topic
WordPress大学
WordPress大学
P
Palo Alto Networks Blog

The Old New Thing

Making an agile version of a Windows Runtime delegate in C++/WinRT, part 5 - The Old New Thing Making an agile version of a Windows Runtime delegate in C++/WinRT, part 4 - The Old New Thing Making an agile version of a Windows Runtime delegate in C++/WinRT, part 3 - The Old New Thing Making an agile version of a Windows Runtime delegate in C++/WinRT, part 2 - The Old New Thing Making an agile version of a Windows Runtime delegate in C++/WinRT, part 1 - The Old New Thing Why has the display control panel pointer truncation bug gone unfixed for so long? - The Old New Thing Speculating on how the buggy control panel extension truncated a value that it had right in front of it - The Old New Thing The case of the invalid function pointer when shutting down the display control panel - The Old New Thing Microspeak: Double-click and drill down - The Old New Thing Why don't we just make the entire stack out of guard pages? - The Old New Thing The case of the mysterious changes to integers when there shouldn't have been any code generation effect - The Old New Thing I've decoded a #pragma detect_mismatch error and fixed the mismatch, but I still get the error - The Old New Thing The other kind of control flow guard check: The combined validate and call - The Old New Thing How did Windows 95 decide that a setup program ran? - The Old New Thing I opened a file with FILE_FLAG_DELETE_ON_CLOSE, but now I changed my mind - The Old New Thing How did we conclude that CcNamespace.dll was the ringleader of a group of DLLs that unloaded prematurely? - The Old New Thing The case of the thread executing from an unloaded third-party DLL - The Old New Thing It rather involved being on the other side of this airtight hatchway: Changing administrative settings - The Old New Thing 2026 mid-year link clearance - The Old New Thing A compatibility note on the abuse of Windows window class extra bytes - The Old New Thing The evolution of window and class extra bytes in Windows - The Old New Thing The case of the DLL that was not present in memory despite not being formally unloaded, part 2 - The Old New Thing Raymond's hot take on Hainanese chicken - The Old New Thing The case of the DLL that was not present in memory despite not being formally unloaded, part 1 - The Old New Thing Cancellation of Windows Runtime activities is asynchronous - The Old New Thing Microspeak elaborated: Isn't escrow just a release candidate by another name? - The Old New Thing In memory of the man who put red and green squiggles under words - The Old New Thing What does it mean when the bottom bit of my HMODULE is set? - The Old New Thing Why doesn't Get­Last­Input­Info() return info for the user I'm impersonating? - The Old New Thing Windows stack limit checking retrospective, follow-up - The Old New Thing Retrofitting the WM_COPY­DATA message onto Windows 3.1 - The Old New Thing The time the x86 emulator team found code so bad that they fixed it during emulation - The Old New Thing How can I schedule work on a thread pool with low latency? Understanding the rationale behind a rule when trying to circumvent it The Microsoft Company Party where everybody played name tag swap Rotation revisited: Shuffling more than three blocks, and other small notes The back cover of C++: The Programming Language also raises questions not answered by the front cover Rotation revisited: Avoiding having to calculate the gcd when doing cycle decomposition Rotation revisited: Cycle decomposition in clang’s libcxx Rotation revisited: A shocking discovery about gcc’s unidirectional rotation algorithm Rotation revisited: Another unidirectional algorithm The placeholder name for the Windows 8 experience was “modern” Sharing the result of a single Windows Runtime IAsyncOperation among multiple coroutines, part 3 Sharing the result of a single Windows Runtime IAsyncOperation among multiple coroutines, part 2 Sharing the result of a single Windows Runtime IAsyncOperation among multiple coroutines, part 1 If C# and JavaScript lets me await a Windows Runtime asynchronous operation more than once, why not C++/WinRT? A hypothetical redesign of System.Diagnostics.Process to avoid confusion over properties that are valid only when you are the one who called Start Why do you say that a COM STA thread must pump messages if I see sample code creating STA threads and not pumping messages? How do I use Win32 structures from the Windows Runtime? What is the history of the ERROR_ARENA_TRASHED error code? The classic TreeView control lets me sort by name or by lParam, but why not both? Just shows that nobody cares about debugging the parity flag any more The case of the Create­File­Mapping that always reported ERROR_ALREADY_EXISTS
What’s the opposite of Clip­Cursor that lets me exclude the cursor from a region?
Raymond Chen · 2026-06-10 · via The Old New Thing

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 SetCursorPos 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.

Let’s illustrate this with our scratch program.

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 };
}

The g_pt variable holds the location of our object, and the g_rcExclude is the rectangle in which the object is forbidden. The ItemRect function produces a bounding rectangle for our object so we can draw something there.

void
PaintContent(HWND hwnd, PAINTSTRUCT* pps)
{
    FillRect(pps->hdc, &g_rcExclude, (HBRUSH)(COLOR_WINDOWTEXT + 1));
    RECT rcItem = ItemRect(g_pt);
    FillRect(pps->hdc, &rcItem, (HBRUSH)(COLOR_APPWORKSPACE + 1));
}

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.

void OnMouseMove(HWND hwnd, int x, int y, UINT keyFlags)
{
    POINT ptNew = { x, y };

    if (PtInRect(&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 < rightMargin) {
            x = g_rcExclude.left;
            dx = leftMargin;
        } else {
            x = g_rcExclude.right;
            dx = rightMargin;
        }
        if (topMargin < bottomMargin) {
            y = g_rcExclude.top;
            dy = topMargin;
        } else {
            y = g_rcExclude.bottom;
            dy = bottomMargin;
        }
        if (dx < dy) {
            ptNew.x = x;
        } else {
            ptNew.y = y;
        }
        POINT ptScreen = ptNew;
        ClientToScreen(hwnd, &ptScreen);
        SetCursorPos(ptScreen.x, ptScreen.y);
    }

    if (g_pt.x != ptNew.x || g_pt.y != ptNew.y) {
        RECT rcItem = ItemRect(g_pt);
        InvalidateRect(hwnd, &rcItem, TRUE);
        g_pt = ptNew;
        rcItem = ItemRect(g_pt);
        InvalidateRect(hwnd, &rcItem, TRUE);
    }
}

// Add to WndProc

        HANDLE_MSG(hwnd, WM_MOUSEMOVE, OnMouseMove);

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 SetCursorPos.

Whether or not we had to update the coordinates, if the result produces a new location, then invalidate the object’s old location (so it will be erased at the next paint cycle), update the object position, and then invalidate the object’s new position (so it will be drawn at the next paint cycle).

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.

The customer saw that there is a ClipCursor function to constrain the mouse to remain inside a rectangle, but is there an inverse version that forces the mouse to remain outside a rectangle?

There is no such function, but that’s okay.

What you can do when the mouse is in an illegal position is just pretend that it’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.

In the above program, that means we remove the call to SetCursorPos.

void OnMouseMove(HWND hwnd, int x, int y, UINT keyFlags)
{
    POINT ptNew = { x, y };

    if (PtInRect(&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 < rightMargin) {
            x = g_rcExclude.left;
            dx = leftMargin;
        } else {
            x = g_rcExclude.right;
            dx = rightMargin;
        }
        if (topMargin < bottomMargin) {
            y = g_rcExclude.top;
            dy = topMargin;
        } else {
            y = g_rcExclude.bottom;
            dy = bottomMargin;
        }
        if (dx < dy) {
            ptNew.x = x;
        } else {
            ptNew.y = y;
        }
        // POINT ptScreen = ptNew;              
        // ClientToScreen(hwnd, &ptScreen);     
        // SetCursorPos(ptScreen.x, ptScreen.y);
    }

    if (g_pt.x != ptNew.x || g_pt.y != ptNew.y) {
        RECT rcItem = ItemRect(g_pt);
        InvalidateRect(hwnd, &rcItem, TRUE);
        g_pt = ptNew;
        rcItem = ItemRect(g_pt);
        InvalidateRect(hwnd, &rcItem, TRUE);
    }
}

This time, we don’t try to punish you for moving the mouse into the forbidden rectangle. But the object won’t follow the mouse into a forbidden region.

Category

Topics

Author

Raymond Chen

Raymond has been involved in the evolution of Windows for more than 30 years. In 2003, he began a Web site known as The Old New Thing which has grown in popularity far beyond his wildest imagination, a development which still gives him the heebie-jeebies. The Web site spawned a book, coincidentally also titled The Old New Thing (Addison Wesley 2007). He occasionally appears on the Windows Dev Docs Twitter account to tell stories which convey no useful information.