iReso Style > Program > C# Tips > C# Tips - 現在の行や文字の位置を取得
2006年4月5日 23:21
カーソルの位置を表示するのは、カーソルが何らかの形で移動した時なので、この「移動」を知らせるイベントを作成すればよいです。 イベント名は「CursorPositionChanged」とし、このイベントを発生させるメソッドを「OnCursorPositionChanged」とします。 「RichTextBox」には「OnSelectionChanged」メソッドがあり、文字列の選択状態に変更があれば、「SelectionChanged」イベントを発生させます。
「OnSelectionChanged」メソッドは、「0」文字選択した状態、すなわち何も選択していない状態でも、カーソルが移動することにより選択位置が変わったと判断し、イベントを発生させます。 そこで、この「OnSelectionChanged」メソッドを継承し、内部で「OnCursorPositionChanged」メソッドを実行するようにすれば、カーソル移動の検出を知らせるイベントを実現出来ます。
using System; using System.Text; using System.Drawing; using System.Windows.Forms; // namespace (好きな名前でいいです。 // 親コントロールから「using」で呼び出します。) namespace CustomControl { // RichTextBoxを継承した新しいカスタムコントロールを宣言 public class RichTextBoxCustom : System.Windows.Forms.RichTextBox { // カーソル移動の検出を知らせるイベント public event EventHandler CursorPositionChanged; // カーソル移動の検出イベントを発生させるメソッド protected virtual void OnCursorPositionChanged( EventArgs e ) { // イベントが未発生であれば、発生させる if (CursorPositionChanged != null) { CursorPositionChanged(this, e); } } // 既存の「OnSelectionChanged」メソッドをオーバーライドする protected override void OnSelectionChanged( EventArgs e ) { // 「OnCursorPositionChanged」メソッドを実行する OnCursorPositionChanged(e); // 選択範囲が1文字以上あれば、本来の「OnSelectionChanged」メソッドを実行 if (SelectionLength > 0) { base.OnSelectionChanged(e); } }
後は親コントロールで「CursorPositionChanged」イベントを設定すれば、カーソル移動のたびにイベントを受け取る事出来ます。
次に、このカスタムコントロールからカーソルの位置情報を取得するプロパティを設定します。
カーソル位置の行番号を取得するのは簡単です。「RichTextBox」には、指定した文字が何行目にあるかを取得する「GetLineFromCharIndex」メソッドが 実装されていますので、それを使用すればいいでしょう。ちなみにこの「GetLineFromCharIndex」が返す値は「0」から始まる数値ですので、プラス1した数を 返すようにします。指定した文字のインデックスは「SelectionStart」メソッドで取得できます。
現在の行の文字インデックスに関しては、「GetFirstCharIndexOfCurrentLine」メソッドが良いでしょう。これは「.NET Framework version 2.0 」から追加されたメソッドで、 「.NET Framework version 1.1」にはないメソッドです。「GetFirstCharIndexOfCurrentLine」メソッドは、現在カーソルがある行の最初の文字インデックスを返します。 「SelectionStart」で現在の文字カーソル位置の文字インデックスを取得し、この値から「GetFirstCharIndexOfCurrentLine」メソッドで取得した値を減ずる事で、目的の値を取得できます。 サンプルでは、一番左にカーソルがあった場合を「1」としていますので、実際は減じた値にプラス1しています。
また、参考までにv1.1までのバージョンでの方法もコメントアウトで載せておきます。
// 現在のカーソルの行を取得
public int CurrentLine
{
get
{
// 「GetLineFromCharIndex」は「0」から始まる数値を返すので、
// 実際はプラス1した値を返す
return GetLineFromCharIndex(SelectionStart) + 1;
}
}
// 現在の行におけるカーソルが何文字目かを取得 (v2.0~)
public int CurrentColumn
{
get {
// 現在のカーソルの文字インデックスから現在の行の
// 最初の文字インデックスを減じ、さらにプラス1した値を返す
return SelectionStart - GetFirstCharIndexOfCurrentLine() + 1;
}
}
/*
// 現在の行におけるカーソルが何文字目かを取得 (~v1.1)
public int CurrentColumn
{
get {
// 現在のカーソルのリッチテキストボックスにおける座標を
// ピクセル単位で取得する。
Point p = GetPositionFromCharIndex(SelectionStart);
if (p.X == 1)
{
// 一番左にカーソルがあれば、「1」を返す
return 1;
}
else
{
// Y座標はそのまま、X座標を一番左にすることで、
// 現在の行の最初の文字インデックスを取得できる。
// 後は同じ。
p.X = 1;
return SelectionStart - GetCharIndexFromPosition(p) + 1;
}
}
}
*/
}
}
以上で必要最低限の機能が実装されました。
呼び出し側のフォームに今回作成したリッチテキストボックスを置きます。ファイルの先頭に「using CustomRichTextBox1;」も忘れないように記述します。
// カスタマイズしたリッチテキストボックスの宣言 internal CustomRichTextBox1.CsRichTextBox1 richTextBox1;
// コンストラクタ this.richTextBox1 = new CustomRichTextBox1.CsRichTextBox1();
後は普通に「RichTextBox」と同じです。
サイズなどのプロパティを記述している部分に追加で、以下のイベントを記述します。
// カーソルの移動を検出するイベント this.richTextBox1.CursorPositionChanged += new System.EventHandler(this.richTextBox1_CursorPositionChanged); // 選択範囲の変更を検出するイベント this.richTextBox1.SelectionChanged += new System.EventHandler(this.richTextBox1_SelectionChanged);
さらに、メソッドを記述します。
// カーソルの移動が検出された時の動作 private void richTextBox1_CursorPositionChanged(object sender, System.EventArgs e) { // 現在の行と文字位置を取得 int line = richTextBox1.CurrentLine; int col = richTextBox1.CurrentColumn; // ステータスバーなどに表示すると良いでしょう } // 選択範囲の変更が検出された時の動作 private void richTextBox1_SelectionChanged(object sender, System.EventArgs e) { // 例えば、以下のようにすれば、現在選択されている文字数を取得できます。 int sel = richTextBox1.SelectionLength; // 表示 }