You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在C++应用中通过WinAPI设置「精确定位选择」光标?

在C++中通过WinAPI设置精确定位十字光标

嘿,这个需求其实挺常见的,Windows API已经帮我们准备好了现成的解决方案——甚至系统自带了标准的十字交叉光标,不用自己从头画。我分两种常用场景给你讲清楚:


方法一:直接用系统自带的十字光标(最省心)

Windows预定义了十字光标的资源ID是IDC_CROSS,我们可以直接通过LoadCursor函数加载,然后要么设置成窗口的默认光标,要么在特定场景下临时切换。

1. 设置窗口默认光标(窗口一打开就生效)

在注册窗口类的时候,把WNDCLASSEX的hCursor成员指定为加载好的十字光标就行,代码示例如下:

#include <windows.h>

LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);

int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PWSTR pCmdLine, int nCmdShow)
{
    const wchar_t CLASS_NAME[] = L"CrossCursorDemoClass";
    
    WNDCLASSEX wc = {0};
    wc.cbSize        = sizeof(WNDCLASSEX);
    wc.lpfnWndProc   = WindowProc;
    wc.hInstance     = hInstance;
    wc.lpszClassName = CLASS_NAME;
    // 加载系统自带的十字光标,直接赋值给窗口类的hCursor
    wc.hCursor       = LoadCursor(NULL, IDC_CROSS);
    
    RegisterClassEx(&wc);

    HWND hwnd = CreateWindowEx(
        0,
        CLASS_NAME,
        L"精确定位光标示例",
        WS_OVERLAPPEDWINDOW,
        CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
        NULL, NULL, hInstance, NULL
    );

    if (!hwnd) return 0;

    ShowWindow(hwnd, nCmdShow);

    MSG msg = {0};
    while (GetMessage(&msg, NULL, 0, 0))
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }

    return (int)msg.wParam;
}

LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    switch (uMsg)
    {
        case WM_DESTROY:
            PostQuitMessage(0);
            return 0;
        default:
            return DefWindowProc(hwnd, uMsg, wParam, lParam);
    }
}

2. 临时切换光标(比如鼠标 hover 特定区域时)

如果只需要在特定场景下显示十字光标(比如鼠标放在绘图区、按钮上时),可以在窗口过程里处理WM_SETCURSOR消息:

LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    switch (uMsg)
    {
        case WM_SETCURSOR:
            // 这里判断鼠标是否在窗口客户区,你可以改成自己的条件(比如某个控件ID)
            if (LOWORD(lParam) == HTCLIENT)
            {
                // 设置十字光标
                SetCursor(LoadCursor(NULL, IDC_CROSS));
                // 返回TRUE告诉系统我们已经处理了光标,不用走默认逻辑
                return TRUE;
            }
            break;
        case WM_DESTROY:
            PostQuitMessage(0);
            return 0;
        default:
            return DefWindowProc(hwnd, uMsg, wParam, lParam);
    }
    return DefWindowProc(hwnd, uMsg, wParam, lParam);
}

方法二:用自定义十字光标(如果系统样式不合心意)

要是系统自带的十字光标样式不符合你的UI设计,你可以自己制作.cur格式的光标文件,然后用LoadImage加载:

// 加载自定义光标文件(假设cross.cur在程序运行目录下)
HCURSOR hCustomCross = (HCURSOR)LoadImage(
    GetModuleHandle(NULL),
    L"cross.cur",
    IMAGE_CURSOR,
    0, 0,
    LR_LOADFROMFILE | LR_DEFAULTSIZE
);

// 加载成功后就可以用SetCursor设置,或者赋值给窗口类的hCursor
if (hCustomCross)
{
    SetCursor(hCustomCross);
}

一些注意点

  • 记得包含<windows.h>头文件,链接时需要user32.lib——主流IDE(比如VS)默认会自动链接这个库,不用额外配置。
  • LoadCursor(NULL, IDC_CROSS)里的NULL表示加载系统预定义资源,要是加载自己的资源文件,要传当前实例的hInstance。
  • 处理WM_SETCURSOR时一定要返回TRUE,不然系统会覆盖你的光标设置,用回默认样式。

内容的提问来源于stack exchange,提问作者DrStrange

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 10:17:50