开发者

C# writing a code editor issues

So I'm writing a simple code editor for a language I like. I have syntax hilighting going very well. The problem is that if I go back before text I have already written, it screws the whole hilighting up for everything past my pointer. Here is my code, my apologies for posting so much:

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);
        }
    }
}

Thanks for the help.


You are almost on the right track but try blocking WM_PAINT instead of using API calls,i have worked on this type of project and implemented syntax highlighting successfully,its original source code is as below;

///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;
        }
    }

That's it,call both functions in TextChange event handler and pass required arguments to functions as described by comments(I know it's a bit messy because i have directly pasted the source code from the project that i have.)If still anything goes wrong i'll be glad to help you.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜