一、RichTextBox基本設定
二、實作文法高亮
三、關鍵字提示
四、實作行号
就簡單快速得開發文本編輯器TextBox 最為簡單,大家用得也多,缺點是無法實作複雜的操作。RichTextBox雖然是則功能比它強大很多。
這裡要實作以下功能的編輯器:
1、實作文法高亮;
2、關鍵字提示;
3、行号。
顯然TextBox 無法完成我們的任務,雖然都派生自TextBoxBase,但就控制力而言RichTextBox比它優秀很多。這裡選用RichTextBox嘗試開發。
注:以下隻讨論簡單開發,不考慮複雜的關鍵字查找機制。
一、RichTextBox基本設定
這裡先建立一個工程,建立窗體Form1。
可以簡單添加RichTextBox控件,可以在Form1_Load中建立。代碼如下:
複制
儲存
this .WindowState = System.Windows.Forms.FormWindowState.Maximized;
RichTextBox rich = new RichTextBox();
rich.Multiline = true ;
rich.Height = this .Height - 100;
rich.Width = this .Width - 100;
rich.Left = 40;
rich.Top = 40;
rich.WordWrap = true ;
rich.Text = "12345678" ;
rich.ScrollBars = RichTextBoxScrollBars.ForcedVertical;
this .Controls.Add(rich);
這樣就建立了簡單的RichTextBox,寬度和高度都設定了。沒有做Form1窗體縮放的處理。
二、實作文法高亮
在RichTextBox裡實作文法高亮還是非常簡單的。可以使用
複制
儲存
rich.Select(0, 1);
rich.SelectionFont = new Font( "宋體" , 12, (FontStyle.Regular));
rich.SelectionColor = Color.Blue;
意思是,先選擇第一個字母,按上面的設定,選擇到了數字‘1’,然後設定這個字的字型大小,再設定字的顔色。
如果對關鍵字進行處理(這裡隻處理光标向後流動的情況)
首先添加輸入事件
複制
儲存
rich.KeyDown += new KeyEventHandler(rich_KeyDown); //這一行添加到Form1_Load中 void rich_KeyDown( object sender, KeyEventArgs e)
{
//throw new Exception("The method or operation is not implemented."); }
建立關鍵字
複制
儲存
public static List< string > AllClass()
{
List< string > list = new List< string >();
list.Add( "function" );
list.Add( "return" );
list.Add( "class" );
list.Add( "new" );
list.Add( "extends" );
list.Add( "var" );
return list;
}
當KeyDown事件發生時,向前查找
複制
儲存
//傳回搜尋字元 public static string GetLastWord( string str, int i)
{
string x = str;
Regex reg = new Regex( @"/s+[a-z]+/s*" , RegexOptions.RightToLeft);
x = reg.Match(x).Value;
Regex reg2 = new Regex( @"/s" );
x = reg2.Replace(x, "" );
return s;
}
複制
儲存
void rich_KeyDown( object sender, KeyEventArgs e)
{
RichTextBox rich = (RichTextBox) sender;
//throw new Exception("The method or operation is not implemented."); string s = GetLastWord(rich.Text, rich.SelectionStart);
if (AllClass().IndexOf(s) > -1)
{
MySelect(rich, rich.SelectionStart, s, Color.CadetBlue, true );
}
}
複制
儲存
//設定顔色 public static void MySelect(System.Windows.Forms.RichTextBox tb, int i, string s, Color c, bool font)
{
tb.Select(i - s.Length, s.Length);
tb.SelectionColor = c;
//是否改變字型 if (font)
tb.SelectionFont = new Font( "宋體" , 12, (FontStyle.Bold));
else
tb.SelectionFont = new Font( "宋體" , 12, (FontStyle.Regular));
//以下是把光标放到原來位置,并把光标後輸入的文字重置 tb.Select(i, 0);
tb.SelectionFont = new Font( "宋體" , 12, (FontStyle.Regular));
tb.SelectionColor = Color.Black;
}
這樣就完成了高亮工作。
三、關鍵字提示
實作關鍵字提示也是在KeyDown中實作,在提示字種搜尋GetLastWord傳回的文字,如果前半部分比對。那麼就建立ListBox控件。
複制
儲存
void tb_KeyDown( object sender, KeyEventArgs e)
{
RichTextBox tb = (RichTextBox) sender;
if ( /*條件搜尋到比對字元*/ )
{
//搜尋ListBox是否已經被建立 Control[] c = tb. Controls.Find ( "mylb" , false );
if (c.Length > 0)
((ListBox) c[0]).Dispose(); //如果被建立則釋放
ListBox lb = new ListBox();
lb.Name = "mylb" ;
lb.Items.Add( "asdasdasd" );
lb.Items.Add( "asdasdasd" );
lb.Items.Add( "asdasdasd" );
lb.Items.Add( "asdasdasd" );
lb.Items.Add( "asdasdasd" );
lb.Items.Add( "asdasdasd" );
lb.Items.Add( "asdasdasd" );
lb.Show();
lb.TabIndex = 100;
lb.Location = tb.GetPositionFromCharIndex(tb.SelectionStart);
lb.Left += 10;
tb.Controls.Add(lb);
}
}
當然,另外一面,如果建立ListBox,而又在RichTextBox 點選了滑鼠也去釋放。
複制
儲存
void rich_MouseClick( object sender, MouseEventArgs e)
{
RichTextBox tb = (RichTextBox) sender;
Control[] c = tb. Controls.Find ( "mylb" , false );
if (c.Length > 0)
((ListBox) c[0]).Dispose();
}
當然還得在Form1_Load裡注冊事件
複制
儲存
rich.MouseClick += new MouseEventHandler(rich_MouseClick);
然後設定ListBox 被選擇後用被選擇的關鍵字替換前文搜尋到的字元。
下面我們來看看實作行号。
四、實作行号
這個是RichTextBox 唯一令我遺憾的地方,居然無法實作行号問題。為什麼呢?我首先想到的是自己畫。用rich.CreateGraphics()來畫。但是,由于畫的時候發生在窗體被建立時,是以畫不成功,而被RichTextBox 本身的繪制給覆寫了。
然後我選擇了在裡面添加Label控件
複制
儲存
Label l = new Label();
l.Name = "l" ;
l.Top = 0;
l.TextAlign = ContentAlignment.TopRight;
l.Width = 40;
l.Text = "1" ;
l.Font = new Font( "宋體" , 12, (FontStyle.Regular));
l.Height = this .Height;
l.BackColor = Color.Gray;
l.BorderStyle = BorderStyle.None;
rich.Controls.Add(l);
rich.SelectionIndent = 40;
rich.SelectionIndent = 40;是把光标對齊到左邊距40的位置,防止光标被Label覆寫。
實作編号還不是太難。麻煩出在如何讓Lable能跟随RichTextBox 的滾動條滾動。不說實作的 細節,我就假設,如果滾動條向上滾,那麼Lable的Top屬性增加,反之則減少。但是,RichTextBox 居然無法對ScollBar進行監測。
根本每辦法知道滾動條滾動了多少位置,甚至都沒辦法知道滾動條滾動的方向。
嘗試去除滾動條,然後之間添加新的滾動條
複制
儲存
VScrollBar vs = new VScrollBar();
//vs.Dock = DockStyle.Right; vs.Name = "vs" ;
vs.Maximum = 0;
vs.Minimum = 0;
vs.MaximumSize = new Size(0, 0);
vs.Top = 0;
vs.Left = rich.Parent.Width - 100 - 22;
vs.Height = rich.Parent.Height - 100 - 1;
vs.Value = 0;
vs.Scroll += new ScrollEventHandler(vs_Scroll);
rich.Controls.Add(vs);
但是非常難于實作同步滾動,位置很難控制。這個就是目前遇到的RichTextBox 的最大局限性了,非常遺憾,無法開發出這個功能。