public void PutChar(char ch, Brush foregroundBrush, Brush backgroundBrush) { if (ch == '\n') { this.cursorLine += 1; this.cursorColumn = 0; } else { // First, see if we've already inserted something at this position. // If so, delete the old visuals. var cursorPos = Tuple.Create(this.cursorColumn, this.cursorLine); if (this.visualPairs.ContainsKey(cursorPos)) { var visualPair = this.visualPairs[cursorPos]; this.visuals.Remove(visualPair.Background); this.visuals.Remove(visualPair.Character); this.visualPairs.Remove(cursorPos); } var backgroundVisual = new DrawingVisual(); var backgroundContext = backgroundVisual.RenderOpen(); var x = fontCharSize.Width * cursorColumn; var y = fontCharSize.Height * cursorLine; var backgroundRect = new Rect( Math.Floor(x), Math.Floor(y), Math.Ceiling(fontCharSize.Width + 0.5), Math.Ceiling(fontCharSize.Height)); backgroundContext.DrawRectangle(backgroundBrush, null, backgroundRect); backgroundContext.Close(); this.visuals.Insert(0, backgroundVisual); var textVisual = new DrawingVisual(); var textContext = textVisual.RenderOpen(); textContext.DrawText( new FormattedText( ch.ToString(CultureInfo.InvariantCulture), CultureInfo.InstalledUICulture, FlowDirection.LeftToRight, GetTypeface(), this.fontSize, foregroundBrush, new NumberSubstitution(NumberCultureSource.User, CultureInfo.InstalledUICulture, NumberSubstitutionMethod.AsCulture), TextFormattingMode.Display), new Point(x, y)); textContext.Close(); this.visuals.Add(textVisual); var newVisualPair = new VisualPair(backgroundVisual, textVisual); this.visualPairs.Add(cursorPos, newVisualPair); this.cursorColumn += 1; } }