Custom Caret Ghost Carets

General TRichView support forum. Please post your questions here
Post Reply
standay
Posts: 256
Joined: Fri Jun 18, 2021 3:07 pm

Custom Caret Ghost Carets

Post by standay »

Hi Sergey,

I'm using a regular rve. I have CustomCaretInterval = 500 and this in my OnDrawCustomCaret:

Code: Select all

  Canvas.Pen.Color := SRDJournalThemes.EditorFontColor;
  Canvas.Pen.Style := psSolid;
  Canvas.Rectangle(Rect);
All that works OK when my rve background is regular default clWindow, OR if I'm just using the default windows caret. However, most of the time my rve has a different bgnd color than clWindow. In those cases, when the bgnd color is not clWindow, and I scroll vertically up or down, I get the following:
Normal caret before scrolling
Normal caret before scrolling
Image49.png (1.58 KiB) Viewed 8478 times
Ghost caret when scrolled up
Ghost caret when scrolled up
Image50.png (1.29 KiB) Viewed 8478 times
Ghost caret when scrolled down
Ghost caret when scrolled down
Image51.png (1.53 KiB) Viewed 8478 times
I think it has to do with the DrawCustomCaret and/or ClearCustomCaret in RVERVData. My guess would be ClearCustomCaret but I don't want to go poking around in the source! Can you look at it and see if it does it on your system?

Thanks Sergey

NOTE: I was able to fix this by just adding rve.Refresh in the rve's OnVScrolled procedure. Not sure if that's the correct way to fix though!

Stan
Sergey Tkachenko
Site Admin
Posts: 17253
Joined: Sat Aug 27, 2005 10:28 am
Contact:

Re: Custom Caret Ghost Carets

Post by Sergey Tkachenko »

Sorry for the delay.
And sorry, I cannot reproduce this problem.

I tried to do it in the ActionTest demo.
I assigned
rve.CustomCaretInterval := 500
and the event:

Code: Select all

procedure TForm3.RichViewEdit1DrawCustomCaret(Sender: TCustomRichViewEdit;
  Canvas: TCanvas; const Rect: TRect);
begin
  Canvas.Pen.Color := clRed;
  Canvas.Pen.Style := psSolid;
  Canvas.Rectangle(Rect);
end;
(by the way, this code does not assign Canvas.Brush, so if the caret is thick, its background can be random)

I made a colored background, but I cannot reproduce the problem.
Maybe some additional settings affect the problem.
Can you send me a sample project?
standay
Posts: 256
Joined: Fri Jun 18, 2021 3:07 pm

Re: Custom Caret Ghost Carets

Post by standay »

Hi Sergey,

The problem seems to show only in my huge project with lots of moving parts. It's something I've done but I can't find it. I spent another 3+ hours today hunting for it, commenting and/or removing code and trying everything I could think of but nothing works other than calling refresh in vertical on scroll. I'll keep looking but I don't think it's in the rve component. I've tried setting a dark background and light text with the custom caret stuff in a simple app and it works OK there, although there's a lot less going on in that simple app.

Thanks for checking. If I come up with something I'll let you know.

Stan
Sergey Tkachenko
Site Admin
Posts: 17253
Joined: Sat Aug 27, 2005 10:28 am
Contact:

Re: Custom Caret Ghost Carets

Post by Sergey Tkachenko »

Maybe you have custom painting events assigned?
standay
Posts: 256
Joined: Fri Jun 18, 2021 3:07 pm

Re: Custom Caret Ghost Carets

Post by standay »

Sergey Tkachenko wrote: Tue Nov 23, 2021 9:22 am Maybe you have custom painting events assigned?
Not to the rve(s) other than the draw custom caret, and in the rve's style OnDrawParaBack (which I've tried disabling many times for testing) but I do for the line numbers (paint box), multi word highlighting (a combo of TWordEnum (to spin through the words) and WordPaintList (to paint the words)) and URL highlighting (WordPaintList). There is also spell checking that can affect things but spell check seems OK at this point. However, I can turn all that stuff off with menu options and the code inside them is not running and I still have the "ghosts." I've also added hard coded "exit;" calls in those and many other procs and funcs to no avail.

Aside from hints and warnings in the IDE, I rely on MadExcept to tell me about leaks, and the windows task manager to monitor CPU. If all that looks OK and I'm not getting an actual error or AV when running, it's usually good. The added call to rve.Refresh; in rveVScrolled is not driving the cpu crazy so I'm OK with using it for now.

I have several rve's in the "big" app. The main one is the main editor rve and is running all the time. The secondary one is below that and I use that for a notepad and to do simple editing of the theme (and other) files. I have a third rve that shows up if the caret is on a bookmark check point. That one has almost no code attached, and no line numbers, and I use the system caret for that one so it's OK. However, if I set that one up for a custom caret, it too displays a "ghost" caret but only briefly; after a pause it goes away.

The 2 main rve's have the same "ghost" issue. Note that the actual caret (the one in the center vertically, see screen shots below) is a maroon color which matches the text color which is correct, the other 2 are white "ghosts" (probably clWindow, not clWhite). I am not intentionally drawing white carets anywhere in code that I'm aware of!

My guess right now, and it's just a guess, is there's so much going on in this app "behind the scenes," that when I scroll without the rve.Refresh in rveVScrolled, is that the caret drawing can't quite keep up with things. Even in a simple test app set up to use custom caret stuff just like the big app (but with no refresh call in rveVScrolled), there is a slight delay of caret drawing when scrolling vertically, but in the simple app there's time (I guess) for things to refresh properly.

BTW, I tried horizontal scrolling for the first time today and I have the same issue there as well, same refresh call fixes it there too. See screenshot below.

I'll keep looking. There must be something I'm doing causing it. Here are the various calls that seem to workaround the issue for me:

Code: Select all

  //Fixes "ghost" carets when using custom caret functions. SRD
  rve.Refresh;
  //These also work, not sure which alternatives are lowest impact:
  //RVSetLinearCaretPos(rve,RVGetLinearCaretPos(rve));
  //rve.RVData.Invalidate;
  //rve.RVData.Refresh;
Thanks Sergey

Stan
Main app window
Main app window
SRDJournal 3.1.2.509-sm.png (158.34 KiB) Viewed 8042 times
Caret "ghosts" after vertical scrolling
Caret "ghosts" after vertical scrolling
SRDJournal caret ghosts.png (2.59 KiB) Viewed 8042 times
Caret "ghosts" after horizontal scrolling
Caret "ghosts" after horizontal scrolling
SRDJournal caret horz ghosts.png (4.83 KiB) Viewed 8042 times
standay
Posts: 256
Joined: Fri Jun 18, 2021 3:07 pm

Re: Custom Caret Ghost Carets

Post by standay »

Hi Sergey,

I think I found it. I commented out and removed almost everything in my "big" app this morning and still no luck. However, it turns out I had my main rve on a panel with the panel's DoubleBuffered property set to true. Out of desperation I turned that property off and to my surprise, no more "ghost" carets.

So, I tried it on my simple test app. And sure enough, with a dark background style and the rve set to use custom caret drawing, if I put that rve on a doublebuffered panel, caret ghosts appear when scrolling. Turn doublebuffering off and they go away. I even tried putting that rve directly onto the form itself (no panels) and set the form's doublebuffering property to true, the same thing happens: caret ghosts when scrolling until I turn the form's double buffering off.

So with that you should be able to replicate it. That may or may not be something you need or want to address but I wanted you to know in case someone else runs into it in the future. Simple problem, easy to fix on my end, but a booger to find!

Stan
Sergey Tkachenko
Site Admin
Posts: 17253
Joined: Sat Aug 27, 2005 10:28 am
Contact:

Re: Custom Caret Ghost Carets

Post by Sergey Tkachenko »

Thank you! I'll try to fix it in one of future update (by disabling the standard double buffering, because TRichView uses its own double buffering, and the standard one is redundant)
standay
Posts: 256
Joined: Fri Jun 18, 2021 3:07 pm

Re: Custom Caret Ghost Carets

Post by standay »

Sergey Tkachenko wrote: Thu Nov 25, 2021 10:51 am Thank you! I'll try to fix it in one of future update (by disabling the standard double buffering, because TRichView uses its own double buffering, and the standard one is redundant)
OK, sounds good, thanks. FYI, I never changed the rve.DoubleBuffered property, only the panel's DB prop the rve was sitting on.

Stan
standay
Posts: 256
Joined: Fri Jun 18, 2021 3:07 pm

Re: Custom Caret Ghost Carets

Post by standay »

Just a follow up. Sergey fixed this in the component so if you are using v20 you might want to turn the double buffering back on in the panels the rve is sitting on. I was having some issues with some canvas lineto code in my rve paint method and it was because I needed to re-enable the buffering. And yes, the custom caret still works OK after re-enabling the double buffer.
Post Reply