如何在C#控制台应用程序中获取光标处的字符

本文关键字:光标 获取 字符 应用程序 控制台 | 更新日期: 2023-09-27 18:28:19

我知道如何将光标设置到控制台中的特定点,同时使用SetCursorPositionCursorLeftCursorTop。这不是问题。

但是,我如何获得该点的值?难道没有类似控制台的东西。光标吗?所以我可以把角色放在那个位置?也许类似于:

char c = Console.GetCharAtCursor();

运气不好?

如何在C#控制台应用程序中获取光标处的字符

AFAIK,您必须将整个控制台缓冲区读取为二维缓冲区,并使用光标的X和Y坐标作为该缓冲区的索引。参见:

[DllImport("kernel32.dll", CharSet=CharSet.Unicode, SetLastError=true)]
public static extern bool GetConsoleScreenBufferInfo(
    IntPtr consoleHandle,
    out CONSOLE_SCREEN_BUFFER_INFO consoleScreenBufferInfo);

你可以在这里阅读缓冲区结构:

http://msdn.microsoft.com/en-us/library/windows/desktop/ms682093(v=vs.85).aspx

更新:

如果你对使用控制台API编写游戏感兴趣,有人为控制台编写了空间入侵者(实际上是powershell),但所有的API都是托管代码,而不是脚本。他有精灵/路径例程等-来源已经结束http://ps1.soapyfrog.com/2007/08/26/grrr-source-code-including-invaders/

"CursorLeft"answers"CursorTop"有getter,所以您可以直接读取它们:var cleft = Console.CursorLeft

根据MSDN论坛的答案:

[DllImport("kernel32.dll", SetLastError = true)]
static extern IntPtr GetStdHandle(int nStdHandle);
[DllImport("kernel32.dll", SetLastError = true)]
static extern bool ReadConsoleOutputCharacter(
    IntPtr hConsoleOutput, 
    [Out] StringBuilder lpCharacter, 
    uint length, 
    COORD bufferCoord, 
    out uint lpNumberOfCharactersRead);
[StructLayout(LayoutKind.Sequential)]
public struct COORD
{
    public short X;
    public short Y;
}
public static char ReadCharacterAt(int x, int y)
{
    IntPtr consoleHandle = GetStdHandle(-11);
    if (consoleHandle == IntPtr.Zero)
    {
        return ''0';
    }
    COORD position = new COORD
    {
        X = (short)x,
        Y = (short)y
    };
    StringBuilder result = new StringBuilder(1);
    uint read = 0;
    if (ReadConsoleOutputCharacter(consoleHandle, result, 1, position, out read))
    {
        return result[0];
    }
    else
    {
        return ''0';
    }
}

应用它看起来像这样:

class Program
{
    static void Main(string[] args)
    {
        Console.Clear();
        Console.CursorLeft = 0;
        Console.CursorTop = 1;
        Console.Write("0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ");
        char first = ReadCharacterAt(10, 1);
        char second = ReadCharacterAt(20, 1);
        Console.ReadLine();
    }
}

我不喜欢这里为我的简单应用程序发布的长答案,所以我想了一个解决办法——我将整个控制台缓冲区存储在一个2D数组中,然后在数组中进行索引。为我的应用程序工作(在控制台中生成冰柱):

            char[,] array = new char[20, Console.BufferWidth];
            for (int i = 0; i < array.GetLength(0); i++)
            {
                for (int j = 0; j < array.GetLength(1); j++)
                {
                    if (i > 0 && array[i - 1, j] == ' ')
                    {
                        array[i, j] = ' ';
                        Console.Write(' ');
                    }
                    else
                    {
                        int x = getRandom.Next(10);
                        switch (x)
                        {
                            case 0:
                                array[i, j] = ' ';
                                Console.Write(array[i, j]);
                                break;
                            default:
                                array[i, j] = 'x';
                                Console.Write(array[i, j]);
                                break;
                        }
                    }
                }
                Console.WriteLine();
            }