C#编写代码编辑器问题

时间:2011-02-18 02:36:37

标签: c# richtextbox

所以我正在为我喜欢的语言编写一个简单的代码编辑器。我的语法hilighting非常好。 问题是,如果我在我已经写过的文本之前回去,它会把整个过程搞砸到指针上方。 这是我的代码,我很抱歉发布了这么多:

public partial class Form1 : Form
{
    public string MainFontName = "Courier New";
    public int MainFontSize = 12;
    public Color MainFontColor = Color.Black;

    [DllImport("user32.dll")] // import lockwindow to remove flashing
    public static extern bool LockWindowUpdate(IntPtr hWndLock);


    public Regex codeFunctions = new Regex("draw_line|draw_rectangle|draw_circle");
    public Regex codeKeywords = new Regex("and|for|while|repeat|or|xor|exit|break|case|switch|if|then|with|true|false");

    public Form1()
    {
        InitializeComponent();

        CodeInput.Font = new Font(MainFontName, MainFontSize, FontStyle.Regular);
    }

    private void CodeInput_TextChanged(object sender, EventArgs e)
    {
        CodeInput.Font = new Font(MainFontName, MainFontSize, FontStyle.Regular);
        try
        {
            LockWindowUpdate(CodeInput.Handle);

            int selPos = CodeInput.SelectionStart;

            CodeInput.Select(0, CodeInput.TextLength);
            CodeInput.SelectionFont = new Font(MainFontName, MainFontSize, FontStyle.Regular);
            CodeInput.SelectionColor = Color.Black;
            CodeInput.SelectionLength = 0;
            CodeInput.SelectionStart = selPos;

            //Match the functions
            foreach (Match keyWordMatch in codeFunctions.Matches(CodeInput.Text))
            {

                CodeInput.Select(keyWordMatch.Index, keyWordMatch.Length);
                CodeInput.SelectionColor = Color.Red;

                CodeInput.SelectionStart = selPos;
                CodeInput.SelectionColor = MainFontColor;

                CodeInput.SelectionLength = 0;
            }
            // Match the keywords
            foreach (Match keyWordMatch in codeKeywords.Matches(CodeInput.Text))
            {

                Font oFont = new Font(MainFontName, MainFontSize, FontStyle.Bold);
                Font nFont = new Font(MainFontName, MainFontSize, FontStyle.Regular);

                CodeInput.Select(keyWordMatch.Index, keyWordMatch.Length);
                CodeInput.SelectionColor = Color.Blue;
                CodeInput.SelectionFont = oFont;

                CodeInput.SelectionStart = selPos;
                CodeInput.SelectionColor = MainFontColor;
                CodeInput.SelectionFont = nFont;

                CodeInput.SelectionLength = 0;
            }
        }
        finally
        {
            LockWindowUpdate(IntPtr.Zero);
        }
    }
}

感谢您的帮助。

1 个答案:

答案 0 :(得分:0)

你几乎走在正确的轨道上但是尝试阻止WM_PAINT而不是使用API​​调用,我已经处理了这种类型的项目并成功实现了语法高亮,其原始源代码如下;

///RadonCodeEditor is the name of Project
    /// <summary>
    /// Gets or sets a value whether RadonTextEditor should repaint itself.
    /// </summary>
    public bool Repaint = true;
cKeyword=Color.Blue;
cComment=Color.Green;

    /// <summary>
    /// A Windows generated message send to a control that needs repainting.
    /// </summary>
    const short WM_PAINT = 0x00f;

    /// <summary>
    /// Contains creation data to call RadonTextEditor.
    /// </summary>
    public RadonTextEditor()
    {
        SetStyle(ControlStyles.OptimizedDoubleBuffer, true);//Reduces flickering.
    }

    /// <summary>
    /// Overrides default WndProc and handles WM_PAINT message to remove flickering.
    /// </summary>
    /// <param name="m">The message in message queue.</param>
    protected override void WndProc(ref Message m)
    {
        if (m.Msg == WM_PAINT)//If the message in the message queue is WM_PAINT.
        {
            switch (Repaint)
            {
                case true://When we want RadonTextEditor to repaint.
                    base.WndProc(ref m);
                    break;

                case false://When we don't want RadonTextEditor to repaint.
                    m.Result = IntPtr.Zero;
                    break;
            }
        }
        else//If the message in the message queue is anything else but not WM_PAINT.
        {
            base.WndProc(ref m);
        }
    }
//Import namespace System.Text.RegularExpressions
 /// <summary>
    /// Checks the input text for any contained comments using a defined Regular Expression.
    /// </summary>
    /// <param name="Text">The text to check.</param>
    /// <param name="FirstCharIndex">The first character index of current line.</param>
    /// <param name="CaretPosition">The position of caret.</param>
    /// <param name="rtb">The handle to RichTextBox for highlighting.</param>
    /// <returns>If the input text contains any text the return value is true otherwise false.</returns>
    public void IsComment(string Text, int FirstCharIndex, int CaretPosition, RichTextBox rtb)
    {
        rComment = new Regex(@"\/\/.*$", RegexOptions.Compiled);
        MatchCollection Matches = rComment.Matches(Text);
        foreach (Match match in Matches)
        {
            rtb.Select(match.Index + FirstCharIndex, match.Length);
            rtb.SelectionColor = cComment;
            rtb.DeselectAll();
            rtb.SelectionStart = CaretPosition;

        }
        rMultiComment = new Regex(@"/\*.*?\*/", RegexOptions.Multiline);
        MatchCollection Matches2 = rMultiComment.Matches(Text);
        foreach (Match match2 in Matches2)
        {
            rtb.Select(match2.Index + FirstCharIndex, match2.Length);
            rtb.SelectionColor = cComment;
            rtb.DeselectAll();
            rtb.SelectionStart = CaretPosition;
        }
    }

    /// <summary>
    /// Checks the input text for any contained keywords using a defined Regular Expression.
    /// </summary>
    /// <param name="Text">The text to check.</param>
    /// <param name="FirstCharIndex">The first character index of current line.</param>
    /// <param name="CaretPosition">The position of caret.</param>
    /// <param name="rtb">The handle to RichTextBox for highlighting.</param>
    /// <returns>If the input text contains any text the return value is true otherwise false.</returns>
    public void IsKeyword(string Text, int FirstCharIndex, int CaretPosition, RichTextBox rtb)
    {
        rKeyword = new Regex(@:\bint\b|\bdouble\b|\bstring\b", RegexOptions.Compiled);
        MatchCollection Matches = rKeyword.Matches(Text);
        foreach (Match match in Matches)
        {
            rtb.Select(match.Index + FirstCharIndex, match.Length);
            rtb.SelectionColor = cKeyword;
            rtb.DeselectAll();
            rtb.SelectionStart = CaretPosition;
        }
    }

就是这样,在TextChange事件处理程序中调用两个函数并将所需的参数传递给函数,如注释所述(我知道它有点乱,因为我直接粘贴了我所拥有的项目的源代码。)如果还有什么事情发生的话错了,我很乐意帮助你。