简体   繁体   中英

How can I get the character at the cursor in a C# console application?

I know how to set the cursor to a specific point in the console with SetCursorPosition or CursorLeft and CursorTop together. That's not a problem.

But , how can I get the value of that point? Isn't there a thing like Console.Cursor ? So I can get the character at that position? Maybe something like:

char c = Console.GetCharAtCursor();

No luck?

AFAIK, you have to read the entire console buffer as a two dimensional buffer, and use the cursor's X and Y coordinates as an index into that buffer. See:

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

You can read about the buffer structure here:

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

Update:

If you're interested in using console APIs for game writing, someone wrote space invaders for the console (actually powershell) but all of the APIs are managed code, not script. He has sprite/path routines etc - the source is over on http://ps1.soapyfrog.com/2007/08/26/grrr-source-code-including-invaders/

According the answer from the MSDN forum :

[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';
    }
}

Applied it looks like this:

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();
    }
}

I did not like the long answers posted here for my simple application, so I figured a workaround for this – I stored the entire console buffer in a 2D array and then just indexed in the array. Worked for my application (generating icicles in console):

            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();
            }

'CursorLeft' 和 'CursorTop' 有 getter,所以你可以直接阅读它们: var cleft = Console.CursorLeft

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM