How to double buffer a RichTextBox in c#? - c#

Probably not double buffering but I'm trying to make a highlighter (pure amusement) using a RichTextBox. The problem I have is that, when there are a lot of highlighted words, programmer-made flickering appear and even see the textbox scroll.
I don't think that RichTextBox has DoubleBuffered property, and even if it had, it wouldn't word, the flickering is my fault.

int pos = myTextBox.SelectionStart;
RichTextBox buffer = new RichTextBox();
buffer.Rtf = myRichTextBox.Rtf;
//Do whatever you wanna do in buffer
myTextBox.Rtf = buffer.Rtf;
myTextBox.SelectionStart = pos;
myTextBox.SelectionLength = 0;
Tho, I still have a problem because, no matter what I do, myTextBox.ZoomFactor seems to be deleted.

Just use LockWindowUpdate on your RichTextBox before changing the color.

Related

DrawString and TextBox same rendering

Inside OnPaint of a form I am rendering some text on top of an image. For that I call Graphics.DrawString with word wrapping enabled. In order to be able to edit the text I occasionally show (and hide again after editing) an additional TextBox occupying the same rectangle as my hand drawn text and also with word wrapping enabled.
My idea was that the TextBox ought to render the text exactly like the DrawString command. However there appear to be small deviations of text position (and probably text size?). Moreover these deviations seem to vary depending on the chosen font so it is impossible to tune them manually.
While the deviations are not so terrible as such, they lead to irritating consequences when it comes to the automatic word wrapping. For example in the TextBox a word might appear on the second line while it might appear on the first line when rendered with DrawString after accepting the edit. Most of the time it works but for some rectangle sizes it fails.
If transparency had been available for TextBox, I would have used it instead of rendering text manually, but none of the solutions I found has worked.
Is there any hope that I can find out what settings synchronize the rendering between DrawString and TextBox ? Or is the latter an undocumented implementation detail of the win32 textbox?
The essentials of my code (g is a Graphics object from the paint event args):
stringFormat = new StringFormat(StringFormat.GenericDefault);
stringFormat.FormatFlags = StringFormatFlags.NoWrap | StringFormatFlags.NoClip;
stringFormat.Trimming = StringTrimming.None;
stringFormatAutomaticLinebreak = new StringFormat(StringFormat.GenericDefault);
stringFormatAutomaticLinebreak.FormatFlags = StringFormatFlags.NoClip;
stringFormatAutomaticLinebreak.Trimming = StringTrimming.None;
if (Data.IsAutomaticLinebreak)
{
Rectangle boundingRectangle = new Rectangle(Data.TextPosition.X, Data.TextPosition.Y,
Data.WindowSize.Width-Data.TextPosition.X-1, Data.WindowSize.Height-Data.TextPosition.Y-1);
g.DrawString(Data.Text, Data.TextFont, Data.TextBrush, boundingRectangle, stringFormatAutomaticLinebreak);
}
else
{
g.DrawString(Data.Text, Data.TextFont, Data.TextBrush, Data.TextPosition.X, Data.TextPosition.Y, stringFormat);
}
and
surrogateTextBox = new TextBox();
surrogateTextBox.BorderStyle = BorderStyle.None;
surrogateTextBox.Multiline = true;
surrogateTextBox.Text = Data.Text;
surrogateTextBox.Font = Data.TextFont;
surrogateTextBox.Location = new Point(Data.TextPosition.X,Data.TextPosition.Y);
surrogateTextBox.Size = new Size(Data.WindowSize.Width-Data.TextPosition.X-1, Data.WindowSize.Height-Data.TextPosition.Y-1);
surrogateTextBox.WordWrap = Data.IsAutomaticLinebreak;
Controls.Add(surrogateTextBox);

Detecting presence of "Drawn text" under the mouse?

and thanks for taking a peek at my conundrum.
I am trying to write a series of strings to an image as overlays, then later be able to come back and move, or delete one of them selectively using WPF framework...
I've been looking into the FindVisualChildren function, but for the moment cant make heads or tails of how to detect the proximity to the mouse (for selectivity), or actually detect one of my created strings (Perhaps I should be making them dynamic 'Label' elements...????)
Insomnia sucks, and my brains are turning to mush.
TIA for any advice!
Okay, sorry for the lack of sample code, been a long night... well two nights actually (See earlier comment about insomnia)
public void WriteTextToImage(Point position)
{
ImageSource bitmapSource = imgFrame.Source;
var vis = new DrawingVisual();
using (DrawingContext drawingContext = vis.RenderOpen())
{
// Set the pen color... Why is this called a brush if it's for
// writing? perhaps I should overload it and call it crayon?
SolidColorBrush brush = new SolidColorBrush((Color)cpColor.SelectedColor);
drawingContext.DrawImage(bitmapSource, new Rect(0, 0, imgFrame.Source.Width, imgFrame.Source.Height));
//Write some pretty words, (actually print some general stuff)
drawingContext.DrawText(new FormattedText(tbCurrentLabel.Text, CultureInfo.InvariantCulture, FlowDirection.LeftToRight, new Typeface("Arial"), slFontSize.Value, brush),position);
}
//Slap this puppy to the screen
var image = new DrawingImage(vis.Drawing);
//Iterate the label text to the next digit or value
IterateLabel();
}
Basically what will happen is the user will click the screen in several places to make marks on the image for printing, but I want to include support to move those marks, and delete them as needed.
I hope this explains what I am trying to accomplish a little better.
Thanks again!
Excellent! thanks NineBerry, I figured it was going to be something like that. I was originally thinking a label, but the textblock worked perfectly.
Here's the updated code showing how I am getting it done now.
public void WriteTextToImage(Point position)
{
SolidColorBrush brush = new SolidColorBrush((Color)cpColor.SelectedColor);
//Get something to write on (not an old receipt...)
TextBlock textBlock = new TextBlock();
//Say something useful... well something atleast...
textBlock.Text = tbCurrentLabel.Text;
textBlock.FontSize = slFontSize.Value;
textBlock.Foreground = brush;
Canvas.SetLeft(textBlock, position.X);
Canvas.SetTop(textBlock, position.Y);
canvas.Children.Add(textBlock);
//Need to update the canvas, was not seeing children before doing this.
canvas.UpdateLayout();
//Iterate the label text
IterateLabel();
}`

Richtextbox - scroll only if scrollbar is at bottom

I have a RichTextBox and it scrolls with every AppendText, but it shall only scroll if the scrollbar is at bottom. I would like for example to easily select and copy something from the middle of the richtextbox while text is appended to the RichTextBox. Tried many solutions, but nothing really worked correct. Is this even possible?
It depends how you are Appending, but you can tell it to focus back to where the selection (or just cursor) is after appending.
eg (untested, assuming WinForms):
int selStart = rtb.SelectionStart
int selLength = rtb.SelectionLength
rtb.AppendText("test")
rtb.SelectionStart = selStart
rtb.SelectionLength = selLength
That will always push the selection back to where it was before the append - but won't scroll down if it was at the bottom previously. To me, that seems like expected behaviour.

Making TableLayoutPanel Act Like An HTML Table (Cells That Resize Automatically Around Text)

I'm trying to build a TableLayoutPanel on a WinForm and want it to behave exactly like a plain old HTML table.
One requirement is that this table needs to be built programmatically. This is what I have so far:
foreach (var RowLinq in ResultLinq)
{
RichTextBox RT = new RichTextBox();
RT.BorderStyle = BorderStyle.None;
RT.Text = RowLinq.Result.ResultName;
RT.Dock = DockStyle.Fill;
TableLayoutPanel.RowCount++;
TableLayoutPanel.RowStyles.Add(new RowStyle(System.Windows.Forms.SizeType.AutoSize));
TableLayoutPanel.Controls.Add(rt1, 0, tableLayoutPanel5.RowCount - 1);
}
So this builds a row for each row in my Linq result. This works pretty well except for one thing: the height doesn't adjust at all and is completely fixed. I need the height to grow and shrink depending on the height of the text inside each cell.
I need your help with this one big time, thanks Stack-o
Set its AutoSize property to True.

Windows Forms RichTextBox cursor position

I have a C# Windows Forms program that has a RichTextBox control. Whenever the text inside the box is changed (other than typing that change), the cursor goes back to the beginning.
In other words, when the text in the RichTextBox is changed by using the Text property, it makes the cursor jump back.
How can I keep the cursor in the same position or move it along with the edited text?
Thanks
You can store the cursor position before making the change, and then restore it afterwards:
int i = richTextBox1.SelectionStart;
richTextBox1.Text += "foo";
richTextBox1.SelectionStart = i;
You might also want to do the same with SelectionLength if you don't want to remove the highlight. Note that this might cause strange behaviour if the inserted text is inside the selection. Then you will need to extend the selection to include the length of the inserted text.
Be careful, if someone refreshes or changes totally the RichTextBox content, the focus method must be invoqued previously in order to move the caret:
richTextBox1.Focus();
int i = richTextBox1.SelectionStart;
richTextBox1.Text = strPreviousBuffer;
richTextBox1.SelectionStart = i;
here's a smaller one, that has the same effect. this.richTextBox1.Select(this.richTextBox1.Text.Length, 0);
That marks 0 chars at the end of the text and sets the cursor to end

Categories