| Code Edit Box of Simulang (source code) |
|---|
|
Download source files:
この記事は 2026年2月4日 水 12:37 に作者によって編集されましたhttp://www.jkofsp.net/files/ <UserControl1.cs> using System; using System.Collections.Generic; using System.ComponentModel; using System.Drawing; using System.Data; using System.Linq; using System.Text; using System.Windows.Forms; using System.IO; namespace CodeEditBox { public partial class CodeEditBox : UserControl { private List<string> TextLines; private List<List<byte>> TextColor; private readonly byte Color_Normal = 0, Color_Keyword = 1, Color_Comment = 2, Color_String = 3; private int CursorX, CursorDX, CursorY; private int ViewX, ViewY; public string[] Keywords; private Dictionary<char, Bitmap> FullWidthSymbols; public event EventHandler<EventArgs> TextChanged, ViewMouseClick; public CodeEditBox() { InitializeComponent(); View.Visible = true; HScroll.Visible = true; VScroll.Visible = true; TextLines = new List<string>(); TextLines.Add(""); CursorX = 0; CursorDX = 0; CursorY = 0; ViewX = 0; ViewY = 0; TextColor = new List<List<byte>>(); TextColor.Add(null); //this.LostFocus += new EventHandler((sender, e) => Focus()); } public void LoadText(string text) { TextLines = new List<string>(); TextLines.AddRange(text.Replace("\r\n", "\n").Replace('\t', ' ').Split('\n')); if (TextLines.Count == 0) TextLines.Add(""); CursorX = 0; CursorDX = 0; CursorY = 0; ViewX = 0; ViewY = 0; VScroll.Maximum = TextLines.Count - 1; TextColor = new List<List<byte>>(); for (int i = 0; i < TextLines.Count; i++) TextColor.Add(null); for (int i = 0; i < TextLines.Count; i++) Highlight(i); CheckScroll(); View.Refresh(); } public string GetText() { StringBuilder text = new StringBuilder(); text.Append(TextLines[0]); for (int i = 1; i < TextLines.Count; i++) text.Append("\r\n").Append(TextLines[i]); return text.ToString(); } public int GetCurrentLineID() { return CursorY; } public int GetLineCount() { return TextLines.Count; } public string GetLine(int lineIndex) { if (lineIndex < 0 || lineIndex >= TextLines.Count) throw new Exception(); return TextLines[lineIndex]; } public void SelectText(int lineIndex, int start, int length) { if (lineIndex < 0 || lineIndex >= TextLines.Count) throw new Exception(); CursorY = lineIndex; if (start < 0 || start > TextLines[CursorY].Length) throw new Exception(); if (start + length < 0 || start + length > TextLines[CursorY].Length) throw new Exception(); CursorX = start + length; CursorDX = -length; CheckScroll(); View.Refresh(); } public void CancelSeletion() { CursorDX = 0; View.Refresh(); } public string GetSelectedText() { if (CursorDX == 0) { return ""; } else { if (CursorDX < 0) return TextLines[CursorY].Substring(CursorX + CursorDX, -CursorDX); else return TextLines[CursorY].Substring(CursorX, CursorDX); } } public void InsertOrReplaceText(string text) { if (text == "") return; if (CursorDX == 0) { TextLines[CursorY] = TextLines[CursorY].Substring(0, CursorX) + text + TextLines[CursorY].Substring(CursorX); CursorX += text.Length; //CursorDX = 0; } else { if (CursorDX < 0) { TextLines[CursorY] = TextLines[CursorY].Substring(0, CursorX + CursorDX) + text + TextLines[CursorY].Substring(CursorX); CursorX += CursorDX + text.Length; } else { TextLines[CursorY] = TextLines[CursorY].Substring(0, CursorX) + text + TextLines[CursorY].Substring(CursorX + CursorDX); CursorX += text.Length; } CursorDX = -text.Length; } Highlight(CursorY); CheckScroll(); View.Refresh(); } private void Render(Graphics g) { if (CursorDX < 0) g.FillRectangle(Brushes.Aqua, (CursorX + CursorDX - ViewX) * 7 + 1, (CursorY - ViewY) * 11, - CursorDX * 7, 11); else if (CursorDX > 0) g.FillRectangle(Brushes.Aqua, (CursorX - ViewX) * 7 + 1, (CursorY - ViewY) * 11, CursorDX * 7, 11); Font font = new Font("Lucida Console", 9.0f); for (int i = ViewY; i < Math.Min(ViewY + View.Height / 11, TextLines.Count); i++) for (int j = ViewX; j < Math.Min(ViewX + View.Width / 7, TextLines[i].Length); j++) { if (TextLines[i][j] != ' ') { if (new List<char>(new char[] { '←', '∈', '÷', '≠', '≤', '≥' }).Contains(TextLines[i][j])) { //if (TextColor[i][j] != Color_Normal) // throw new Exception(); g.DrawImage(FullWidthSymbols[TextLines[i][j]], (j - ViewX) * 7 + 1, (i - ViewY) * 11); } else { Brush brush; if (TextColor[i][j] == Color_Normal) brush = Brushes.Black; else if (TextColor[i][j] == Color_Keyword) brush = Brushes.Blue; else if (TextColor[i][j] == Color_Comment) brush = Brushes.Green; else if (TextColor[i][j] == Color_String) brush = Brushes.DarkRed; else throw new Exception(); g.DrawString(TextLines[i][j].ToString(), font, brush, (j - ViewX) * 7.0f, (i - ViewY) * 11.0f); } } } g.DrawLine(Pens.Black, (CursorX - ViewX) * 7 + 1, (CursorY - ViewY) * 11, (CursorX - ViewX) * 7 + 1, (CursorY - ViewY) * 11 + 11); } private bool MapKeyword(string ident) { foreach (string d in Keywords) if (ident == d) return true; return false; } private Tuple<byte, int> Lexer(string s, ref int i) { byte color = Color_Normal; int len = 0; string ident = ""; _0: if (i >= s.Length) { color = Color_Normal; return new Tuple<byte, int>(color, len); } else if (s[i] == '/') { len++; i++; goto _Comment0; } else if (s[i] == '`') { len++; i++; goto _String; } else if ((s[i] >= 'a' && s[i] <= 'z') || (s[i] >= 'A' && s[i] <= 'Z') || s[i] == '_' || s[i] == '\'') { ident += s[i]; len++; i++; goto _Ident; } else { len++; i++; goto _1; } _1: if (i >= s.Length) { color = Color_Normal; return new Tuple<byte, int>(color, len); } else if (s[i] == '/') { color = Color_Normal; return new Tuple<byte, int>(color, len); } else if (s[i] == '`') { color = Color_Normal; return new Tuple<byte, int>(color, len); } else if ((s[i] >= 'a' && s[i] <= 'z') || (s[i] >= 'A' && s[i] <= 'Z' || s[i] == '_' || s[i] == '\'')) { color = Color_Normal; return new Tuple<byte, int>(color, len); } else { len++; i++; goto _1; } _Comment0: if (i >= s.Length) { return new Tuple<byte, int>(color, len); } else if (s[i] == '/') { len++; i++; goto _Comment1; } else if (s[i] == '`') { color = Color_Normal; return new Tuple<byte, int>(color, len); } else if ((s[i] >= 'a' && s[i] <= 'z') || (s[i] >= 'A' && s[i] <= 'Z' || s[i] == '_' || s[i] == '\'')) { color = Color_Normal; return new Tuple<byte, int>(color, len); } else { len++; i++; goto _1; } _Comment1: if (i >= s.Length) { color = Color_Comment; i++; return new Tuple<byte, int>(color, len); } else { len++; i++; goto _Comment1; }; _String: if (i >= s.Length) { color = Color_String; return new Tuple<byte, int>(color, len); } else if (s[i] == '`') { len++; i++; color = Color_String; return new Tuple<byte, int>(color, len); } else { len++; i++; goto _String; } _Ident: if (i >= s.Length) { color = MapKeyword(ident) ? Color_Keyword : Color_Normal; return new Tuple<byte, int>(color, len); } else if ((s[i] >= 'a' && s[i] <= 'z') || (s[i] >= 'A' && s[i] <= 'Z') || s[i] == '_' || s[i] == '\'' || (s[i] >= '0' && s[i] <= '9')) { ident += s[i]; len++; i++; goto _Ident; } else { color = MapKeyword(ident) ? Color_Keyword : Color_Normal; return new Tuple<byte, int>(color, len); } } private void Highlight(int lineIndex) { TextColor[lineIndex] = new List<byte>(); int i = 0; while (i < TextLines[lineIndex].Length) { Tuple<byte, int> t = Lexer(TextLines[lineIndex], ref i); for (int j = 0; j < t.Item2; j++) TextColor[lineIndex].Add(t.Item1); } } private void UserControl1_Load(object sender, EventArgs e) { View.Visible = true; HScroll.Visible = true; VScroll.Visible = true; FullWidthSymbols = new Dictionary<char, Bitmap>(); char[] chars = new char[] { '←', '∈', '÷', '≠', '≤', '≥' }; foreach (char ch in chars) { Bitmap bmp = (Bitmap)Image.FromFile(ch + ".bmp"); bmp.MakeTransparent(Color.FromArgb(unchecked((int)0xFFffffff))); FullWidthSymbols.Add(ch, bmp); } } private void CodeEditBox_Resize(object sender, EventArgs e) { try { View.Width = Width - 20; View.Height = Height - 20; HScroll.Top = View.Height; HScroll.Width = View.Width; VScroll.Left = View.Width; VScroll.Height = View.Height; VScroll.Maximum = TextLines.Count - 1; View.Refresh(); } catch (Exception) { } } private void View_Paint(object sender, PaintEventArgs e) { Render(e.Graphics); } private void CheckScroll() { if (CursorY < ViewY) VScroll.Value = CursorY; if (CursorY > ViewY + View.Height / 11 - 1) VScroll.Value = CursorY - View.Height / 11 + 1; if (CursorX < ViewX + 1) HScroll.Value = Math.Max(CursorX - 1, 0); if (CursorX > ViewX + View.Width / 7) HScroll.Value = Math.Min(HScroll.Maximum, CursorX - View.Width / 7); } |
|
protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
{ if (keyData == Keys.Tab) { int tmp = ((CursorX / 4) + 1) * 4 - CursorX; if (tmp == 0) tmp = 4; string spaceOfTab = ""; for (int i = 0; i < tmp; i++) spaceOfTab += ' '; TextLines[CursorY] = TextLines[CursorY].Substring(0, CursorX) + spaceOfTab + TextLines[CursorY].Substring(CursorX); CursorX += spaceOfTab.Length; CursorDX = 0; Highlight(CursorY); View.Refresh(); TextChanged(this, new EventArgs()); return true; } if (keyData == Keys.Up) { CursorY--; if (CursorY < 0) CursorY = 0; if (CursorX > TextLines[CursorY].Length) CursorX = TextLines[CursorY].Length; CursorDX = 0; CheckScroll(); View.Refresh(); return true; } else if (keyData == Keys.Down) { CursorY++; if (CursorY >= TextLines.Count) CursorY = TextLines.Count - 1; if (CursorX > TextLines[CursorY].Length) CursorX = TextLines[CursorY].Length; CursorDX = 0; CheckScroll(); View.Refresh(); return true; } else if (keyData == Keys.Left) { CursorX--; if (CursorX < 0) CursorX = 0; CursorDX = 0; CheckScroll(); View.Refresh(); return true; } else if (keyData == Keys.Right) { CursorX++; if (CursorX > TextLines[CursorY].Length) CursorX = TextLines[CursorY].Length; CursorDX = 0; CheckScroll(); View.Refresh(); return true; } else if (keyData == (Keys.Left | Keys.Shift)) { CursorX--; if (CursorX < 0) CursorX = 0; else CursorDX++; CheckScroll(); View.Refresh(); return true; } else if (keyData == (Keys.Right | Keys.Shift)) { CursorX++; if (CursorX > TextLines[CursorY].Length) CursorX = TextLines[CursorY].Length; else CursorDX--; CheckScroll(); View.Refresh(); return true; } else if (keyData == Keys.Home) { int tmp = 0; for (tmp = 0; tmp < TextLines[CursorY].Length; tmp++) if (TextLines[CursorY][tmp] != ' ') break; CursorX = tmp; CursorDX = 0; CheckScroll(); View.Refresh(); return true; } else if (keyData == Keys.End) { CursorX = TextLines[CursorY].Length; CursorDX = 0; CheckScroll(); View.Refresh(); return true; } else { return base.ProcessCmdKey(ref msg, keyData); } } private void CodeEditBox_KeyDown(object sender, KeyEventArgs e) { bool b = false; char ch = '\0'; if (e.Control) { if (e.KeyCode == Keys.G) { b = true; ch = '←'; } else if (e.KeyCode == Keys.T) { b = true; ch = '∈'; } else if (e.KeyCode == Keys.D) { b = true; ch = '÷'; } else if (e.KeyCode == Keys.E) { b = true; ch = '≠'; } else if (e.KeyCode == Keys.L) { b = true; ch = '≤'; } else if (e.KeyCode == Keys.K) { b = true; ch = '≥'; } else if (e.KeyCode == Keys.C) { string selText = GetSelectedText(); if (selText != "") Clipboard.SetText(selText); e.SuppressKeyPress = true; Highlight(CursorY); CheckScroll(); View.Refresh(); } else if (e.KeyCode == Keys.X) { string selText = GetSelectedText(); if (selText != "") { InsertOrReplaceText(""); Clipboard.SetText(selText); } e.SuppressKeyPress = true; Highlight(CursorY); CheckScroll(); View.Refresh(); TextChanged(this, new EventArgs()); } else if (e.KeyCode == Keys.V) { string clipBoard = Clipboard.GetText(); if (clipBoard != "") { int tmp = clipBoard.IndexOfAny(new char[] { '\r', '\n' }); string clipBoard_ = clipBoard.Substring(0, Math.Min(99, tmp >= 0 ? tmp : clipBoard.Length)).Replace('\t', ' '); InsertOrReplaceText(clipBoard_); CancelSeletion(); } e.SuppressKeyPress = true; Highlight(CursorY); CheckScroll(); View.Refresh(); TextChanged(this, new EventArgs()); } else e.SuppressKeyPress = true; } if (b) { e.SuppressKeyPress = true; if (CursorDX == 0) { TextLines[CursorY] = TextLines[CursorY].Substring(0, CursorX) + ch + TextLines[CursorY].Substring(CursorX); CursorX += 1; //CursorDX = 0; } else { if (CursorDX < 0) { TextLines[CursorY] = TextLines[CursorY].Substring(0, CursorX + CursorDX) + ch + TextLines[CursorY].Substring(CursorX); CursorX += CursorDX + 1; } else { TextLines[CursorY] = TextLines[CursorY].Substring(0, CursorX) + ch + TextLines[CursorY].Substring(CursorX + CursorDX); CursorX += 1; } CursorDX = 0; } Highlight(CursorY); CheckScroll(); View.Refresh(); TextChanged(this, new EventArgs()); } } |
|
private void CodeEditBox_KeyPress(object sender, KeyPressEventArgs e) { if (e.KeyChar == '\b') { if (CursorDX == 0) { if (CursorX == 0) { if (CursorY > 0) { CursorX = TextLines[CursorY - 1].Length; TextLines[CursorY - 1] += TextLines[CursorY]; TextLines.RemoveAt(CursorY); TextColor.RemoveAt(CursorY); CursorY -= 1; VScroll.Maximum = TextLines.Count - 1; Highlight(CursorY); } } else { TextLines[CursorY] = TextLines[CursorY].Substring(0, CursorX - 1) + TextLines[CursorY].Substring(CursorX); CursorX -= 1; Highlight(CursorY); } } else { if (CursorDX < 0) { TextLines[CursorY] = TextLines[CursorY].Substring(0, CursorX + CursorDX) + TextLines[CursorY].Substring(CursorX); CursorX += CursorDX; } else { TextLines[CursorY] = TextLines[CursorY].Substring(0, CursorX) + TextLines[CursorY].Substring(CursorX + CursorDX); } CursorDX = 0; Highlight(CursorY); } } else if (e.KeyChar == '\r') { string newLine = TextLines[CursorY].Substring(CursorX); TextLines[CursorY] = TextLines[CursorY].Substring(0, CursorX); string space = ""; for (int i = 0; i < TextLines[CursorY].Length; i++) if (TextLines[CursorY][i] == ' ') { space += ' '; continue; } else { break; } TextLines.Insert(CursorY + 1, space + newLine); TextColor.Insert(CursorY + 1, null); CursorY += 1; CursorX = space.Length; CursorDX = 0; VScroll.Maximum = TextLines.Count - 1; Highlight(CursorY - 1); Highlight(CursorY); } else { if (CursorDX == 0) { TextLines[CursorY] = TextLines[CursorY].Substring(0, CursorX) + e.KeyChar + TextLines[CursorY].Substring(CursorX); CursorX += 1; //CursorDX = 0; } else { if (CursorDX < 0) { TextLines[CursorY] = TextLines[CursorY].Substring(0, CursorX + CursorDX) + e.KeyChar + TextLines[CursorY].Substring(CursorX); CursorX += CursorDX + 1; } else { TextLines[CursorY] = TextLines[CursorY].Substring(0, CursorX) + e.KeyChar + TextLines[CursorY].Substring(CursorX + CursorDX); CursorX += 1; } CursorDX = 0; } Highlight(CursorY); } CheckScroll(); View.Refresh(); TextChanged(this, new EventArgs()); } private void View_MouseClick(object sender, MouseEventArgs e) { Focus(); CursorY = ViewY + e.Y / 11; if (CursorY >= TextLines.Count) CursorY = TextLines.Count - 1; CursorX = ViewX + e.X / 7; if (CursorX >= TextLines[CursorY].Length) CursorX = TextLines[CursorY].Length; CursorDX = 0; CheckScroll(); View.Refresh(); ViewMouseClick(this, new EventArgs()); } private void VScroll_ValueChanged(object sender, EventArgs e) { ViewY = VScroll.Value; View.Refresh(); } private void HScroll_ValueChanged(object sender, EventArgs e) { ViewX = HScroll.Value; View.Refresh(); } private void VScroll_KeyDown(object sender, KeyEventArgs e) { e.Handled = true; //Focus(); } private void HScroll_KeyDown(object sender, KeyEventArgs e) { e.Handled = true; //Focus(); } private void HScroll_KeyUp(object sender, KeyEventArgs e) { e.Handled = true; //Focus(); } private void VScroll_KeyUp(object sender, KeyEventArgs e) { e.Handled = true; //Focus(); } } } |
|
<UserControl1.Designer.cs>
namespace CodeEditBox { partial class CodeEditBox { /// <summary> /// 必要なデザイナー変数です。 /// </summary> private System.ComponentModel.IContainer components = null; /// <summary> /// 使用中のリソースをすべてクリーンアップします。 /// </summary> /// <param name="disposing">マネージ リソースが破棄される場合 true、破棄されない場合は false です。</param> protected override void Dispose(bool disposing) { if (disposing && (components != null)) { components.Dispose(); } base.Dispose(disposing); } #region コンポーネント デザイナーで生成されたコード /// <summary> /// デザイナー サポートに必要なメソッドです。このメソッドの内容を /// コード エディターで変更しないでください。 /// </summary> private void InitializeComponent() { this.HScroll = new System.Windows.Forms.HScrollBar(); this.VScroll = new System.Windows.Forms.VScrollBar(); this.View = new System.Windows.Forms.PictureBox(); ((System.ComponentModel.ISupportInitialize)(this.View)).BeginInit(); this.SuspendLayout(); // // HScroll // this.HScroll.LargeChange = 1; this.HScroll.Location = new System.Drawing.Point(1, 193); this.HScroll.Maximum = 999; this.HScroll.Name = "HScroll"; this.HScroll.Size = new System.Drawing.Size(194, 20); this.HScroll.TabIndex = 0; this.HScroll.ValueChanged += new System.EventHandler(this.HScroll_ValueChanged); this.HScroll.KeyDown += new System.Windows.Forms.KeyEventHandler(this.HScroll_KeyDown); this.HScroll.KeyUp += new System.Windows.Forms.KeyEventHandler(this.HScroll_KeyUp); // // VScroll // this.VScroll.LargeChange = 1; this.VScroll.Location = new System.Drawing.Point(194, 0); this.VScroll.Name = "VScroll"; this.VScroll.Size = new System.Drawing.Size(20, 195); this.VScroll.TabIndex = 1; this.VScroll.ValueChanged += new System.EventHandler(this.VScroll_ValueChanged); this.VScroll.KeyDown += new System.Windows.Forms.KeyEventHandler(this.VScroll_KeyDown); this.VScroll.KeyUp += new System.Windows.Forms.KeyEventHandler(this.VScroll_KeyUp); // // View // this.View.BackColor = System.Drawing.Color.White; this.View.Location = new System.Drawing.Point(0, 0); this.View.Margin = new System.Windows.Forms.Padding(0); this.View.Name = "View"; this.View.Size = new System.Drawing.Size(194, 195); this.View.TabIndex = 2; this.View.TabStop = false; this.View.Paint += new System.Windows.Forms.PaintEventHandler(this.View_Paint); this.View.MouseClick += new System.Windows.Forms.MouseEventHandler(this.View_MouseClick); // // CodeEditBox // this.AutoScaleDimensions = new System.Drawing.SizeF(9F, 18F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; this.Controls.Add(this.VScroll); this.Controls.Add(this.HScroll); this.Controls.Add(this.View); this.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4); this.Name = "CodeEditBox"; this.Size = new System.Drawing.Size(225, 225); this.Load += new System.EventHandler(this.UserControl1_Load); this.KeyDown += new System.Windows.Forms.KeyEventHandler(this.CodeEditBox_KeyDown); this.KeyPress += new System.Windows.Forms.KeyPressEventHandler(this.CodeEditBox_KeyPress); this.Resize += new System.EventHandler(this.CodeEditBox_Resize); ((System.ComponentModel.ISupportInitialize)(this.View)).EndInit(); this.ResumeLayout(false); } #endregion private System.Windows.Forms.HScrollBar HScroll; private System.Windows.Forms.VScrollBar VScroll; private System.Windows.Forms.PictureBox View; } } |