How to eliminate "flicker" in a RichEdit...

Hi Experts, here's a little brain teaser for you. It's related to a previous question I asked a couple of weeks ago:

http://www.experts-exchange.com/questions/28688857/Storing-the-original-index-of-each-character-in-a-TRichEdit.html

Basically, I have 2 RichEdits and I want to save off the original index position of each character in RichEdit1, before I copy the contents over to RichEdit2 and do possible manipulations and changes on the contents (not important why I'm doing these manipulations). Anyway, as noted in my previous question above, I think I've discovered a little trick using the SelAttributes of RichEdit. My dilemma seemed to be that I needed a variable where I could "save" the original position index of each character in RichEdit1... something like having a "tag" property for each character in the RichEdit. of course, there is no individual "tag" property for each character, but I think I found the next best thing - I discovered that if I set the font of the RichEdit to the "default font" of Arial|20|Bold, then I could freely use and overwrite the NAME attribute of RichEdit and it would save whatever value I stored in there. If I program a MouseMove event to reflect the values of each character position in RichEdit2 in a hint, this seems to work perfectly for me. Perfect provided I use SelLength = 1 while I'm displaying the hint. If I set SelLength = 0, then the indexing seems to get thrown off by 1 starting at the 2nd character.
   If this is confusing to this point, I've created a small test app and have attached it to this post... using it to illustrate should clear everything up. Here's how to use it:

- make sure the RadioGroup is set to "RichEdit2.SelLength = 1".
- in the 1st RichEdit field, type in some text like ABCDEFGH.
- click the downward "double arrow" button to copy the text to RichEdit2 underneath it. In this ButtonClick routine, I loop through each character in RichEdit2 and assign to RichEdit2.SelAttributes.Name property, the index position of the current character (ie. "1" for 1st character, "2" for 2nd character, and so on). This event also produces a "tracefile" to your default folder, outputting each character, SelStart value, index position, and NAME property value.... just to verify that everything is getting stored right... and it is.
- hover the mouse over each character in RichEdit2 from left to right and you'll see everything is correct - the hint shows the correct character being hovered over and the correct "Current Position" index and "Original Position" index.
- Now in the RadioGroup, select RichEdit2.SelLength = 0. Now hover again in RichEdit2 from left to right. You'll see that on the 2nd character 'B', the "OrigPos" index value gets out of step with the "CurrPos" index value. That is my dilemma - why does this happen? Changing RichEdit2.SelLength from 1 to 0 is the culprit, but why? Setting SelLength to 0 shouldn't make any difference. According to the Delphi documentation for SelStart:

"If there is no selected text, SelStart indicates the position of the cursor."

In my MouseMove event, I'm setting SelStart with the RichEdit2.SelStart := iCharIndex statement, so really, there should be no need for me to have to set SelLength to 1, is there? But it just won't work right if SelLength is 0.
   Now you're probably asking, "well just leave SelLength at 1 and be done with it, if it works!". Well yes I could, but when Sellength is 1, the RichEdit MouseMove event produces an ugly "flicker" when you hover the mouse over it whilst the focus is on RichEdit2. If the focus is NOT on RichEdit2 and you hover the mouse over it, there is of course no flicker.

So my goal is to have the indexing working right (of course), AND to have no ugly flicker as the user hovers the mouse over RichEdit2 if the focus is in RichEdit2. Can someone offer some help on this brain-twister please?

Thanks!
    Shawn

P.S: I created the sample project in Delphi 7
FixFlicker.dpr
Unit1.dfm
Unit1.pas
shawn857Asked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

jimyXCommented:
Hi Shawn,
I can not run/test any project at the moment, but will try to help.

When SelLength=1 (or higher) you get/set the attributes of the marked text.

But when SelLength=0 then you only get the attributes of the char that's at the left of the cursor, IIRC.

So if you want to avoid SelLength=1 then place the cursor at the end of the char where it reads the correct attributes (your target index).

Then the MouseMove event becomes:
procedure TForm1.RichEdit2MouseMove(Sender: TObject; Shift: TShiftState; X,
  Y: Integer);
var
  Pt: TPoint;
  sHint : string;
  OrgPos : string;
  hSelStart : integer;
  lnth, iCharIndex : integer;
begin

  //if RichEdit2.SelLength >= 1 then EXIT;

  RichEdit2.hint := '';     // Clear out the old hint
  lnth := Length(RichEdit2.Text);
  if lnth <= 0 then EXIT;    // if nothing in TRichEdit, then just exit


  with TRichEdit(Sender) do
  begin
    Pt := Point(X, Y);

    // Get Character Index from word under the cursor
    iCharIndex := Perform(EM_CHARFROMPOS, 0, Integer(@Pt));

    if iCharIndex < 0 then EXIT;

    if iCharIndex >= lnth then
       iCharIndex := iCharIndex - 1;


    hSelStart:= RichEdit2.SelStart;       // save off the cursor position, if any. Will restore after MouseMove completed

    //since there will be not SelLength place the cursor after the char to detect its attributes
    RichEdit2.SelStart := iCharIndex    +1;

    //RichEdit2.SelLength := RadioGroup1.ItemIndex;   // Set the SelLength. 1 works fine, 0 gives wrong index in hint
    OrgPos:= RichEdit2.SelAttributes.Name;        // Retrieve the Original Index position stored in the NAME property
    RichEdit2.SelLength := 0;                     // Set the Sellength back to 0
    RichEdit2.SelStart := hSelStart;              // Restore the orignal cursor position in the RichEdit back to where it was


    sHint:= IntToStr(iCharIndex+1);

    if TRichEdit(Sender).Hint <> sHint then
    begin
      TRichEdit(Sender).Hint := RichEdit2.Text[iCharIndex+1]+'   CurrPos: '+sHint+'   OrigPos: '+OrgPos;
    end;

    Application.ActivateHint(TRichEdit(Sender).ClientToScreen(Point(X,Y)));
  end;
end;  // RichEdit2MouseMove

Open in new window

0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
shawn857Author Commented:
"But when SelLength=0 then you only get the attributes of the char that's at the left of the cursor, IIRC."

ohhhhhhh! I thought that it was supposed to get the attributes of the char that is to the RIGHT of the cursor!!

This fixed it - and you didn't even have to look at the sample program! Thank you Jimy!!

Cheers
   Shawn
0
shawn857Author Commented:
Perfect... thank you Jimy.

Cheers
   Shawn
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Delphi

From novice to tech pro — start learning today.

Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.