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

如何在C#控制台应用中实现鼠标悬停效果?

实现控制台程序鼠标悬停触发效果

原生.NET的Console类并没有直接提供鼠标悬停检测的API,但可以通过调用Windows API结合控制台窗口坐标计算来实现你的需求。下面是具体的实现思路和代码示例:

核心逻辑

  1. 预先记录灰色盒子在控制台中的行列范围
  2. 循环检测鼠标位置,将屏幕坐标转换为控制台内的行列坐标
  3. 判断鼠标是否处于盒子区域内,根据状态切换颜色或触发自定义函数

完整代码实现

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.31 13:05:17