March 29, 2024, 03:47:31 AM

News:

Own IWBasic 2.x ? -----> Get your free upgrade to 3.x now.........


Rich edit control colouring

Started by Andy, March 29, 2020, 03:52:49 AM

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

Andy

March 29, 2020, 03:52:49 AM Last Edit: March 29, 2020, 04:00:36 AM by Andy
This year so far, I have been working with rich edit controls - something I haven't really touched on much before, so a little learning was required.

IWBasic has built in functions to help you do things like get text, colour text etc, so that's where I naturally started.

I've been working on loading a test file with 4,085 lines of code and started to test the time taken to colour these lines of text.

My initial attempts started at around 5 seconds to do it.

Well 5 seconds is quite fast when you think of how many words it colours, but 5 seconds is a wait that can start to irritate you, so I needed to go faster than that.

First I noticed that if I disabled showing the rich edit vertical scroll bar it completed quicker - I forget how much now, but it was enough to leave it hidden and create my own scroll bar as a replacement.

So that is step 1, hide the vertical scroll bar and use a custom one.

Now, what else can be done?

With a lot of reading I came across something interesting....

Turning off messages for my rich edit control (rHandle) before colouring speeds things up apparently?, so I tried it like this...

  SendMessage(rHandle,EM_SETEVENTMASK,0,0)
  SendMessage(rHandle,WM_SETREDRAW,false,0)

And indeed it did! - it saved at least 2.7 seconds, getting it down to 2.2 seconds.

So Step 2 - turn of messages for your rich edit control before colouring it.

When finished colouring, turn the messages back on again...

  SendMessage(rHandle,WM_SETREDRAW,true,0)
  InvalidateRect(rHandle,0,true)
  SendMessage(rHandle,EM_SETEVENTMASK,TRUE,ENM_CHANGE | ENM_SCROLL)

Here "rHandle" is just a handle to my rich edit control.

What next?

Use Win32 API calls instead of IWBasic's built in commands...

Instead of say @RTSETSELSELECTION use this:

SendMessage(rHandle,EM_SETSEL,(#i[GetLine].StartPos[c1]+Offset),(#i[GetLine].EndPos[c1]+Offset))

(#i[GetLine].StartPos[c1]+Offset) and (#i[GetLine].EndPos[c1]+Offset)) are just my calculated start and end positions to select for highlighting.

Now for colouring,

  cf.dwMask = CFM_COLOR
  cf.crTextColor = #h[GetLine].Colour[c1]
  cf.cbSize = sizeof(cf)
  SendMessage(rHandle,EM_SETCHARFORMAT,SCF_SELECTION,&cf)

To do this, you will this structure defined:

type CHARFORMAT
    UINT        cbSize
    DWORD      dwMask
    DWORD      dwEffects
    LONG        yHeight
    LONG        yOffset
    COLORREF    crTextColor
    BYTE        bCharSet
    BYTE        bPitchAndFamily
    char        szFaceName[LF_FACESIZE]
endtype

CHARFORMAT cf

Steps 3 and 4, use Win32 API calls instead of the built in commands and add $INCLUDE "Richedit,inc" to your program.

Step 5, use pointers instead of arrays.

Following these steps I have got the colouring of 4,085 lines of code down from 4.9 seconds to 1.5 seconds.

Hope you find this interesting (if you haven't already fallen asleep!).

Andy.
:)
Day after day, day after day, we struck nor breath nor motion, as idle as a painted ship upon a painted ocean.

h3kt0r

Well done Andy. Keep up the good work !
;)

LarryMc

I have a question ...just for kicks
You can't possibly SEE 4000-10000 lines on the screen at one time on the screen.
So why spend the time to color 4000-10000 lines.
Why not just spend the time to only color the lines that can be seen like 40 or 60?

You're wanting speed....

LarryMc
LarryMc
Larry McCaughn :)
Author of IWB+, Custom Button Designer library, Custom Chart Designer library, Snippet Manager, IWGrid control library, LM_Image control library

Andy

Hecktor,

Thanks very much for the support! and you have helped me with this - so thanks again.

Larry,

Well the obvious thing to do is to only colour the lines you can see not the whole file.

However I ran into difficulties, I was trying to colour say 35 lines at a time when I scrolled, but the colouring was slow and it was delaying the thumb scroll.

So I decided to see just how fast I could actually colour the whole file...

I'm glad I did because I've learnt some invaluable things along the way (as posted above).

Now based on what I have learned trying to colour the whole file as fast as possible I have now gone back to the original idea of only colouring a nominal 100 lines on load, and colouring the rest as you scroll.

So all the speed up tricks posted above have now been implemented when scrolling, and I'm very pleased to say it works very well now.

All keywords are coloured correctly as are quotations, I just now need to colour commented lines to finish off this section then I can move on to other things in my editor.

This whole speeding up process has delayed me by probably 3 weeks or so.

Like an old joke about British Rail - I get there in the end!  :D

Andy.
 :)
 
Day after day, day after day, we struck nor breath nor motion, as idle as a painted ship upon a painted ocean.

aurelCB

Andy 
there is another but hard option
if you find similar code in NASM assembler then you may try it inject into code ?

Andy

Good suggestion Aurel,

But I think that's above me!

Andy.
Day after day, day after day, we struck nor breath nor motion, as idle as a painted ship upon a painted ocean.

Andy

April 02, 2020, 05:54:29 AM #6 Last Edit: April 02, 2020, 05:56:39 AM by Andy
Thought I would post this.

My editor is a very long way away from being finished, but it's colouring sufficiently fast enough now when you scroll vertically so I thought I would share what I have got so far...

Subroutines / code that may be of interest to you:

ColourLineZ (in the include file)

This subroutine takes a line of text and detects words, delimiters, quotations and single comment characters. Depending on what it finds, it will colour appropriately.

ColourText sub (in the xeditor4.iwb file)

It gets the first visible line on screen.
This turns off messages from the rich edit prior to colouring.
Invokes a subroutine called "GetTheScrollPos" (in the xeditor4.iwb file)
Then turns rich edit messages back on.

GetTheScrollPos sub (in the xeditor4.iwb file)

This gets each line of text, and the "Offset" (start position of the first character on the line).
Then in a FOR / NEXT loop calls "ColourLineZ" (as mentioned above).

In the xeditor4.iwb file

Line 343 is where I make the program invoke colouring as and when someone scrolls.


How to

Compile as single file (F8) with the include file in the same location.

Questions 1 and 2

Do you think it colours the text fast enough, looks okay to me - but that's just me!
Do the lines look coloured correctly to you?

Observation

When scrolling downwards, I do see the cursor flashing / the wait symbol briefly - is there a way to stop this / turn it off until you have finished scrolling?

Anyway, attached are the files + a test file which is loaded.

There is a lot of junk in the files, so please just ignore them - will tidy it up later.

Please let me know what you think.

Thanks,
Andy.
Day after day, day after day, we struck nor breath nor motion, as idle as a painted ship upon a painted ocean.

Brian

April 02, 2020, 06:14:44 AM #7 Last Edit: April 02, 2020, 08:59:18 AM by Brian
Andy,

Can't compile - it is asking for xeditor.iwb, which is missing, I think

Brian

Edit: Sorry, Andy. Just rename xeditor4.iwb to xeditor.iwb. Works then