locked
RichTextBox Syntax Highlight RRS feed

  • Question

  • Hi,

    I'd like to make a simple application based on RichTextBox which while writing should highlight (bold) words IF and THEN (to start with) and still keep the cursor at its actual position, e.i. standard syntax hightlight editor.

    I use ContentChanged event. My approach is to find the beginning of the current line and then to go back to the end of it. While on the move, I compare every token (set of characters delimited by space, empty string, tab and end of line) to IF and THEN and if I get true, the token is changed to bold else it's changed to normal. Before traversing throught the line, I save current selection start as well as end. After finishing, I try to restore the position. And that's where I keep having a problem. It doesn't behave the way I would expect. While debugging, I can see that suddenly the contents of the variables with stored beginning or the end changes.  

    Would any of you know how to implement it or where I'm taking a wrong assumption or something? Thanks a lot. I spent a few days on this and I am at the point where I consider buying 3rd party component.

    Pavel

    XAML:

    <UserControl x:Class="ScriptEdit.MainPage"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        mc:Ignorable="d"
        d:DesignHeight="330" d:DesignWidth="400">

        <Grid x:Name="LayoutRoot" Background="White" Height="330" Width="400">
            <Grid.RowDefinitions>
                <RowDefinition/>
                <RowDefinition Height="20"/>
            </Grid.RowDefinitions>
            <RichTextBox Name="editBox" ContentChanged="editBox_ContentChanged"
                         VerticalAlignment="Stretch" HorizontalAlignment="Stretch" />
            <TextBlock Grid.Row="1" Name="status" VerticalAlignment="Stretch" HorizontalAlignment="Stretch" />
        </Grid>
    </UserControl>

    cs file:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Net;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Documents;
    using System.Windows.Input;
    using System.Windows.Media;
    using System.Windows.Media.Animation;
    using System.Windows.Shapes;
    using System.Text.RegularExpressions;

    namespace ScriptEdit
    {
        public partial class MainPage : UserControl
        {

            public MainPage()
            {
                InitializeComponent();
            }

            private void editBox_ContentChanged(object sender, ContentChangedEventArgs e)
            {
                editBox.ContentChanged -= editBox_ContentChanged;
                HighlightLine();
                editBox.ContentChanged += new ContentChangedEventHandler(editBox_ContentChanged);
            }

            private void HighlightLine()
            {
              
                TextPointer start = editBox.Selection.Start;
                TextPointer origStart = editBox.Selection.Start,
                    origEnd = editBox.Selection.End;

                if (start == null)
                    return;
                // find beginning of the current line
                string currentChar = GetCurrentChar(editBox, start, LogicalDirection.Backward);
                while (currentChar != "\n" && currentChar != null && currentChar != "")
                {
                    start = start.GetNextInsertionPosition(LogicalDirection.Backward);
                    currentChar = GetCurrentChar(editBox, start, LogicalDirection.Backward);
                }
               
                TextPointer end = start;
                if (end == null)
                    return;
                currentChar = GetCurrentChar(editBox, end, LogicalDirection.Forward);
                string token = "";
                // move towards the end of the current line
                while (currentChar != null)
                {
                    if (currentChar == " " || currentChar == "\t" || currentChar == "\n" || currentChar == "")
                    {
                        if (token == "IF" || token == "THEN")
                        {
                            editBox.Selection.Select(end, start);
                            editBox.Selection.ApplyPropertyValue(TextElement.FontWeightProperty, FontWeights.Bold);
                        }
                        else
                        {
                            editBox.Selection.Select(end, start);
                            editBox.Selection.ApplyPropertyValue(TextElement.FontWeightProperty, FontWeights.Normal);
                        }
                        token = "";
                        start = end;
                    }
                    else
                    {
                        token += currentChar;

                    }
                    if (currentChar == "\n" || currentChar == "") break;
                    end = end.GetNextInsertionPosition(LogicalDirection.Forward);
                    currentChar = GetCurrentChar(editBox, end, LogicalDirection.Forward);
                }
                editBox.Selection.Select(origStart, origEnd);
               
            }

            private string GetCurrentChar(RichTextBox RTB, TextPointer pointer, LogicalDirection direction)
            {
                TextPointer nextPointer = pointer.GetNextInsertionPosition(direction);

                if (nextPointer != null)
                {
                    RTB.Selection.Select(pointer, nextPointer);
                    if (RTB.Selection.Text.Length != 0)
                        return RTB.Selection.Text[0].ToString();
                }
                return "";
            }

        }
    }

    Friday, August 6, 2010 11:04 AM

Answers


  •    I remember that you can not change the Selection of a richtextbox.

       THe only api is RTB.Selection.Select() which takes two Texpointer instance.

       Thta class's constructor is internal

       You better not change the selection place in the first place.

       You can see if the blocks property can do what you need

    Tuesday, August 10, 2010 1:37 AM