画面上の指定された位置から単一の文字を読み取るためにWindows10で機能する簡略化されたデモ。(X, Y)
.NET4.7.2でテスト済み。
まず、コンソールにデモグリッドを入力するコード行を次に示します。デモを機能させるには、画面の左上隅にレンダリングする必要があることに注意してください。
static void Populate_Console()
{
Console.Clear();
Console.Write(@"
┌───────┐
1│C D E F│
2│G H I J│
3│K L M N│
4│O P Q R│
└───────┘
2 4 6 8 ".Trim());
}
次のようになります。

それでは、いくつかの文字を読み返してみましょう。開始するには、 stdoutのネイティブコンソールハンドルが必要です。Win32から取得するためのP/Invokeメソッドは次のとおりです。
[DllImport("kernel32", SetLastError = true)]
static extern IntPtr GetStdHandle(int num);
さて、クールな部分です。ReadConsoleOutputCharacter
これは、 Win32関数を使用するこのページのこれまでのところ唯一の答えのようです。文字の色属性を取得することはできませんが、このアプローチでは、長方形のコピーを処理したり、CreateConsoleScreenBuffer
画面バッファーを割り当ててそれらの間でコピーしたりする手間を省くことができます。
AnsiとUnicodeのバージョンは別々にあり、コンソールウィンドウでアクティブになっているコードページに応じて適切なバージョンを呼び出す必要があります。ここでは両方のP/Invoke署名を示していますが、簡単にするために、例ではAnsiバージョンを続行します。
[DllImport("kernel32", SetLastError = true, CharSet = CharSet.Ansi)]
[return: MarshalAs(UnmanagedType.Bool)] // ̲┌──────────────────^
static extern bool ReadConsoleOutputCharacterA(
IntPtr hStdout, // result of 'GetStdHandle(-11)'
out byte ch, // A̲N̲S̲I̲ character result
uint c_in, // (set to '1')
uint coord_XY, // screen location to read, X:loword, Y:hiword
out uint c_out); // (unwanted, discard)
[DllImport("kernel32", SetLastError = true, CharSet = CharSet.Unicode)]
[return: MarshalAs(UnmanagedType.Bool)] // ̲┌───────────────────^
static extern bool ReadConsoleOutputCharacterW(
IntPtr hStdout, // result of 'GetStdHandle(-11)'
out Char ch, // U̲n̲i̲c̲o̲d̲e̲ character result
uint c_in, // (set to '1')
uint coord_XY, // screen location to read, X:loword, Y:hiword
out uint c_out); // (unwanted, discard)
一度に1文字のみをフェッチするように設計されたサンプルコードの目的に必要な最小限に、これらのマーシャリングを削除したことに気付くかもしれません。したがって、マネージポインタ宣言'<code> outbytech'および'<code>out Char ch'により、これc_in
は常にである必要があります。1
本当に必要なのはそれだけです。上記のように適切なP/Invoke関数を呼び出すことは、1文字の読み取りに制限している場合、ほとんどの場合自明です。これを簡単な例で示すためにConsole
、上に描いたグリッドの対角線に沿って、から4文字を読み取るかわいいデモプログラムで終了します。
static void Windows_Console_Readback()
{
var stdout = GetStdHandle(-11);
for (uint coord, y = 1; y <= 4; y++)
{
coord = (5 - y) * 2; // loword <-- X coord to read
coord |= y << 16; // hiword <-- Y coord to read
if (!ReadConsoleOutputCharacterA(
stdout,
out byte chAnsi, // result: single ANSI char
1, // # of chars to read
coord, // (X,Y) screen location to read (see above)
out _)) // result: actual # of chars (unwanted)
throw new Win32Exception();
Console.Write(" " + (Char)chAnsi + " ");
}
}
そして、あなたはそれを持っています...
