WM_SETREDRAW

135 views
Skip to first unread message

Stefan Küng

unread,
Aug 15, 2014, 1:32:48 PM8/15/14
to scintilla...@googlegroups.com
I'd like to request a feature:
Handle the WM_SETREDRAW message.

This message is implemented by most windows controls: when set to FALSE, the control isn't updated. Only when set back to TRUE, the control updates its UI.

Why:
When I load a file into Scintilla, I'm reading chunks of data (4kbytes) and add them to Scintilla using SCI_APPENDTEXT. Of course I first call SCI_ALLOCATE with the full file size.
The reason I'm not using SCI_SETTEXT: if I were to use SCI_SETTEXT, I'd have to load the whole file first into memory, then pass that to Scintilla. Which means there would be twice the memory required to load a file. By loading chunks and insert those with SCI_APPENDTEXT I can keep the required memory to the actual file size plus a little bit more, but not twice the file size.

Now, for every call to SCI_APPENDTEXT, Scintilla does a lot of work. It does not just insert the text but also updates the styling (sometimes at least), but it always updates the scroll bars. Even if the window is not visible! And that slows down loading big files quite a lot.

That's why I suggest Scintilla implements the WM_SETREDRAW message, or maybe implements a new SCI_SETREDRAW(bool bRedraw) command: when set to false, all UI updates are suspended until the command is set to true again.

Neil Hodgson

unread,
Aug 16, 2014, 12:21:13 AM8/16/14
to scintilla...@googlegroups.com
Stefan Küng:

> I'd like to request a feature:
> Handle the WM_SETREDRAW message.
>
> This message is implemented by most windows controls: when set to FALSE, the control isn't updated. Only when set back to TRUE, the control updates its UI.

How do you see this being implemented? I could imagine the window appearing inconsistent if a paint occurs when redraw is set off.

> When I load a file into Scintilla, I'm reading chunks of data (4kbytes) and add them to Scintilla using SCI_APPENDTEXT. Of course I first call SCI_ALLOCATE with the full file size.

Why such a small buffer? SciTE uses 128K.

> Now, for every call to SCI_APPENDTEXT, Scintilla does a lot of work. It does not just insert the text but also updates the styling (sometimes at least),

It shouldn’t update styling unless you are handling an event during loading.

> but it always updates the scroll bars. Even if the window is not visible! And that slows down loading big files quite a lot.

An alternate is ILoader (SCI_CREATELOADER) as used by SciTE for loading in a background thread.

Neil

Stefan Küng

unread,
Aug 16, 2014, 3:08:46 AM8/16/14
to scintilla...@googlegroups.com, nyama...@me.com


On Saturday, August 16, 2014 6:21:13 AM UTC+2, Neil Hodgson wrote:
Stefan Küng:

> I'd like to request a feature:
> Handle the WM_SETREDRAW message.
>
> This message is implemented by most windows controls: when set to FALSE, the control isn't updated. Only when set back to TRUE, the control updates its UI.

   How do you see this being implemented? I could imagine the window appearing inconsistent if a paint occurs when redraw is set off.

Yes, but that's not really a problem. After all, if we tell a control to stop drawing we can't be surprised if it doesn't paint nicely :)

Also, how that message is usually used is by first turning redraw off, then fill the control with data or do lots of other stuff with it, then turn redrawing back on. And all that's usually done in one function so there's no WM_PAINT handled since the message handler isn't even called between the setredraw() calls.

Scintilla itself uses that message for the listbox control btw.
 

> When I load a file into Scintilla, I'm reading chunks of data (4kbytes) and add them to Scintilla using SCI_APPENDTEXT. Of course I first call SCI_ALLOCATE with the full file size.

   Why such a small buffer? SciTE uses 128K.

4k is the size of one block on a harddrive - when reading blockwise, the block size should be a multiple of those 4k.
Using a bigger buffer won't improve performance when reading - but I can see now that this would improve performance when using SCI_APPENDTEXT since there would be much fewer calls to that function.
 

> Now, for every call to SCI_APPENDTEXT, Scintilla does a lot of work. It does not just insert the text but also updates the styling (sometimes at least),

   It shouldn’t update styling unless you are handling an event during loading.

I've seen styling update on the first call, then nothing until the file was fully loaded.
 

> but it always updates the scroll bars. Even if the window is not visible! And that slows down loading big files quite a lot.

   An alternate is ILoader (SCI_CREATELOADER) as used by SciTE for loading in a background thread.

I'll take a look.

But the feature request still stands: I know of another few features that would benefit from this. For example we have a function to sort lines in the editor. Preventing Scintilla from doing any updates while we write back the sorted lines would also benefit from this. Or when we change all tabs to spaces in a huge document. Or ...

Stefan

 

Col_Blimp

unread,
Aug 18, 2014, 7:20:23 AM8/18/14
to scintilla...@googlegroups.com
Can't you achieve what you want by setting a variable ie: SCI_NoDraw = 1 then subclassing the Scintilla window and returning true on the WM_DRAW/WM_PAINT messages if SCI_NoDraw = 0?

Stefan Küng

unread,
Aug 18, 2014, 1:27:16 PM8/18/14
to scintilla...@googlegroups.com


On Monday, August 18, 2014 1:20:23 PM UTC+2, Col_Blimp wrote:
Can't you achieve what you want by setting a variable ie: SCI_NoDraw = 1 then subclassing the Scintilla window and returning true on the WM_DRAW/WM_PAINT messages if SCI_NoDraw = 0?

That would only prevent the drawing, but not all the UI handling stuff that's still done. For example the whole styling or word wrap calculations are still done. With a proper flag this could be postponed as well until the SetRedraw(true) call.

Stefan

Neil Hodgson

unread,
Aug 18, 2014, 7:03:10 PM8/18/14
to scintilla...@googlegroups.com
Stefan Küng:

> Also, how that message is usually used is by first turning redraw off, then fill the control with data or do lots of other stuff with it, then turn redrawing back on.

How would the scroll bars be stopped from drawing? They are integrated in the window, not separate windows.

> But the feature request still stands: I know of another few features that would benefit from this.

Its not something that I want to work on now so it would have to be contributed by someone.

> For example we have a function to sort lines in the editor. Preventing Scintilla from doing any updates while we write back the sorted lines would also benefit from this. Or when we change all tabs to spaces in a huge document. Or …

Changing tabs to spaces or similar in SciTE over a large document doesn’t cause display flashing. Is your application changing the selection when making each modification?

Neil

Stefan Küng

unread,
Aug 19, 2014, 3:45:16 PM8/19/14
to scintilla...@googlegroups.com, nyama...@me.com


On Tuesday, August 19, 2014 1:03:10 AM UTC+2, Neil Hodgson wrote:
Stefan Küng:

> Also, how that message is usually used is by first turning redraw off, then fill the control with data or do lots of other stuff with it, then turn redrawing back on.

   How would the scroll bars be stopped from drawing? They are integrated in the window, not separate windows.

Yes, but if you don't call SetScrollInfo(), they're not redrawn or recalculated.
 

> But the feature request still stands: I know of another few features that would benefit from this.

   Its not something that I want to work on now so it would have to be contributed by someone.

> For example we have a function to sort lines in the editor. Preventing Scintilla from doing any updates while we write back the sorted lines would also benefit from this. Or when we change all tabs to spaces in a huge document. Or …

   Changing tabs to spaces or similar in SciTE over a large document doesn’t cause display flashing. Is your application changing the selection when making each modification?

ok, maybe the tabs/spaces example wasn't the best. But the line sorting really is affected:
the lines are first removed, then inserted again one-by-one in the sorted order.
After every insert, Scintilla does a lot of stuff that could be postponed until the last line is inserted.
 
Stefan

Neil Hodgson

unread,
Aug 19, 2014, 8:05:21 PM8/19/14
to scintilla...@googlegroups.com
Stefan Küng:

> Yes, but if you don't call SetScrollInfo(), they're not redrawn or recalculated.

Then you have a scroll state that is not synchronised with Scintilla’s state. For example, the vertical scroll bar may have more lines than are in Scintilla. That seems like a situation that could lead to bugs.

> ok, maybe the tabs/spaces example wasn't the best. But the line sorting really is affected:
> the lines are first removed, then inserted again one-by-one in the sorted order.

Why insert line-by-line? Just replace the whole range in one call.

Neil

Stefan Küng

unread,
Aug 20, 2014, 2:19:05 PM8/20/14
to scintilla...@googlegroups.com, nyama...@me.com


On Wednesday, August 20, 2014 2:05:21 AM UTC+2, Neil Hodgson wrote:
Stefan Küng:

> Yes, but if you don't call SetScrollInfo(), they're not redrawn or recalculated.

   Then you have a scroll state that is not synchronised with Scintilla’s state. For example, the vertical scroll bar may have more lines than are in Scintilla. That seems like a situation that could lead to bugs.

That's why SetRedraw(true) should re-sync and update everything it needs in one go, instead of doing this on every command.
 

> ok, maybe the tabs/spaces example wasn't the best. But the line sorting really is affected:
> the lines are first removed, then inserted again one-by-one in the sorted order.

   Why insert line-by-line? Just replace the whole range in one call.

saving memory:
I have an array of lines that are now sorted. Inserting this in one go means first creating a buffer big enough to hold all lines and then fill that buffer, then insert that buffer in one go.
Not a problem if you only sort 100 lines. If you sort 5000 lines or more it might cause problems: even if there's enough memory available it's not guaranteed that we get a big enough consecutive memory block.

And yes, there are ways around that as well. But despite all that: I'm asking for a new and IMHO very useful feature. If you're not interested, that's fine with me. Just wanted to suggest something that might benefit other users of Scintilla in various tasks.

Stefan

 

Neil Hodgson

unread,
Aug 20, 2014, 6:41:34 PM8/20/14
to Scintilla mailing list
Stefan Küng:

> saving memory:
> I have an array of lines that are now sorted. Inserting this in one go means first creating a buffer big enough to hold all lines and then fill that buffer, then insert that buffer in one go.
> Not a problem if you only sort 100 lines. If you sort 5000 lines or more it might cause problems: even if there's enough memory available it's not guaranteed that we get a big enough consecutive memory block.

Inserting line by line creates an undo Action for each line. An Action is 20 bytes in 32-bit mode plus an allocation for the line’s text which will commonly have an overhead of between 8 and 24 bytes. So an extra 28-44 bytes is being used for each line and this memory will likely remain allocated until the file is closed. If the lines are first joined by the application then that allocation is temporary and can be freed immediately after inserting the text into Scintilla.

Scintilla provides a nice high level API with a lot of features but those features have costs and they are not always obvious.

> And yes, there are ways around that as well. But despite all that: I'm asking for a new and IMHO very useful feature. If you're not interested, that's fine with me. Just wanted to suggest something that might benefit other users of Scintilla in various tasks.

I am not completely against a block on redraw. However, I think it is likely to be overused when there is a drawing problem, and in many cases an alternate solution would be a bigger improvement. Blocking redraw hides problems instead of solving them.

Neil

Neil Hodgson

unread,
Jul 22, 2021, 9:44:51 PM7/22/21
to Scintilla mailing list
WM_SETREDRAW(FALSE) on Win32 will now stop scroll bar updates.

SciTE wraps its Replace All command with stop/start redraw as a test case.

https://sourceforge.net/p/scintilla/code/ci/e49f7ddc941c2f2aa930ee11d4de8432268bd3a5/

I still don’t think this is optimal but its been 7 years since the topic started and I haven’t found time to do something better.

https://docs.microsoft.com/en-us/windows/win32/gdi/wm-setredraw

Neil
Reply all
Reply to author
Forward
0 new messages