Solved

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

Posted on 2002-03-07
13
556 Views
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?
0
Comment
Question by:efz
13 Comments
 
LVL 15

Expert Comment

by:simonet
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".

Alex
0
 
LVL 9

Expert Comment

by:ginsonic
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 .
0
 
LVL 27

Expert Comment

by:kretzschmar
ID: 6849752
do you mean screen-coords or caret-coords?
0
Free Tool: IP Lookup

Get more info about an IP address or domain name, such as organization, abuse contacts and geolocation.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

 
LVL 3

Expert Comment

by:gandalf_the_white
ID: 6850077
listening...
0
 

Author Comment

by:efz
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.
0
 
LVL 2

Expert Comment

by:classmate
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.

classmate.
0
 

Author Comment

by:efz
ID: 6851138
classmate:

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?
0
 
LVL 2

Expert Comment

by:classmate
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.
0
 

Author Comment

by:efz
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.
0
 

Author Comment

by:efz
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.
0
 
LVL 34

Accepted Solution

by:
Slick812 earned 300 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);
var
ClarPos: TPoint;
begin
{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;
end;

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

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
0
 

Author Comment

by:efz
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?
0
 
LVL 2

Expert Comment

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

classmate.
0

Featured Post

Free Tool: Path Explorer

An intuitive utility to help find the CSS path to UI elements on a webpage. These paths are used frequently in a variety of front-end development and QA automation tasks.

One of a set of tools we're offering as a way of saying thank you for being a part of the community.

Question has a verified solution.

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

Suggested Solutions

Title # Comments Views Activity
Delphi Mdi application Child forms get behind control 7 274
creating threads in delphi 1 138
SUM 2 INTEGER ARRAYS INTO 1 10 108
Slow Restore if incremental backups using RDiff.exe 4 31
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…
The uses clause is one of those things that just tends to grow and grow. Most of the time this is in the main form, as it's from this form that all others are called. If you have a big application (including many forms), the uses clause in the in…
Microsoft Active Directory, the widely used IT infrastructure, is known for its high risk of credential theft. The best way to test your Active Directory’s vulnerabilities to pass-the-ticket, pass-the-hash, privilege escalation, and malware attacks …

821 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