"Syntax Highlighting" in a (Rich)Edit Control

Posted on 1997-10-28
Last Modified: 2013-11-20

   I have taking on a personal task of trying to create an edit control that will do "syntax highlighting" a'la every decent IDE out there.

   My first approach was using a RichEdit control, and then starting a thread that looks for specific keywords and turns them blue.  This thread would start (starting at the current line, or last word) whenever <SPACE>, <TAB> or <ENTER> was hit.  Another thread would start (when scrolling occured) at the first visible line. (Redraws are disabled while the thread is running.)

   This works OK, but is a tad slow, and holding down a key produces unexpected results because a character can be entered while the thread has something selected, and then that selection gets replaced.

   My problem?  There has GOT to be a faster, and/or easier way to do this.  I can deal with the speed issue if I can guarantee that the actual text will not get changed if a user holds down a key.  Right now, setting and unsetting Read Only and/or waiting for the thread to finish produce undiserable results.

   1: Is there a way to apply a CHARFORMAT effect without actually causing a selection to take place?

   2: Is threre a better way for me to be doing this?   Making the user wait for the thread to finish is not acceptable.

   3: Currently, I am applying a "Normal" (color black) style to words that are being types (worrd that have the caret in them), to prevent "false highlighting".  This, too is slow.

   Thoughts on this one?

BTW: I have tried using both AfxBeginThread() and CreateThread(), both give the same results (of course, CreateThread() is faster).

-=- James.
Question by:jtwine100697

Expert Comment

ID: 1308994
You can intercept the keypress message of the rich edit box. When your treahd is proccessing the selection, set a flag, and when this flag is true, redirect the character to appear after the selected word

Author Comment

ID: 1308995
A Good idea, although it does not solve all of the problems.  The problem that I have with your answer is that the thread needs to excute a SetSel on a keyword to be able to change the color to Blue.

   In order for me to place the character after the selection, I need to move the caret, and the only way that I know how to do that is using SetSel.  If I change the selection while the thread is about to change the color...  Well...  

   Lastly...   You are assuming that the thread will always be processing the "previous" word (word to the left of the caret).  This is not the case.

-=- James.

Expert Comment

ID: 1308996
Your main problem with using a rich-edit control is that you need to edit the contents synchronously. Instead, why not derive your own class (like all IDEs do) and then you can use a bit-blt from your synchronous thread to the screen when you want. It'd be a lot faster, wouldn't be affected by inserting characters into the buffer, and isn't too hard to implement. I've done a similar thing with a custom listbox. It's especially easy if you use a fixed size font for the display, but it's up to you.
Master Your Team's Linux and Cloud Stack!

The average business loses $13.5M per year to ineffective training (per 1,000 employees). Keep ahead of the competition and combine in-person quality with online cost and flexibility by training with Linux Academy.

LVL 10

Expert Comment

ID: 1308997
If you want to spend some money - or rather, don't mind doing so - get ObjectiveEdit from Stingsoft which is a configurable sytax-higlighting editor class(es) for MFC.  It does both a view and a control class (so you have a full app that does editing in a view or just use it for a control in a dialog).

It also derives from CWnd directly and does its own drawing.

Unfortunately, the rich edit control just isn't fat/powerful enough to do syntax editing - rolling your own is the only feasible solution.


Expert Comment

ID: 1308998
You could try using StreamIn and StreamOut with RTF codes.

Author Comment

ID: 1308999
(ROnslow): I know of the classes/controls from StingSoft.  I wish to see if I can achieve something similar without going out to another product.  This is for fun!  No profit involved, hence no cost involved.

(Taryn): I thought of an owner drawn control, but I do not know how to acheive an owner drawn edit control.  Know of any source that I can take a look at?

(Gav): Are you suggesting that after every char (or word delimiter) that I StreamOut the contents (or recent words) in RTF, and then apply the RTF codes?  This is not as easy as it seems, as I will need to pre-define the "colortbl" entries, and the entries tend to change positions in the table.

(All): It seems that an owner drawn edit control is the way to go.  But I have never done a owner drawn edit control.  I can understand using TextOut (saving the last position) to colorize specific words, what about drawing the caret?

-=- James
LVL 10

Accepted Solution

RONSLOW earned 200 total points
ID: 1309000
You can create and set the caret for any window with the caret commands (CreateCaret etc).

Looks like you've come to the same conclusion as my answer suggested - doing it yourself.

Of course, the tricky stuff is in parsing and recognising the syntax (which you've already done).

The really tricky stuff is creating a structure that records (say) colour changes by text position - or maybe a list of records with text and colour with one record per colour change or line.  Then your paint routin for the window could traverse this list and draw the text in the required colour.

Good luck !!

Expert Comment

ID: 1309001
I recently wrote an entire CWnd derived class similar to CEdit, except that mine also will do numbered, bulleted, and definition lists.  I'd share the code, but since it was for work, I don't think I have the rights to give it away.  But I'd be glad to answer any questions if you run in to trouble.

Author Comment

ID: 1309002
ROnslow: I did not come to the same conslusion, really...  You and "Taryn" just pointed me in the right direction.

   I am awarding you the points.  If you have anything further to tell me, please email me directly.

JohnWeidner: If possible, do you know where I can see an example of painting a CEdit (derived) control?  Besides using the default processing, of course! :)

   Thanx to all...

-=- James.

Featured Post

ScreenConnect 6.0 Free Trial

Explore all the enhancements in one game-changing release, ScreenConnect 6.0, based on partner feedback. New features include a redesigned UI, app configurations and chat acknowledgement to improve customer engagement!

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

Title # Comments Views Activity
either24  challenge 19 97
wait notify demo infinite loop 3 110
Use of condition with 'serial' in ansible 2 61
Increment column based of a FK 8 23
Introduction: Database storage, where is the exe actually on the disc? Playing a game selected randomly (how to generate random numbers).  Error trapping with try..catch to help the code run even if something goes wrong. Continuing from the seve…
Exception Handling is in the core of any application that is able to dignify its name. In this article, I'll guide you through the process of writing a DRY (Don't Repeat Yourself) Exception Handling mechanism, using Aspect Oriented Programming.
This video will show you how to get GIT to work in Eclipse.   It will walk you through how to install the EGit plugin in eclipse and how to checkout an existing repository.
Microsoft Active Directory, the widely used IT infrastructure, is known for its high risk of credential theft. The best way to test your Active Directory’s vulnerabilities to pass-the-ticket, pass-the-hash, privilege escalation, and malware attacks …

809 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question