473,782 Members | 2,525 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

RichTextBox repainting artifacts

I have created a Control that extends RichTextBox to do syntax-hilighting. My
strategy is to have a timer that restarts every time a user types a key so
that it can wait until the user pauses for at least 500 milliseconds, then
perform its work. The hilighting simply goes through a list of keywords,
finding each instance in the RichTextBox, and selecting it in order to change
its color. I figured out how to remember where the cursor is and put it back
where the user left it. I even bracketed all my activity with a
SuspendLayout/ResumeLayout. But I cannot get around my problem: the RTB has
an annoying flash/scroll/jump each time my hilighting occurs (if there are
more lines in the box than the height of the box). How can I avoid this?

Here is the code basics:
=============== =============== ====
private void SyntaxHilightTe xtBox_TextChang ed(object sender, EventArgs e)
{
if (timer.Tag.Equa ls(1)) { return; }
if (timer.Enabled) { timer.Stop(); }
timer.Start(); // restart it
}

private void timer_Tick(obje ct sender, EventArgs e)
{
timer.Stop();
timer.Tag = 1; // disable TextChanged so our changes are transparent
SuspendLayout() ;
Colorize();
ResumeLayout();
timer.Tag = 0; // re-enable TextChanged
}

private void Colorize()
{
int saveCaret = CaretPosition() ;

// Restore all text to black.
// Prevents terminal hilighting from bleeding into new typing.
SelectAll();
SelectionColor = Color.Black;

ColorWords(myWo rdList);

SelectionStart = saveCaret; // restore caret
SelectionLength = 0;
}

public void ColorWords(stri ng[] text)
{
foreach (string s in text) { ColorWord(s); }
}

public void ColorWord(strin g text)
{
RichTextBoxFind s options =
(RichTextBoxFin ds.WholeWord | RichTextBoxFind s.NoHighlight);
int start = Find(text, options);
bool done = (start < 0);
while (!done)
{
SelectionStart = start;
SelectionLength = text.Length;
SelectionColor = hilightColor;
int lastStart = start;
start = Find(text, start + text.Length, options);
done = (start <= lastStart);
}
}

=============== =============== ====
Mar 20 '07 #1
8 2621
Additional note:
If I disable the auto-hilight and put it on a button, the button works great
(i.e. no annoying flash/scroll). Is this possibly because the timer tick
occurs on a different thread? I tried adding some debug lines to identify
thread differences, but if I instrumented that correctly it is on the same,
main thread. Any suggestions from this point?

Mar 27 '07 #2
Hi Michael,

I performed a test based on your sample code and did see the problem on my
side. But I don't think the problem is caused by the timer tick occurring
on a thread other than the UI thread. It is UI thread that executes the
timer's Tick event handler when the timer's Tick event occurs.

I think the reason of the problem is that you're attempting to
select/unselect the text in the RichTextBox while it gets focused, which
causes the window flash/scroll.

I suggest that you remove the timer in your project and only check the
words near the current input cursor to see if they match the key words, if
yes, select them and change their color. In this way, you needn't always
re-check ALL the text and re-hilight those key words.

The following is a sample. It requires that you add a RichTextBox control
on the form.

public partial class Form1 : Form
{
string[] myWordList = new string[] { "the", "a", "an" };
Color hilightColor = Color.Orange;

public Form2()
{
InitializeCompo nent();
this.richTextBo x1.TextChanged += new
EventHandler(ri chTextBox1_Text Changed);
}

void richTextBox1_Te xtChanged(objec t sender, EventArgs e)
{
if (this.richTextB ox1.Text.Trim() != "")
{
if (this.GetCharBe foreSelectionSt art() == 0)
{
this.ProcessNex tWord(this.rich TextBox1.Select ionStart);
}
if (this.GetCharBe foreSelectionSt art() == ' ' ||
this.GetCharBef oreSelectionSta rt() == '\n')
{
this.ProcessPre Word(this.richT extBox1.Selecti onStart);
this.ProcessNex tWord(this.rich TextBox1.Select ionStart);
}
else
{

this.ProcessCur rentWord(this.r ichTextBox1.Sel ectionStart);
}
}
}

private char GetCharBeforeSe lectionStart()
{
if (this.richTextB ox1.SelectionSt art == 0)
{
return '0';
}
else
{
return
this.richTextBo x1.Text[this.richTextBo x1.SelectionSta rt - 1];
}
}
private bool IsMatchKeyword( string text)
{
int i = 0;
for (; i < myWordList.Leng th; i++)
{
if (myWordList[i] == text)
{
break;
}
}
if (i < myWordList.Leng th)
return true;
else
return false;
}

private void ProcessCurrentW ord(int carsetIndex)
{
int wordstart = carsetIndex -1;
while ((wordstart - 1 >= 0) &&
(this.richTextB ox1.Text[wordstart - 1] != ' ' &&
this.richTextBo x1.Text[wordstart-1]!='\n'))
{
wordstart--;
}
int wordend = carsetIndex - 1;
while ((wordend + 1 < this.richTextBo x1.TextLength) &&
this.richTextBo x1.Text[wordend + 1] != ' ' &&
this.richTextBo x1.Text[wordend +1] != '\n')
{
wordend++;
}
string wordtext = this.richTextBo x1.Text.Substri ng(wordstart,
wordend - wordstart + 1);
this.richTextBo x1.SelectionSta rt = wordstart;
this.richTextBo x1.SelectionLen gth = wordend - wordstart + 1;

if (IsMatchKeyword (wordtext))
{
this.richTextBo x1.SelectionCol or = this.hilightCol or;
}
else
{
this.richTextBo x1.SelectionCol or =
this.richTextBo x1.ForeColor;
}
this.richTextBo x1.SelectionSta rt = carsetIndex;
this.richTextBo x1.SelectionLen gth = 0;
}

private void ProcessPreWord( int carsetIndex)
{
int wordend = carsetIndex -1;
while (wordend >= 0 && (this.richTextB ox1.Text[wordend] == ' '
|| this.richTextBo x1.Text[wordend] == '\n'))
{
wordend--;
}
int wordstart = wordend;
if (wordstart 0)
{
while ((wordstart - 1 >= 0) &&
this.richTextBo x1.Text[wordstart-1] != ' ' &&
this.richTextBo x1.Text[wordstart-1]!='\n')
{
wordstart--;
}
}
if (wordstart >= 0)
{
this.richTextBo x1.SelectionSta rt = wordstart;
this.richTextBo x1.SelectionLen gth = wordend - wordstart + 1;

string wordtext =
this.richTextBo x1.Text.Substri ng(wordstart, wordend - wordstart + 1);
if (IsMatchKeyword (wordtext))
{
this.richTextBo x1.SelectionCol or = this.hilightCol or;
}
else
{
this.richTextBo x1.SelectionCol or =
this.richTextBo x1.ForeColor;
}
this.richTextBo x1.SelectionSta rt = carsetIndex;
this.richTextBo x1.SelectionLen gth = 0;
}
}

private void ProcessNextWord (int carsetIndex)
{
int wordstart = carsetIndex -1;
while ((wordstart < this.richTextBo x1.TextLength) &&
(this.richTextB ox1.Text[wordstart] == ' ' ||
this.richTextBo x1.Text[wordstart]=='\n'))
{
wordstart++;
}
int wordend = wordstart;
if (wordend < this.richTextBo x1.TextLength - 1)
{
while (wordend + 1 < this.richTextBo x1.TextLength &&
this.richTextBo x1.Text[wordend +1]!= ' '&&
this.richTextBo x1.Text[wordend+1]!='\n')
{
wordend++;
}
}
if (wordstart < this.richTextBo x1.TextLength)
{
this.richTextBo x1.SelectionSta rt = wordstart;
this.richTextBo x1.SelectionLen gth = wordend - wordstart + 1;
string wordtext = this.richTextBo x1.Text.Substri ng
(wordstart,word end - wordstart +1);
if (IsMatchKeyword (wordtext))
{
this.richTextBo x1.SelectionCol or = this.hilightCol or;
}
else
{
this.richTextBo x1.SelectionCol or =
this.richTextBo x1.ForeColor;
}
this.richTextBo x1.SelectionSta rt = carsetIndex;
this.richTextBo x1.SelectionLen gth = 0;
}
}
}

Hope this helps.
If you have anything unclear, please feel free to let me know.

Sincerely,
Linda Liu
Microsoft Online Community Support

=============== =============== =============== =====
Get notification to my posts through email? Please refer to
http://msdn.microsoft.com/subscripti...ult.aspx#notif
ications.

Note: The MSDN Managed Newsgroup support offering is for non-urgent issues
where an initial response from the community or a Microsoft Support
Engineer within 1 business day is acceptable. Please note that each follow
up response may take approximately 2 business days as the support
professional working with you may need further investigation to reach the
most efficient resolution. The offering is not appropriate for situations
that require urgent, real-time or phone-based interactions or complex
project analysis and dump analysis issues. Issues of this nature are best
handled working with a dedicated Microsoft Support Engineer by contacting
Microsoft Customer Support Services (CSS) at
http://msdn.microsoft.com/subscripti...t/default.aspx.
=============== =============== =============== =====

This posting is provided "AS IS" with no warranties, and confers no rights.

Apr 13 '07 #3
While I appreciate your industriousness in providing a good bit of code, it
seems like a lot of code to workaround a simple repaint issue. Also, it will
handle typing but I do not think it could deal with cut-and-paste very well.

I do agree that it is not a thread issue and that it is related to the
selection/focus issue. So is there not a simple way to suspend the UI
activity while doing some processing? That is what I was hoping the
SuspendLayout/ResumeLayout bracketing would do, but it did not.
Apr 16 '07 #4
Hi Michael,

Thank you for your reply.

Yes, you're right that my code doesn't work well when the user pastes a
block of text into the RichTextBox.

The key point of your solution is that the RichTextBox get focused when
you're trying to select its text. So a better way solve the problem is to
make the RichTextBox lose the keyboard focus before we're trying to select
the text and restore the focus after we finish the task, based on your
original code.

To make a control lose focus, we could use the Win32API function
'SendMessage' to to send a 'WM_KILLFOCUS' message to the RichTextBox.

The following is a sample.

using System.Runtime. InteropServices ;
class API
{
[DllImport("user 32.dll")]
public static extern int SendMessage(Int Ptr hWnd,uint msg, IntPtr
wParam, IntPtr lParam);
}

uint WM_KILLFOCUS = 0x0008;
// this is your original method
void timer1_Tick(obj ect sender, EventArgs e)
{
timer1.Stop();
timer1.Tag = 1; // disable TextChanged so our changes are
transparent
// SuspendLayout() ;
API.SendMessage (this.richTextB ox1.Handle, WM_KILLFOCUS,
IntPtr.Zero, IntPtr.Zero);

Colorize();
// note that we need to get the form focused first
this.Focus();
this.richTextBo x1.Focus();

// ResumeLayout();
timer1.Tag = 0; // re-enable TextChanged
}

Please try my suggestion and let me know the result.

Sincerely,
Linda Liu
Microsoft Online Community Support

Apr 18 '07 #5
That works great--thank you!!

Just a couple followup questions (marginally related to your solution
details):

(1) I had already been using SendMessage in the same class for another
purpose with this signature:
private static extern IntPtr
SendMessage(Han dleRef hWnd, int msg, int wParam, int lParam);

That differs subtlely from the signature you provided:
public static extern int SendMessage(Int Ptr hWnd,uint msg, IntPtr
wParam, IntPtr lParam);

However, I was able to alter the arguments you provided to fit my existing
signature and it worked fine:
const int WM_KILLFOCUS = 0x0008;
HandleRef hr = new HandleRef(this, base.Handle);
SendMessage(hr, WM_KILLFOCUS, 0, 0);

My question: Is one of these SendMessage signatures more "correct" ? My
knowledge of the Win32API is very minimal.

(2) Could you provide a URL to the Win32API documentation root? In the
future when I want to tinker with a control I would like to be able to dig
through the documentation to see if there is a command to do what I might
need.

Apr 18 '07 #6
Hi Michael,

Thank you for your prompt feedback.

The parameters of the SendMessage function may differ for different Windows
message it is going to send. It is OK to use your existing signature of
SendMessage to send the WM_KILLFOCUS message.

MSDN has provided a full reference for Win32API. You may visit the
following link for it:

'Windows API'
http://msdn2.microsoft.com/en-us/library/aa383750.aspx

Hope this helps.
If you have any question, please feel free to let me know.

Sincerely,
Linda Liu
Microsoft Online Community Support

Apr 19 '07 #7
Hi Michael,

How about the problem now?

If you have anything unclear, please feel free to let me know.

Thank you for using our MSDN Managed Newsgroup Support Service!

Sincerely,
Linda Liu
Microsoft Online Community Support

Apr 23 '07 #8
As I indicated on my 4/18 post, your information at that point solved my
problem (and I marked your post with a checkmark indicating it answered the
question).
The follow-up questions were just for future reference.

Thanks again.

"Linda Liu [MSFT]" wrote:
Hi Michael,

How about the problem now?

If you have anything unclear, please feel free to let me know.

Thank you for using our MSDN Managed Newsgroup Support Service!

Sincerely,
Linda Liu
Microsoft Online Community Support

Apr 23 '07 #9

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

0
1306
by: Mike Richardson | last post by:
Hello, I am using VB.net. Is there a way to stop the screen from repainting. I would perfer to stop screen repainting for the entire application. Example when a form is loading. Stop repainting. Execute code. restore repainting. In VB 6 I called
0
3251
by: nouno | last post by:
I am trying to spell check a richtextbox. Through code (shown below) I save the contents of the richtextbox to a rtf file, open the rtf file in Word, spell check it, save it, and then load the ftf file back into the ricktextbox using loadfile. The problem is that the richtextbox seems to remain bound to the rtf file. If I make a change in the richtextbox after spell checking, the changes are successfully saved to the database but if the...
2
17380
by: JonnyT | last post by:
I searched high and low for an answer on how to auto scroll a richtextbox and now I finally have it. Since it took me a while to get a good efficient way of doing it that didn't require focus to the control or the scrolltocaret method I decided that it would be worth posting to anyone who might have similar concerns. For the record this works well in an environment where you cannot have focus going to the richtextbox....such as a chat...
5
1431
by: Jesse Aufiero | last post by:
Hello all, I have many buttons on a form and at the bottom of the form is a grid that behaves as though it is 'retractable' - at various times during the life of the app, the grid becomes taller and conceals the many buttons below it. That transition is fine. The problem is that when the grid retracts back down to the bottom portion of the form, to reveal the many buttons underneath it, the repainting is slow and ugly.
9
4878
by: James Wong | last post by:
Hi, I use the RichTextBox in my program. It will use different language in this RichTextBox (chinese and english characters), and it set the "DualFont" and use different fonts. By the way, how can I print out this content to printer easily? Thanks! James
1
1092
by: kjensen | last post by:
Hi I'm working on a simple FTP server implementation but I've run into a strange problem. I use this function to recieve: def stor(self): f = open('test', 'w') while 1:
2
2136
by: vunet.us | last post by:
Please, explain an interesting phenomenon, if you can. I have an array of references to an HTML element: <div id='container'> <div id='someId1'></div> <div id='someId2'></div> </div> ..... myArray = document.getElementById("someId1"); myArray = document.getElementById("someId2");
0
2060
by: Vimalathithan | last post by:
I just developing a editor. I have provide the options like Bold, Italic, underlin, font change, font size change. These font options are keep in with one toolstripbutton. the toolstripbar keep inside with panel. The RichTextBox keep inside with other panel. The panel height and width is same with RichTextBox. The RichTextBox both scrolling options are make it as false. I done the coding for RichTextBox's height to fit with...
0
1550
by: =?Utf-8?B?UmF5IE1pdGNoZWxs?= | last post by:
Hello, I have a scrolling RichTextBox to which I add characters one at a time using the AppendText method as they are received by my application. Some of these characters may be backspace characters, which I need to somehow use to erase the most recent character displayed in the last line displayed in the text box. Of course, the backspace must only apply to the last line and must not back up into the previous line once all characters...
0
9641
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However, people are often confused as to whether an ONU can Work As a Router. In this blog post, we’ll explore What is ONU, What Is Router, ONU & Router’s main usage, and What is the difference between ONU and Router. Let’s take a closer look ! Part I. Meaning of...
0
9480
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can effortlessly switch the default language on Windows 10 without reinstalling. I'll walk you through it. First, let's disable language synchronization. With a Microsoft account, language settings sync across devices. To prevent any complications,...
0
10313
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers, it seems that the internal comparison operator "<=>" tries to promote arguments from unsigned to signed. This is as boiled down as I can make it. Here is my compilation command: g++-12 -std=c++20 -Wnarrowing bit_field.cpp Here is the code in...
0
10146
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven tapestry of website design and digital marketing. It's not merely about having a website; it's about crafting an immersive digital experience that captivates audiences and drives business growth. The Art of Business Website Design Your website is...
0
9944
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each protocol has its own unique characteristics and advantages, but as a user who is planning to build a smart home system, I am a bit confused by the choice of these technologies. I'm particularly interested in Zigbee because I've heard it does some...
0
8968
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing, and deployment—without human intervention. Imagine an AI that can take a project description, break it down, write the code, debug it, and then launch it, all on its own.... Now, this would greatly impact the work of software developers. The idea...
0
6735
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and then checking html paragraph one by one. At the time of converting from word file to html my equations which are in the word document file was convert into image. Globals.ThisAddIn.Application.ActiveDocument.Select();...
0
5511
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
3
2875
bsmnconsultancy
by: bsmnconsultancy | last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence can significantly impact your brand's success. BSMN Consultancy, a leader in Website Development in Toronto offers valuable insights into creating effective websites that not only look great but also perform exceptionally well. In this comprehensive...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.