简体   繁体   中英

How do I only repaint a special area?

My English skill is poor because I'm not a native speaker.

I have written an editor that has a visual effect like Highlight. The editor has DrawingControl for representing a visual effect as the following code.

public class HighlightTextBox : TextBox
{
    private DrawingControl renderCanvas;
}

public class DrawingControl : FrameworkElement
{
    private VisualCollection visuals;
    private DrawingVisual visual;

    public DrawingControl()
    {
        visual = new DrawingVisual();
        visuals = new VisualCollection(this);
        visuals.Add(visual);
    }

    public DrawingContext GetContext()
    {
        return visual.RenderOpen();
    }

    protected override int VisualChildrenCount
    {
        get { return visuals.Count; }
    }

    protected override Visual GetVisualChild(int index)
    {
        if (index < 0 || index >= visuals.Count)
            throw new ArgumentOutOfRangeException();
        return visuals[index];
    }
}

If a user input a character on the editor then the TextChanged event is called. And after that, the OnRender function is called by calling InvalidateVisual function.

TextChanged(s,e)
{
    InvalidateVisual();
}

Then all text is drawn that has a visual effect by using DrawingContext in the DrawingControl.

protected override void OnRender(DrawingContext drawingContext)
{
    if (this.bSingleLineChanged)
    {
        this.SingleLineChangedRender(drawingContext);
        this.bSingleLineChanged = false;
        return;
    }
    else
        this.AllRender(drawingContext);
}

private void AllRender(DrawingContext drawingContext)
{
    // Calculate drawing position, texts, etc...

    var dc = this.renderCanvas.GetContext();

    // Here draw texts

    dc.Close();
    base.OnRender(drawingContext);
}

As a result, drawing process success when all text is repainted but the way take a lot of time. To shorten a drawing time, I tried to repaint only an updated part. The part drawing process is defined in the SingleLineChangedRender function. Also the logic of the function alike with an AllRender function.

Now I would explain a problem. I calculate an updated part and have written logic in the SingleLineChangedRender function. But when is called a GetContext function in the SingleLineChangedRender function all drawn context is erased.

private void SingleLineChangedRender(DrawingContext drawingContext)
{
    // I think that here all drawn contexts are erased.
    var dc = this.renderCanvas.GetContext();

    // Here draw texts

    dc.Close();    
    base.OnRender(drawingContext);
}

I want to repaint only an updated part but I can't do it because all contexts is erased when the GetContext function is called.

I would like to seek your advice to solve this problem.

Thank you for reading.

I follow your advice and I solved this problem by updating DrawingControl class.

I updated the TextViewer class as a container of DrawingContext.

As a result, the class has formed the following.

public class TextViewer : FrameworkElement
{
    // For highlighting of the selected line.
    private DrawingVisual selectionLineAppearance = new DrawingVisual();

    // For highlighting tokens of the lines.
    private VisualCollection lines;

    protected override int VisualChildrenCount
    {
        // selectionLineAppearance + lines
        get { return 1+lines.Count; }
    }

    protected override Visual GetVisualChild(int index)
    {
        if (index < 0 || index >= VisualChildrenCount)
            throw new ArgumentOutOfRangeException();

        if (index == 0) return this.selectionLineAppearance;
        return lines[index-1];
    }

    // logices
    ...

}

Now, Editor can repaint only an updated part. Addition can paint the appearance of the selected line.

Thank you for your advice.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM