如何在C#控制台应用中实现鼠标悬停效果?
实现控制台程序鼠标悬停触发效果
原生.NET的Console类并没有直接提供鼠标悬停检测的API,但可以通过调用Windows API结合控制台窗口坐标计算来实现你的需求。下面是具体的实现思路和代码示例:
核心逻辑
- 预先记录灰色盒子在控制台中的行列范围
- 循环检测鼠标位置,将屏幕坐标转换为控制台内的行列坐标
- 判断鼠标是否处于盒子区域内,根据状态切换颜色或触发自定义函数
完整代码实现
using System; using System.Runtime.InteropServices; using System.Threading; sealed public class Program { // 引入Windows API用于获取鼠标位置和窗口坐标转换 [DllImport("user32.dll")] private static extern bool GetCursorPos(out POINT lpPoint); [DllImport("kernel32.dll")] private static extern IntPtr GetConsoleWindow(); [DllImport("user32.dll")] private static extern bool ScreenToClient(IntPtr hWnd, ref POINT lpPoint); private struct POINT { public int X; public int Y; } // 定义盒子的控制台行列范围 private const int BoxStartRow = 10; private const int BoxEndRow = 20; private const int BoxStartCol = 0; private const int BoxEndCol = 35; public static void Main(string[] args) { // 绘制初始界面 DrawInitialUI(); bool isHovering = false; // 循环检测鼠标状态 while (true) { var consoleHandle = GetConsoleWindow(); GetCursorPos(out POINT screenPos); ScreenToClient(consoleHandle, ref screenPos); // 将屏幕坐标转换为控制台行列(基于默认字体估算,可根据实际字体调整) int row = screenPos.Y / Console.CursorSize; int col = screenPos.X / (Console.WindowWidth / Console.BufferWidth); // 判断鼠标是否在盒子区域内 bool currentHover = row >= BoxStartRow && row <= BoxEndRow && col >= BoxStartCol && col <= BoxEndCol; if (currentHover != isHovering) { isHovering = currentHover; // 更新盒子颜色 UpdateBoxColor(isHovering); // 触发对应函数 if (isHovering) OnBoxHover(); else OnBoxLeave(); } // 降低CPU占用 Thread.Sleep(50); } } private static void DrawInitialUI() { Console.BackgroundColor = ConsoleColor.Red; Console.ForegroundColor = ConsoleColor.Yellow; Console.Write("F"); Console.ResetColor(); Console.BackgroundColor = ConsoleColor.Gray; Console.ForegroundColor = ConsoleColor.Black; Console.Write("ile - "); Console.BackgroundColor = ConsoleColor.Red; Console.ForegroundColor = ConsoleColor.Yellow; Console.Write("E"); Console.ResetColor(); Console.BackgroundColor = ConsoleColor.Gray; Console.ForegroundColor = ConsoleColor.Black; Console.Write("dit - "); Console.BackgroundColor = ConsoleColor.Red; Console.ForegroundColor = ConsoleColor.Yellow; Console.Write("C"); Console.ResetColor(); Console.BackgroundColor = ConsoleColor.Gray; Console.ForegroundColor = ConsoleColor.Black; Console.WriteLine("lose"); Console.ResetColor(); Console.BackgroundColor = ConsoleColor.Blue; Console.ForegroundColor = ConsoleColor.Black; Console.WriteLine("- - - - - - - - - - - - - - - - - - - - - - -"); Console.WriteLine("This is just some sample code."); Console.WriteLine("Now I will generate a little box that requires a hover effect."); Console.WriteLine("Basically I want its color to be changed to red upon hovering on it, or better - triggering some function."); Console.WriteLine("I don't think this is possible with console application, but just asking in case if it is still possible."); // 绘制初始灰色盒子 UpdateBoxColor(false); } private static void UpdateBoxColor(bool isHover) { // 保存当前光标位置,避免干扰其他输出 var originalCursorPos = new { Left = Console.CursorLeft, Top = Console.CursorTop }; Console.BackgroundColor = isHover ? ConsoleColor.Red : ConsoleColor.Gray; Console.ForegroundColor = isHover ? ConsoleColor.Red : ConsoleColor.Gray; // 重新绘制盒子区域 for (int i = BoxStartRow; i <= BoxEndRow; i++) { Console.SetCursorPosition(BoxStartCol, i); Console.WriteLine("###################################"); } // 恢复光标位置 Console.SetCursorPosition(originalCursorPos.Left, originalCursorPos.Top); Console.ResetColor(); } private static void OnBoxHover() { // 自定义悬停触发逻辑 Console.SetCursorPosition(0, 22); Console.WriteLine("鼠标已悬停在盒子上!"); } private static void OnBoxLeave() { // 自定义离开触发逻辑 Console.SetCursorPosition(0, 22); Console.WriteLine(" "); // 清空提示文本 } }
注意事项
- 坐标转换逻辑基于控制台默认字体,若你修改了控制台字体大小,需要调整
row和col的计算方式以匹配实际字符尺寸 - 循环检测会占用少量CPU,可通过调整
Thread.Sleep的参数平衡响应速度和资源占用 - 该方案仅适用于Windows系统,因为依赖Windows API;如果需要跨平台实现,可以考虑使用第三方终端UI库(如Terminal.Gui)
内容的提问来源于stack exchange,提问作者winscripter
相关产品推荐
相关产品推荐

