.NET TIPS

コンソール画面でカーソルを自由に移動させるには?

デジタルアドバンテージ 一色 政彦
2006/08/25

 コンソール・アプリケーションの画面では、テキストの入力位置にカーソルが表示される。例えば、次の画面で示されているようなカーソルである。

コンソール画面上のカーソル
赤丸で示した部分がカーソルである。カーソルは通常点滅している。

 .NET Framework 2.0では、このカーソルの表示をカスタマイズするためのプロパティと、カーソルの位置を操作するためのプロパティおよびメソッドが追加されている。具体的には次の静的プロパティと静的メソッドである。

【カーソル表示関連】
Console.CursorVisibleプロパティ
Console.CursorSizeプロパティ

【カーソル位置関連】
Console.CursorLeftプロパティ
Console.CursorTopプロパティ
Console.SetCursorPositionメソッド

■カーソル表示に関するプロパティ

 まずはカーソル表示に関するプロパティについて説明しよう。

 コンソール・アプリケーションでは、デフォルトの状態でカーソルが表示されるはずだが、CursorVisibleプロパティにFalseを設定するとこのカーソルが非表示になる。また、CursorVisibleプロパティの値を取得することでカーソルの表示(=True)/非表示(=False)の状態を判別することもできる。

 CursorSizeプロパティでは、カーソルの高さの取得と設定が(「1」〜「100」%の間で)行える。筆者の環境ではデフォルトでこのプロパティの値は「25」%になっていたが(先ほど掲載した画面のカーソルの高さは「25」%である)、次の画面は「100」を設定した場合のカーソルの表示例だ。

CursorSizeプロパティに「100」を設定した場合のカーソルの高さ
先ほどの画面のカーソルと比べると、文字の高さいっぱいまでカーソルのサイズが大きくなっていることが分かる。

■カーソル操作に関するプロパティとメソッド

 次はカーソル操作に関連するプロパティとメソッドについて説明する。

 CursorLeftプロパティでは、現在カーソルがある列位置の値を取得/設定することができる。またCursorTopプロパティでは行位置の値を取得/設定できる(なお、どちらも「0」開始で、画面左上隅が原点だ。ただし、バッファ領域外の場所にカーソルを設定しようとすると例外が発生するので注意すること。バッファ領域の横幅はBufferWidthプロパティ、高さはBufferHeightプロパティから取得できる。これらのプロパティも.NET Framework 2.0で追加されたものである)。

 カーソル位置をプログラム・コードによって移動させたい場合、これらのCursorLeftプロパティとCursorTopプロパティを設定すればよいわけだが、SetCursorPositionメソッドを使えば列と行の両方の指定を一括して行えるので便利だ。

■上記のプロパティとメソッドを活用したサンプル・プログラム

 次のコードは、以上のプロパティとメソッドを活用したコンソール・アプリケーションである。このアプリケーションでは、[←][→][↑][↓]などのキーを押すことにより、コンソール画面内(厳密にはバッファ領域内)で自由にカーソルを移動できるというものである(カーソルを移動する際、画面から見えない位置に移動するときには自動的にコンソール画面がスクロールする)。

using System;

namespace ConsoleApplication1
{
  class Program
  {
    static void Main(string[] args)
    {
      // カーソルを非表示にする
      Console.CursorVisible = false;

      // コンソール画面に3行のテキストを出力
      Console.WriteLine("[←][→][↑][↓]キーで移動。");
      Console.WriteLine("[Esc]キーで終了します。");
      Console.WriteLine("[Enter]キーを押すと開始します。");
      Console.ReadLine();

      // 画面をクリアする
      Console.Clear();

      // カーソルを表示する
      Console.CursorVisible = true;

      // カーソルの高さを100%に設定する(デフォルトは25%)
      Console.CursorSize = 100;

      bool reading = true;
      while (reading)
      {
        // 入力されたキーを取得する
        ConsoleKeyInfo c = Console.ReadKey(true);
        switch (c.Key)
        {
          case ConsoleKey.Escape:
            Console.Clear();
            reading = false;
            break;

          case ConsoleKey.LeftArrow:
            MoveCursor(-1, 0);
            break;
          case ConsoleKey.RightArrow:
            MoveCursor(1, 0);
            break;
          case ConsoleKey.UpArrow:
            MoveCursor(0, -1);
            break;
          case ConsoleKey.DownArrow:
            MoveCursor(0, 1);
            break;
        }
      }
    }

    // カーソルの位置を移動する
    private static void MoveCursor(int x, int y)
    {
      // 移動先のカーソル位置を決定する
      int destCursorLeft = Console.CursorLeft + x;
      int destCursorTop = Console.CursorTop + y;

      // カーソルの左位置の範囲からオーバーしていれば補正する
      if (destCursorLeft < 0)
      {
        destCursorLeft = 0;
      }
      if (destCursorLeft > Console.BufferWidth - 1)
      {
        destCursorLeft = Console.BufferWidth - 1;
      }

      // カーソルの上位置の範囲からオーバーしていれば補正する
      if (destCursorTop < 0)
      {
        destCursorTop = 0;
      }
      if (destCursorTop > Console.BufferHeight - 1)
      {
        destCursorTop = Console.BufferHeight - 1;
      }

      // カーソルの位置を移動する
      Console.SetCursorPosition(destCursorLeft, destCursorTop);

      // 次のようにプロパティ経由で設定してもよい
      //Console.CursorLeft = destCursorLeft;
      //Console.CursorTop = destCursorTop;
    }
  }
}
Module Module1

  Sub Main()
    ' カーソルを非表示にする
    Console.CursorVisible = False

    ' コンソール画面に3行のテキストを出力
    Console.WriteLine("[←][→][↑][↓]キーで移動。")
    Console.WriteLine("[Esc]キーで終了します。")
    Console.WriteLine("[Enter]キーを押すと開始します。")
    Console.ReadLine()

    ' 画面をクリアする

    Console.Clear()

    ' カーソルを表示する
    Console.CursorVisible = True

    ' カーソルの高さを100%に設定する(デフォルトは25%)
    Console.CursorSize = 100

    Dim reading As Boolean = True
    While (reading)
      ' 入力されたキーを取得する
      Dim c As ConsoleKeyInfo = Console.ReadKey(True)
      Select Case c.Key
        Case ConsoleKey.Escape
          Console.Clear()
          reading = False

        Case ConsoleKey.LeftArrow
          MoveCursor(-1, 0)

        Case ConsoleKey.RightArrow
          MoveCursor(1, 0)

        Case ConsoleKey.UpArrow
          MoveCursor(0, -1)

        Case ConsoleKey.DownArrow
          MoveCursor(0, 1)

      End Select
    End While

  End Sub

  ' カーソルの位置を移動する
  Sub MoveCursor(ByVal x As Integer, ByVal y As Integer)

    ' 移動先のカーソル位置を決定する
    Dim destCursorLeft As Integer = Console.CursorLeft + x
    Dim destCursorTop As Integer = Console.CursorTop + y

    ' カーソルの左位置の範囲からオーバーしていれば補正する
    If destCursorLeft < 0 Then
      destCursorLeft = 0
    End If
    If destCursorLeft > Console.BufferWidth - 1 Then
      destCursorLeft = Console.BufferWidth - 1
    End If

    ' カーソルの上位置の範囲からオーバーしていれば補正する
    If destCursorTop < 0 Then
      destCursorTop = 0
    End If
    If destCursorTop > Console.BufferHeight - 1 Then
      destCursorTop = Console.BufferHeight - 1
    End If

    ' カーソルの位置を移動する
    Console.SetCursorPosition(destCursorLeft, destCursorTop)

    ' 次のようにプロパティ経由で設定してもよい
    'Console.CursorLeft = destCursorLeft
    'Console.CursorTop = destCursorTop
  End Sub

End Module
カーソルを自由に移動できるコンソール・アプリケーションのサンプル・プログラム(上:C#、下:VB)

 コードの詳しい内容はコード内のコメントを参照してほしいが、以下で、一通りのプログラムの流れを解説しておこう。

 まずこのアプリケーションでは、カーソルを非表示にしてテキストを3行ほどコンソール画面に出力している。次にReadLineメソッドにより[Enter]キーの入力を待ち、実際に[Enter]キーが押されると、画面のクリア、カーソルの再表示、カーソルの高さの変更を行っている(画面のクリアに関しては「TIPS:コンソール画面をクリアするには?」を参考にされたい)。

 そしてユーザーからのキー入力を取得し続けるループに入る。このループ内ではReadKeyメソッドが呼び出されて、ユーザーからのキー入力を受け付ける。

 実はReadKeyメソッドも.NET Framework 2.0で新たに追加されたもので、パラメータなしで呼び出すと、ユーザーが押したキーの内容をConsoleKeyInfo構造体(System名前空間)のオブジェクトとして取得できる。

 ただしこの際、押されたキーはコンソール画面に出力されてしまうので注意が必要だ。これを出力しないようにするには、ReadKeyメソッドのパラメータにtrueを指定して呼び出さなければならない。本稿のサンプル・プログラムではそのようにすることでコンソール画面への入力キーの表示を抑制している。

 ReadKeyメソッドで取得したConsoleKeyInfoオブジェクトから押されたキーを判定するには、そのKeyプロパティを参照すればよい。このプロパティからはConsoleKey列挙体(System名前空間)の値が取得できる(この列挙体の値については「MSDN:ConsoleKey 列挙体」を参照してほしい)。本プログラムでは、この値が[Esc]キー(=[Escape]キー)であればループから抜け出してアプリケーションを終了する。また、[←][→][↑][↓]などのキーであればそれぞれの方向への移動処理を実行する。

 移動処理自体は独自に実装したMoveCursorメソッドを呼び出すことで実現している。MoveCursorメソッド内では、CursorLeftプロパティとCursorTopプロパティを参照して現在のカーソル位置を取得し、その位置からの移動分を加算/減算することで最終的な移動先の位置を決定している。

 ここで移動先が範囲外だった場合のエラーを防ぐため、移動位置が範囲内に収まっているかどうかを確認し、範囲外であれば範囲内に収まるように値を修正している。適正な移動先の位置をパラメータに指定してSetCursorPositionメソッドを呼び出し、カーソルの移動を行っている。

■サンプル・プログラムの実行

 以上が理解できたら、このサンプル・プログラムを実際に実行してみよう。次の画面はその実行例だ。

[Enter]キーを押す
[←][→][↑][↓]などのキーを押す
サンプル・プログラムの実行結果
[←][→][↑][↓]などのキーを押すと、コンソール画面内でカーソルを自由に移動させられる。なおアプリケーションを終了するには[Esc]キーを押す。

 このように、.NET Framework 2.0ではコンソール画面内でカーソルを自由に移動させられる。これを活用すれば任意の位置にテキストを表示させることもできるので、プログラム・コードでアスキー・アートのような図を作成するようなことも簡単である(例えばコンソール・アプリケーションでプログラムのコピーライトなどを表示する場所に、テキストで何らかのマークを表示させたい場合などで使えるだろう)。End of Article

カテゴリ:コンソール・アプリケーション 処理対象:画面
使用ライブラリ:Consoleクラス(System名前空間)
使用ライブラリ:ConsoleKeyInfo構造体(System名前空間)
使用ライブラリ:ConsoleKey列挙体(System名前空間)
関連TIPS:コンソール画面をクリアするには?

この記事と関連性の高い別の.NET TIPS
コンソール・アプリケーションで進行状況を表示するには?
待機状態のマウス・カーソルを表示するには?
簡単に待機カーソルを表示するには?
Visual Studio 2005でクラスやメソッドの定義を簡単に参照するには?
マウス・カーソルの位置を取得・設定するには?
このリストは、(株)デジタルアドバンテージが開発した
自動関連記事探索システム Jigsaw(ジグソー) により自動抽出したものです。
generated by

「.NET TIPS」


Insider.NET フォーラム 新着記事
  • 第2回 簡潔なコーディングのために (2017/7/26)
     ラムダ式で記述できるメンバの増加、throw式、out変数、タプルなど、C# 7には以前よりもコードを簡潔に記述できるような機能が導入されている
  • 第1回 Visual Studio Codeデバッグの基礎知識 (2017/7/21)
     Node.jsプログラムをデバッグしながら、Visual Studio Codeに統合されているデバッグ機能の基本の「キ」をマスターしよう
  • 第1回 明瞭なコーディングのために (2017/7/19)
     C# 7で追加された新機能の中から、「数値リテラル構文の改善」と「ローカル関数」を紹介する。これらは分かりやすいコードを記述するのに使える
  • Presentation Translator (2017/7/18)
     Presentation TranslatorはPowerPoint用のアドイン。プレゼンテーション時の字幕の付加や、多言語での質疑応答、スライドの翻訳を行える
@ITメールマガジン 新着情報やスタッフのコラムがメールで届きます(無料)

注目のテーマ

Insider.NET 記事ランキング

本日 月間