Go Premium for a chance to win a PS4. Enter to Win


Locating the x,y coordinates of text in a rich text control

Posted on 2002-03-07
Medium Priority
Last Modified: 2010-04-05
I'd like to be able to determine the x,y pixel coordinates of certain text in a rich text editing control (Delphi's TRichEdit). I tried to locate the text by coloring the text red with the intention of searching for red pixels using the GetPixel function. Apparently, the rich text editing control does not have a device context whose handle can be supplied to the GetPixel function (or at least I haven't figured out how it can be done in several days of playing around). Is there a way to do this using GetPixel? Or is there another way to do this?
Question by:efz
LVL 15

Expert Comment

ID: 6849683
Is the TRichEdit in the same application as the desired routine?

Will there be a need to search for the selected text?

Keep in mind that it's just valid if the text searched is being displayed and not "scrolled".


Expert Comment

ID: 6849704
What is your reason to do that ? I need this information to know how can I help you .

Untill then ... you can use the mouse events ?
I have a tip how to get the word under the mouse cursor in a TRichEdit .
LVL 27

Expert Comment

ID: 6849752
do you mean screen-coords or caret-coords?
What does it mean to be "Always On"?

Is your cloud always on? With an Always On cloud you won't have to worry about downtime for maintenance or software application code updates, ensuring that your bottom line isn't affected.


Expert Comment

ID: 6850077

Author Comment

ID: 6850224
Yes, the TRichEdit component is located in the same unit as the routine that will perform the search.

I don't expect there will be a need to actually search for the text for reasons stated below.

Because the form or window is always longer than the screen (ie., requires vertical scrolling), the desired code would need to work with the window containing the TRichEdit component as opposed to the viewable screen. The x,y coordinates to which I referred in the original question are the window or TRichEdit component's x,y pixel coordinates. The TRichEdit component is "maximized" or client-aligned within the containing form window.

I'm familiar with the mouse location tip, but that won't suffice because the text input box must move from one location to another when the user presses the TAB key. Thus far, I can move a red dot or text to the desired location (by altering the underlying RTF file), but I can't determine the x,y pixel coordinates of the window in order to then locate a text input box in that location (ie., overlapping and hiding the red dot).

The reason for locating the x,y coordinate is that we currently place a text edit box at certain locations so that users can make entries in those areas of our forms and TAB from one area of the form to the next. Until now we have measured each x,y location manually and that's worked reasonably well. However, we also have different percentages of scaling available so that users can size the forms to their liking. The problem is that when users choose percentages of scaling other than 100%, there's a tendency for the text input box to float off the desired location of the form (the form is presented in a TRichEdit component). The best solution I can think of would be to have the form itself tell us where the text input box should be located. That way the box will always be perfectly aligned with the area of the form where the text input box/answer should appear. Also we won't need to laboriously plot the x,y location of each answer on the form.

Expert Comment

ID: 6850846
If i read this correctly, you are trying to use RTF to make a little "stunt"; you're using RTF as read-only so that you easily can make a tasefull look, but still you want users to be able to edit selected parts of the text.

If i were you i would experiment with the ReadOnly property to see if you can enter text directly into the richedit at desired locations instead of using another edit control for it. Adjust readonly when the caret has moved. Next, you probably should use some kind of searching in the richedits text property to be able to place the caret at the desired "field" when the user presses tab.

To do all this you might have to make a derived component from TRichEdit.


Author Comment

ID: 6851138

Everything you say is true, we make the RTF editor read-only so users can't destroy the rather complicated and highly formatted forms we use. Your suggestion is a good one, but once we let the user enter directly into the RTF editor, it will be real easy for the user to skew the formatting. Our solution was to overlay a text input (sometimes a checkbox) over the top of the editor so we could police the user's entries and do error-trapping, etc. The system works real well except when the user selects a different viewing scale, then nomatter what algorithm we use, we find that for various reasons the text input boxes tend to float from from their designated areas. I was able to turn the location where the input box should appear red by altering the underlying RTF file and thought that if I could locate that red spot, I could make sure that nomatter what viewing scale the user chose, the input box would always align itself perfectly. If this can't be done, then I think I might have to lock the forms at 100% scaling because your solution would not account for the handling of checkboxes and other entry-validation, etc. Am I right or am I overlooking something?

Expert Comment

ID: 6851628
Since you also use checkboxes, I only have one approach that might work:

1) Try to let the richedit selection move using some movement logic in the keyboard events or -messages of TRichEdit;

2) Use windows api GetCaretPos to find the position of the caret (selection), and place your "inplace control" at this point. You have to be sure that the richedit owns the caret each time. After this you can focus your inplaced control.

3) repeat 2 at each scroll or resize.

Author Comment

ID: 6851849
I think you're on to something. If I understand correctly I can:

1. Position the cursor (caret) via the RTF file while the RTF component is not read-only.

2. Then, using I can use your api call to get the x,y coordinates of the cursor.

3. Finally, switch back to read-only and position my text box.

Your solution sounds like the ticket, but I'm not sure how to position the caret (step 1) in the RTF file. I guess I'll need to review the RTF 1.5 specification to see if there's a command for positioning the cursor at a specific location in a RTF file. Many thanks for your suggestion. I'll need a day or two to see if this works. I'll be very grateful to you if this works. I'll let you know.

Author Comment

ID: 6851860
Sorry for being dense. You did mention that I might be able to use the search command to locate the cursor. I can hardly wait to see if this works. Many thanks again.
LVL 34

Accepted Solution

Slick812 earned 1200 total points
ID: 6851963
hello efz, There is an API sendmessage of EM_POSFROMCHAR, which may be just what you need. Here is some code for a button click

procedure TForm1.sbut_FindPointClick(Sender: TObject);
ClarPos: TPoint;
{I use RichEdit1.SelStart for the charater position, but you can use any number to specify
the charater (position) in the RichEdit}
SendMessage(RichEdit1.Handle, EM_POSFROMCHAR, Integer(@ClarPos),RichEdit1.SelStart);
{check to see if the charater is ot of view}
if (ClarPos.x < 0) or (ClarPos.y < 0) or (ClarPos.x > RichEdit1.ClientRect.Right) or
(ClarPos.y > RichEdit1.ClientRect.Bottom) then Exit;
{change the Point Mapping to the Main Form}
MapWindowPoints(RichEdit1.Handle, Handle, ClarPos, 1);
{set your control to the charater Position}
Panel1.Top := ClarPos.y;
Panel1.Left := ClarPos.x;

- - - - - - - - - - - - - - - - - - - - -

the RichEdit1.SelStart give you the current Claret Position. You can put in a Charater Position in the last parameter of SendMessage to get the pixel position of Any charater, and the Claret can be any where. I beleive this will work with the richedit in ReadOnly

Author Comment

ID: 6852643
Your code was the right on! The MapWindowPoints call was especially necessary. I pretty much used classmate's generalized outline of the solution and Slick812's code. Isn't there a way to divide the points between several correct and excellent answers?

Expert Comment

ID: 6855507
If the points were good for something in real life, I might have bothered. -Believe me, I don't!!


Featured Post

Keep up with what's happening at Experts Exchange!

Sign up to receive Decoded, a new monthly digest with product updates, feature release info, continuing education opportunities, and more.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

A lot of questions regard threads in Delphi.   One of the more specific questions is how to show progress of the thread.   Updating a progressbar from inside a thread is a mistake. A solution to this would be to send a synchronized message to the…
Creating an auto free TStringList The TStringList is a basic and frequently used object in Delphi. On many occasions, you may want to create a temporary list, process some items in the list and be done with the list. In such cases, you have to…
Want to learn how to record your desktop screen without having to use an outside camera. Click on this video and learn how to use the cool google extension called "Screencastify"! Step 1: Open a new google tab Step 2: Go to the left hand upper corn…
When cloud platforms entered the scene, users and companies jumped on board to take advantage of the many benefits, like the ability to work and connect with company information from various locations. What many didn't foresee was the increased risk…

824 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question