/// <summary> /// キーが押された時。特定のキーが押された時の動作を定義する。 /// </summary> /// <param name="e"></param> protected override void OnKeyDown(KeyEventArgs e) { switch (e.KeyCode) { case Keys.Up: break; case Keys.Down: break; case Keys.Right: CurrentPos = new Position(CurrentPos.Line, CurrentPos.Pos + 1); e.SuppressKeyPress = true; break; case Keys.Left: CurrentPos = new Position(CurrentPos.Line, CurrentPos.Pos - 1); e.SuppressKeyPress = true; break; case Keys.Enter: // 現在の行(Enterキーを押した行) MyLine currentLine = list[CurrentPos.Line]; // 新しく作られる行。現在の行のEnterキーを押した場所(キャレットの位置)から後ろの文字列と現在の行の改行コードを移す。 MyLine newLine = new MyLine(currentLine.TextWithoutReturnValue.Substring(CurrentPos.Pos),currentLine.ReturnCode); // 現在の行のEnterキーを押した場所(キャレットの位置)から後ろの文字列を削除する。 currentLine.Delete(CurrentPos.Pos, currentLine.Length - CurrentPos.Pos); // 現在の行の改行コードにはMyTextboxのデフォルトの改行コードを入れる。 currentLine.ReturnCode = this._returnCode; // リストに新しい行を追加する。 list.Insert(CurrentPos.Line + 1, newLine); // キャレットの位置を新しく作成した行の先頭に設定する。 CurrentPos = new Position(CurrentPos.Line + 1, 0); // Keyイベントをコントロールに渡さない場合はtrue。これをtrueにすると、同時にHandledもtrueとなる。 e.SuppressKeyPress = true; // 再描画する。 Invalidate(); break; case Keys.Back: // 1文字deleteする。キャレット操作もDelete()でやる。 this.Delete(CurrentPos.Line, CurrentPos.Pos - 1, 1); e.SuppressKeyPress = true; break; case Keys.Tab: break; } //base.OnKeyDown(e); }
/// <summary> /// 任意の位置に文字列を挿入 /// </summary> /// <param name="nLine">Line number. 0 origin</param> /// <param name="pos"></param> /// <param name="str"></param> public Task Insert(int nLine, int pos, string str) { //nLineがまだ存在しない行番号だった場合に備えて、その行までの存在しない行を全て作成 // 例えば、現在0-4行目が存在、8行目に文字を挿入する場合、 // 5-8行目を作成する。 for (int i = list.Count; i < nLine + 1; i++) { MyLine newLine = new MyLine(); list.Add(newLine); } MyLine line = list[nLine]; line.Insert(pos, str); CurrentPos = new Position(CurrentPos.Line, CurrentPos.Pos + str.Length); Task task = new Insert(); task.fromLine = nLine; task.fromPos = pos; task.length = str.Length; task.str = str; history.Add(task); if (MyTaskEvent != null) { TaskEventArgs args = new TaskEventArgs(); args.task = task; MyTaskEvent(this, args); } return task; }
/// <summary> /// /// </summary> public MyTextbox() { list = new List<MyLine>(); MyLine firstLine = new MyLine(); list.Add(firstLine); this.Font = MyTextboxDefaultValue.Font; this._returnCode = MyTextboxDefaultValue.ReturnCode; this.AllowDrop = true; this.DragDrop += new DragEventHandler(MyTextbox_DragDrop); caret = new Caret(this.Handle, 2, this.Font.Height); CurrentPos = new Position(0, 0); history = new List<Task>(); vScrollBar = new VScrollBar(); hScrollBar = new HScrollBar(); vScrollBar.Dock = DockStyle.Right; hScrollBar.Dock = DockStyle.Bottom; vScrollBar.Value = 0; vScrollBar.Minimum = 0; vScrollBar.Scroll += vScrollBar_Scroll; this.Controls.Add(vScrollBar); this.Controls.Add(hScrollBar); }
/// <summary> /// 文字列を削除 /// </summary> /// <param name="nLine"></param> /// <param name="index">開始点</param> /// <param name="count">削除する長さ</param> public void Delete(int nLine, int index, int count) { if (index < 0) { // 行の先頭でBackspaceを押すとここに来る。 // (0, 0)であれば無視。 // それ以外であれば前の行の改行コードを消して、前の行と結合する。 if (nLine == 0) { // 無視する。 return; } else { CurrentPos = new Position(nLine - 1, list[nLine - 1].Length); MyLine line = new MyLine(list[nLine - 1].TextWithoutReturnValue + list[nLine].TextWithoutReturnValue, list[nLine].ReturnCode); list[nLine - 1] = line; list.RemoveAt(nLine); Invalidate(); } } else { // 現状、0点で実行すると-1になるバグあり MyLine line = list[nLine]; line.Delete(index, count); CurrentPos = new Position(nLine, index); } // 履歴に登録し、タスクイベントを起こす Task task = new Delete(); task.fromLine = nLine; task.fromPos = index; task.length = count; history.Add(task); if (MyTaskEvent != null) { TaskEventArgs args = new TaskEventArgs(); args.task = task; MyTaskEvent(this, args); } Invalidate(); }
/// <summary> /// /// </summary> /// <param name="position"></param> /// <returns></returns> private Point Position2Point(Position position) { float testHeight = 0F; for (int i = 0; i < position.Line; i++) { testHeight += list[i].Height; } int y = (int)testHeight; MyLine line = list[position.Line]; int x; if (position.Pos == 0) x = 0; else x = (int)line.GetWidth(0, position.Pos - 1);// 前の文字までの長さを取得 return new Point(x, y); }