Author: Jonas Bilinkevicius
How to detect a mouse movement over a word in a TRichEdit
Answer:
Solve 1:
How can I detect when the mouse runs over a word or an expression in a TRichEdit?
You start by adding a handler to the TRichEdit's OnMouseMove event. In the handler
you get to the character under the mouse with:
1 uses
2 richedit; {for EM_EXLINEFROMCHAR}
3
4 var
5 pt: TPoint;
6 charindex, lineindex, charoffset: Integer;
7 begin
8 pt := Point(X, Y);
9 charindex := richedit.perform(Messages.EM_CHARFROMPOS, 0, integer(@pt));
10 if charindex >= 0 then
11 begin
12 lineindex := richedit.perform(EM_EXLINEFROMCHAR, 0, charindex);
13 charoffset := charindex - richedit.perform(EM_LINEINDEX, lineindex, 0);
14 end;
15 end;
Lineindex and charoffset now allow you to get the line out of the richedit.Lines
array and look at the characters value. Note that you have to use charoffset+1 as
index into the string, e.g.:
16 S := richedit.lines[lineindex];
17 charundercursor := S[charoffset + 1];
If charundercursor is a letter (IsCharAlpha( charundercursor )) you could now walk
backwards in S to find the start of the word and forward to find its end. Similar
for an "expression" (whatever that may mean in your context).
Solve 2:
Using the source code above, how can I determine, whether the mouse is over a
phrase like 'Inprise Delphi', which has the text attribute Bold and the colour Lime?
Well, you have to jump through some hoops, I'm afraid. The TRichEdit component has
a method FindText that can be used to search for text, ignoring any text
attributes. It would go something like this:
18 {additional vars required}
19 S: string;
20 foundPos, oldSelStart: Integer;
21
22 {after determining charindex as above}
23 S := 'Inprise Delphi'; {text to search for}
24 foundpos := richedit.FindText(S, charindex - Length(S) + 1, charindex + Length(S),
25 [stWholeWord, stMatchCase]);
26 if foundpos > = 0 then
27 begin
28 {found the text, check attributes}
29 {for this we need to select the text}
30 oldSelStart := richedit.SelStart;
31 richedit.SelStart := foundPos;
32 richedit.SelLength := Length(S);
33 with richedit.SelAttributes do
34 if ((ConsistentAttributes * [caBold, caColor]) = [caBold, caColor]) and
35 (Color = clLime) and (fsBold in Style) then
36 {we have a match!}
37 else
38 SelStart := oldSelStart;
39 end;
Solve 3:
How can I tell from a WM_MOUSEMOVE message that the mouse cursor is over a
particular character or line of a TRichedit? I am simulating a very simplistic
browser and want to know when the user is over a "hyperlink" which is really just a
TRichedit with some of the text underlined. That way I can tell the cursor to
change from crHand and back.
40 uses
41 richedit;
42
43 var
44 pt: TPoint;
45 charindex, row, col: Integer;
46
47 { ... }
48 GetCursorPos(pt);
49 pt := richedit.screentoclient(pt);
50 charindex := richedit1.perform(Messages.EM_CHARFROMPOS, 0, integer(@pt));
51 Row := richedit1.PerForm(EM_EXLINEFROMCHAR, 0, charindex);
52 Col := charindex - richedit1.Perform(EM_LINEINDEX, Row, 0);
Solve 4:
Looking for a way to find the character position the mouse is over during a
TRichEdit.onMouseMove event.
53 var
54 msg: TMessage;
55 pt: TPoint;
56 pos: integer; {offset into RichEdit.Text}
57
58 { ... }
59 pt.x := X;
60 pt.y := Y;
61 msg.Result := SendMessage(RichEdit.handle, EM_CHarFromPos, 0, Integer(@pt));
62 pos := msg.ResultLo;
63 if RichEdit.Text[pos] = '?' then
64 { ... }
|