
1. 从一次鼠标坐标调试说起C 获取鼠标位置与移动鼠标在 Windows 桌面开发里属于那种「看起来一行 API 就能搞定、真写起来却总有几个坑」的典型需求。核心检索词其实就三个GetCursorPos负责读坐标SetCursorPos负责写坐标POINT结构体负责装数据。它能做的事情很具体——读取当前光标在屏幕上的像素位置、把光标移动到指定坐标、做坐标偏移、做自动化点击前的定位。适合谁做 MFC/Qt 桌面工具的人、写自动化脚本的人、做辅助输入类小工具的人以及正在用 Cline 这类 AI 编码助手、想让模型帮你补全 Win32 代码的人。我这次的目标很明确写一段能直接编译运行的 C 代码完成「读取当前位置 → 偏移移动 → 再读一次确认」的端到端验证同时把 AI 辅助工具以 Cline 为例的settings.json骨架配好让模型在补全GetCursorPos/SetCursorPos相关代码时有稳定的 API 通道。这里会用到 TaoToken 的统一 Key 接入方式把模型调用收敛到一个入口省得在多个工具里反复填不同厂商的 Key。需要先说明一点鼠标坐标读写本身是纯本地 Win32 调用不依赖任何网络服务TaoToken 在这里的角色是给「帮你写这段代码的 AI 工具」提供统一的模型接入通道。两者是配合关系不是替代关系。下面按「先配通道、再写代码、最后验证排障」的顺序走一遍。2. TaoToken 统一 Key 的前置准备在动手写settings.json之前先把账号侧的东西准备好。TaoToken 的定位是统一 Key/API 通道你可以在一个后台里管理模型访问凭证然后把它填到 Cline、Continue 这类支持自定义 API 的编码工具里。官网入口是 https://taotoken.net/?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content API 基址是 https://taotoken.net/api 这个地址不加 UTM 参数配置里直接用它。操作路径大致是这样先注册登录进控制台创建 API Key然后按工具要求把 Base URL 和 Key 填进去。控制台地址是 https://taotoken.net/console?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content API Keys 管理页是 https://taotoken.net/api-keys?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 。如果你只是想先在网页里试试模型对话、确认通道通不通可以用模型对话页 https://taotoken.net/chat?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 。注意API Key 属于敏感凭证不要写进会提交到公开仓库的文件里。本地调试可以用环境变量或者把settings.json加进.gitignore。如果你打算长期用 AI 做编码和 Agent 任务可以了解下 Coding Planhttps://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 。接入文档在 https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 配置字段以文档为准下面给的骨架是通用结构。3. 可复制的 settings.json 配置骨架Cline 的配置一般放在用户目录下的扩展设置里不同版本路径略有差异但核心字段是一致的一个 API 提供方标识、一个 Base URL、一个 Key、一个模型名。下面这份骨架你可以直接抄把apiKey换成你自己的即可。{ apiProvider: openai, openAiBaseUrl: https://taotoken.net/api, openAiApiKey: sk-你的TaoToken密钥, openAiModelId: claude-sonnet-4-20250514, openAiLegacyFormat: false, openAiHeaders: {}, autoApprovalEnabled: false, alwaysAllowReadOnly: true, alwaysAllowWrite: false }几个字段说明一下。apiProvider选openai是因为 TaoToken 的 API 走 OpenAI 兼容格式这样 Cline 能直接识别。openAiBaseUrl填https://taotoken.net/api注意结尾不要多加/v1具体以接入文档为准。openAiModelId按你实际开通的模型填上面只是个示例。autoApprovalEnabled建议先关掉让模型改代码前你确认一下尤其是涉及SetCursorPos这种会真实移动鼠标的调用。如果你用的是 Claude Code 这类工具接入方式略有不同可以参考 https://taotoken.net/claudecode-anthropic?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 里的说明。核心思路一样把 Base URL 指向统一通道Key 用同一把。配好之后让模型帮你写下面这段鼠标坐标代码它就能基于稳定的通道给出补全建议。下面进入正题。4. 鼠标坐标读写的完整代码与验证先给一个最小可编译的完整示例用g或 MSVC 都能编。它做三件事读当前坐标、向右下偏移 30 像素、再读一次确认移动生效。#include iostream #include windows.h int main() { POINT p, pNext; // 第一次读取获取当前鼠标位置 if (!GetCursorPos(p)) { std::cerr GetCursorPos failed, error GetLastError() std::endl; return 1; } std::cout before: p.x , p.y std::endl; // 移动鼠标在当前位置基础上偏移 if (!SetCursorPos(p.x 30, p.y 30)) { std::cerr SetCursorPos failed, error GetLastError() std::endl; return 1; } // 第二次读取确认移动结果 if (!GetCursorPos(pNext)) { std::cerr GetCursorPos failed, error GetLastError() std::endl; return 1; } std::cout after: pNext.x , pNext.y std::endl; return 0; }编译命令MSVC 下cl /EHsc mouse_pos.cpp user32.libMinGW/g 下g mouse_pos.cpp -o mouse_pos.exe -luser32运行后你会看到类似输出before: 640,360 after: 670,390两次坐标差正好是 30说明读取和移动都生效了。这里有个细节值得说GetCursorPos返回的是屏幕坐标原点在屏幕左上角单位是物理像素还是逻辑像素取决于进程的 DPI 感知设置。如果你的程序没声明 DPI 感知在高分屏上拿到的可能是缩放后的逻辑坐标和SetCursorPos的预期会有偏差。解决办法是在程序入口调用SetProcessDPIAware()或者在清单文件里声明 DPI 感知。#include windows.h int main() { SetProcessDPIAware(); // 让坐标基于物理像素 // ... 后续逻辑 }如果你在 MFC 里用把坐标显示到窗口标题的写法是这样POINT p; CString strPos, strCaption; GetCursorPos(p); strPos.Format(_T(%d, %d), p.x, p.y); strCaption _T(位置-) strPos; this-SetWindowTextW(strCaption);这段和上面的控制台版本本质一样只是把结果输出到了窗口标题。MFC 项目里记得包含afxwin.h之类的头CString的Format用_T宏保证宽窄字符兼容。5. 本篇常见错排查第一个高频问题GetCursorPos返回 0GetLastError拿到 5拒绝访问。这通常发生在服务进程或权限受限的会话里普通桌面程序很少遇到。如果你在 Windows 服务里跑鼠标操作需要额外处理会话隔离这不是本文范围建议改成桌面进程。第二个问题坐标对不上移动后读回来的值和预期差一截。九成是 DPI 缩放。检查你的进程有没有声明 DPI 感知或者用GetPhysicalCursorPos/SetPhysicalCursorPos这组物理坐标版本。注意GetPhysicalCursorPos在部分系统版本上对权限有要求普通用户态程序一般可用但如果你发现它失败退回GetCursorPos加 DPI 声明更稳。第三个问题SetCursorPos调用成功但鼠标没动。先确认目标坐标在屏幕范围内超出边界会被裁剪。多显示器场景下坐标是虚拟屏幕坐标副屏可能在负坐标区域SetCursorPos(-100, 200)是合法的。如果你只按主屏尺寸判断范围就会误判。第四个问题编译报undefined reference to GetCursorPos。这是没链接user32.lib。MSVC 加user32.libMinGW 加-luser32。SetCursorPos同样在这个库里。第五个问题Cline 里模型补全的代码用了GetCursorPos但没检查返回值。你可以在提示里明确要求「所有 Win32 调用都要检查返回值并打印 GetLastError」这样生成的代码更接近生产可用。这也是配好统一通道后让模型稳定输出高质量代码的一个小技巧。6. 把通道和代码串起来到这里鼠标坐标的读取、移动、验证已经跑通settings.json骨架也配好了。后续如果你想让 AI 帮你扩展功能比如加一个定时轮询坐标、或者做坐标记录回放可以直接在 Cline 里描述需求它会基于当前配置的通道补全代码。需要确认模型通道是否正常时用模型对话页 https://taotoken.net/chat?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 发一条测试消息即可要管理或新增 Key去 https://taotoken.net/api-keys?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 接入字段有疑问就查 https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 。一个实用建议把SetCursorPos相关的自动化代码放在独立函数里调用前先GetCursorPos存一份原始坐标操作完再还原这样调试时不会把鼠标「弄丢」。这个习惯我在写坐标偏移类工具时一直保留能省掉很多手动找鼠标的麻烦。