如何在Windows中全局修改鼠标光标?自定义十字光标不生效怎么解决?
失效原因
Cursor.Current = Cursors.Cross;仅在鼠标位于当前进程的窗体客户区范围内时生效,当你隐藏主窗体后,鼠标移动到桌面或其他进程窗口区域时,系统会自动重置光标样式,因此该设置自然失效。
可行解决方案
方案1:全屏透明覆盖窗体(最适配你的需求,无API调用)
你可以新增一个全屏、全透明、置顶的覆盖窗体铺满所有屏幕区域、显示在所有窗口上层,此时整个屏幕范围都属于该窗体的客户区,直接设置该窗体的光标为十字即可全局生效,同时你需要的鼠标点击、Tooltip显示逻辑都可以直接挂载在这个窗体上:
// 取点开始时调用 Form coverForm = new Form() { FormBorderStyle = FormBorderStyle.None, WindowState = FormWindowState.Maximized, BackColor = Color.Magenta, TransparencyKey = Color.Magenta, TopMost = true, Cursor = Cursors.Cross, ShowInTaskbar = false }; // 你原本的极小form的tooltip功能可以直接关联到这个覆盖窗体 ToolTip toolTip = new ToolTip(); toolTip.SetToolTip(coverForm, "你要显示的提示内容"); // 左键点击事件处理 coverForm.MouseClick += (s, e) => { if(e.Button == MouseButtons.Left) { // 此处e.Location就是你要的取点坐标 Point targetPoint = e.Location; // 关闭覆盖窗体自动恢复默认光标 coverForm.Close(); // 重新显示主窗体 mainForm.Show(); } }; coverForm.Show();
*该方案不会修改系统级配置,不会出现光标恢复失败的问题,兼容性最好。
方案2:调用系统API替换全局光标
如果不想新增窗体的话,可以调用SetSystemCursor API临时替换系统默认箭头光标为十字,取点完成后必须恢复系统默认光标:
// 导入所需API及常量定义 [DllImport("user32.dll")] private static extern bool SetSystemCursor(IntPtr hcur, uint id); [DllImport("user32.dll", SetLastError = true)] private static extern IntPtr LoadCursor(IntPtr hInstance, uint lpCursorName); [DllImport("user32.dll")] private static extern bool SystemParametersInfo(uint uiAction, uint uiParam, IntPtr pvParam, uint fWinIni); private const uint OCR_NORMAL = 32512; private const uint SPI_SETCURSORS = 0x0057; private const uint SPIF_UPDATEINIFILE = 0x01; private const uint SPIF_SENDCHANGE = 0x02; // 切换为十字光标时调用 IntPtr crossCursor = Cursors.Cross.CopyHandle(); SetSystemCursor(crossCursor, OCR_NORMAL); // 取点完成恢复默认光标时调用 SystemParametersInfo(SPI_SETCURSORS, 0, IntPtr.Zero, SPIF_UPDATEINIFILE | SPIF_SENDCHANGE);
注意:如果程序意外崩溃没有执行恢复逻辑会导致系统光标永久变为十字,需要重启资源管理器或者电脑才能恢复,因此优先推荐方案1
内容的提问来源于stack exchange,提问作者Arvo Bowen
相关产品推荐
相关产品推荐

