RichTextBox 的 RTF 內容記錄位置屬性。設定第一個字元顏色後,Clear() 或 Text = "" 會清除樣式,重新設定文字時顏色恢復預設黑色。
richTextBox1.Text = "123";
richTextBox1.Select(0, 1);
richTextBox1.SelectionColor = Color.Red;
richTextBox1.Clear(); // 或 Text = ""
richTextBox1.Text = "abc"; // 顏色為黑色
richTextBox1.Text = "efg"; // 顏色為黑色
public partial class RichTextBoxForm : Form
{
public RichTextBoxForm()
{
InitializeComponent();
}
private void tSql_TextChanged(object sender, EventArgs e)
{
int index = this.tSql.SelectionStart; // 記錄游標位置
this.tSql.SelectAll();
this.tSql.SelectionColor = Color.Black; // 重置全部為黑色
string[] keystr = { "select ", "from ", "where ", " and ", " or ", " order ", " by ", " desc ",
" when ", " case ", " then ", " end ", " on ", " in ", " is ", " else ", " left ", " join ", " not ", " null " };
for (int i = 0; i < keystr.Length; i++)
HighlightKeyword(keystr[i], this.tSql.Text);
this.tSql.Select(index, 0); // 還原游標位置
this.tSql.SelectionColor = Color.Black;
}
public int HighlightKeyword(string keyword, string text)
{
int cnt = 0;
int M = keyword.Length;
int N = text.Length;
char[] ss = text.ToCharArray(), pp = keyword.ToCharArray();
if (M > N) return 0;
for (int i = 0; i <= N - M; i++)
{
int j;
for (j = 0; j < M; j++)
if (ss[i + j] != pp[j]) break;
if (j == M)
{
this.tSql.Select(i, M);
this.tSql.SelectionColor = Color.Blue;
cnt++;
}
}
return cnt;
}
}
WM_SETREDRAW 訊息鎖定更新:[DllImport("user32.dll")]
private static extern int SendMessage(IntPtr hwnd, int wMsg, int wParam, IntPtr lParam);
private const int WM_SETREDRAW = 0x0B;
private void BeginPaint()
{
SendMessage(richTextBox.Handle, WM_SETREDRAW, 0, IntPtr.Zero);
}
private void EndPaint()
{
SendMessage(richTextBox.Handle, WM_SETREDRAW, 1, IntPtr.Zero);
richTextBox.Refresh();
}
// 使用範例
private void HighlightAll()
{
BeginPaint();
try
{
// 大量 Select/SelectionColor 操作
}
finally
{
EndPaint();
}
}
TextChanged 事件的 e.Changes(需自行追蹤)。Rtf 屬性,避免大量 Select 呼叫。| 問題 | 原因 | 解決 |
|---|---|---|
| 高亮後游標跳到開頭 | SelectAll/Select 改變選取範圍 | 記錄/還原 SelectionStart |
| 輸入時畫面閃爍 | 頻繁觸發重繪 | WM_SETREDRAW 暫停重繪 |
| 大文件卡頓 | O(n²) 字元比對 + 大量 Select | 增量解析、ScintillaNET、RTF 批次 |
| 中文關鍵字誤判 | 逐字元比對不分詞 | 使用 Regex \b 邊界或分詞器 |