?
Solved

Using tables in TRichEdit or TWebBrowser; Translating a location in an HTML file to a screen x,y coordinate

Posted on 2005-03-18
19
Medium Priority
?
6,403 Views
Last Modified: 2012-08-13
BACKGROUND

Our company creates form-filling software for the government. Our current technique for displaying forms for completion by the user involves using a Delphi component called TRichEdit. Our method uses three basic steps shown below with a simple example for clarification.

1. First an RTF file that is a duplicate of the subject form is loaded into the TRichEdit component for display on the user's screen. A typical RTF file might look like this:

     {RTF Header stuff}
     A. Enter an amount on line A. /$1/
     B. Enter an amount on line B. /$2/
     C. This is the total of A & B. /$3/

2. Once the form is loaded into the TRichEdit component, our program locates the variables and substitutes answer text for each variable except the "current" variable. We use TRichEdit's FindText method to locate the "current" variable (i.e., /$1/) on the form. TRichEdit's SelStart property then lets us put the cursor at the location of that variable.

3. When the cursor is properly located at the "current" variable, we use an EM_POSFROMCHAR Windows message to determine the screen X,Y coordinates of the cursor location and then superimpose a text input box like TEdit (or any other Delphi control) at that location so that the user can enter the requested information.

Every time the user presses tab or clicks on an area of the form, the program updates its calculations, advances the "current" variable and refreshes the page with the input control in the new "current" location.

PROBLEM

As we encounter more complicated government forms, we've discovered that formatted tables work the best for laying them out. Unfortunately, we're finding that the TRichEdit component is not very capable when it comes to rendering tables accurately. It's not that the tables we are using are extremely complex, it's just that the TRichEdit is not capable of rendering anything more than a very basic table. We've tried a third-party solution by Woll2Woll software (TwwRichEdit), and although the RTF capabilities were much better than Borland's TRichEdit, the TwwRichEdit component still doesn't do tables adequately, i.e., not restricting text to a cell's boundaries and not observing font changes from cell to cell.

QUESTION

A. We need a TRichEdit or substitute RTF component that has (1) the ability to render more than just simple tables, and (2) permits the use of the FindText, SelStart and EM_POSFROMCHAR (or similar) commands so we can use it as explained above. Are we overlooking a way to make TRichEdit handle tables better or is there a 3rd party RTF component that has the desired functionality?

B. If the answer to A above is "no", using Delphi's HTML component (TWebBrowser) might work because it handles tables much better than the TRichEdit component. However, we don't know how to get the above-described functionality out of the HTML component. For example, positioning a cursor at a particular location in the HTML file (i.e, like SelStart does for RTF files) and then defining that location in terms of screen x,y coordinates (i.e., EM_POSFROMCHAR) so we can superimpose the appropriate Delphi input component (i.e., TEdit). Could you provide an example of these two functions using the HTML component?

We have countless forms in RTF format, so the first of the two methods is more desirable. I apologize for the length of this question.
0
Comment
Question by:efz
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 8
  • 5
  • 3
  • +2
19 Comments
 
LVL 5

Expert Comment

by:paulb1989
ID: 13578998
Maybe the TRichView component will help, it has many more capabilities than TRichEdit:

http://www.trichview.com/
0
 

Author Comment

by:efz
ID: 13580165
You're quite right. The TRichView component boasts many more capabilities specifically related to complex tables. Several days ago, before I posted this question on Experts Exchange, I sent an inquiry to TRichview. They haven't responded to my question yet. I did note, however, that their TRichView component did not inherit from the TCustomRichEdit control, so I'm guessing that the SelStart function may not be available in their component. Hopefully they'll let me know a bit more about this. Please accept my sincere thanks for your comment.
0
 
LVL 10

Expert Comment

by:Jacco
ID: 13581025
We use a component WPRichEdit made by the company WPTools (written by Julian Ziersch). We first bought it because it was the only component we could find supporting right-aligned and decimal-aligned tabs. But it also supports complex tables and has extensive support for mail merging. We use it for automatic mail merging but I think it would be very possible to do manual filling of the insert points as well.

We have found now way of improving the existing TRichEdit since it is based on the inner working of the RichEd20.dll of microsoft. This DLL is included only to make WordPad work and does not include all formatting features Word does. It does not support the full RTF standard.

The SelStart method would have to change a bit but the concepts of moving the cursor around in the TWPRichEdit is about the same.

Regards Jacco
0
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.

 
LVL 10

Expert Comment

by:Jacco
ID: 13581030
Oh yeah, here is a link to their site:

http://www.wpcubed.com/index.htm

We always had very good email support from Julian as well.

Regards Jacco
0
 
LVL 5

Expert Comment

by:paulb1989
ID: 13581534
In regards to TRichView there is an example of moving the caret to a paragraph below, so its possible to move the caret.

http://www.trichview.com/support/dnewsweb.cgi?cmd=article&group=trichview.support.examples&item=26&utag=
0
 
LVL 2

Expert Comment

by:prevarant
ID: 13582030
...just listen
0
 

Author Comment

by:efz
ID: 13582085
To Jacco: Thanks for your pointer. I don't know how many TRichEdit substitutes there are, but I was hoping for specific knowledge about these issues so that I might get a confirmation without needing to purchase each one or download and test each demo in order to find out whether it does what I want. I've downloaded the TRichView materials and started combing thru the Help files. I'll try WPRichEdit next once I determine whether TRichView solves my problem. You and I were thinking along parallel lines concerning RichEd20.dll. I found Version 4. However, both RichEd20 and RichEd32 are present in my systems folder, how do I know which one Delphi 7 is using? You may be close on this because I noticed that WordPad (Windows XP) handles tables much better than my Delphi component. I believe that if I could get WordPad's functionality in my Delphi component my problem would be largely solved. Is it possible that the Delphi component is using RichEd32, yet WordPad is using RichEd20? How can I be certain which version my Delphi component (currently TwwRichEdit from Woll2Woll) is using?
0
 
LVL 3

Expert Comment

by:Octabun
ID: 13586712
To find out what Windows control is used by a Rich Edit component use Spy++ or similar utility (or write your own to enum windows). With Delphi, both 7 and 2K5, TRichEdit should always use RichEd32, just look into the VCL code.

Another link for you: http://jvcl.sourceforge.net. This is project Jedy with lots of components, including TJvRichEdit that uses the best Rich Edit version available.

Yes, it is possible to use TWebBrowser instead of TRichEdit. Implement form in HTML, its logic in Java Script, and use document.external to communicate to the Delphi application.

"WebBrowser customization" MSDN topic is a good starting point. Since relevant interfaces and structures are not translated from C headers to Delphi units, you will need MSDN and Platform SDK any way.

The basic idea is as follows: create a descendent of TWebBrowser and implement IDocHostUIHandler in it. IDocHostUIHandler.GetExternal returns IDispatch that Java Script sees as document.external.

The only issue not covered in MSDN is how IDocHostUIHandler gets to Web browser. Fortunately, the answer is very simple: as soon as you implement IDocHostUIHandler, Delphi COM support framework makes it available through QueryInterface, and TOleControl implements IOleSiteClient and presents it to Web browser. Web browser calls QueryInterface and gets IDocHostUIHandler.
0
 

Author Comment

by:efz
ID: 13594871
To PaulB1989: I've had te weekend to study TRichView and I don't think it's going to do what I ask. I don't know what RTF standard it adheres to but it didn't have the fidelity that I was hoping for. Although cell size and place was accurate, and text was restricted to the intended cell, font formatting was lost, ie., font changes and styles applied within a cell were ignored. Of course that's a big part of our form design, so I don't think TRichView is the answer. I'm not looking for a clone of Microsoft's Word for Windows, but I need something that will render tables at least as accurately as WordPad. Many thanks for your time and attention. LEt me know if anything else comes to mind.
0
 

Author Comment

by:efz
ID: 13595110
To Jacco: If it's not too much trouble, I could email a PDF of the government form along with our RTF version. If you could load it into WPRichEdit component and let me know if the two look reasonably similar, I'd be satisfied. You could also load our RTF file into Word for Windows or WordPad (with WordPad you'll need to set the margins) to compare whether the WPRichEdit component is accurate enough. Let me know if you're interested and, even if you're not,  thank you for all your help anyway.
0
 
LVL 10

Expert Comment

by:Jacco
ID: 13595898
Mail it to Jacco@despammer.com and I'll see what I can do.

Regards Jacco
0
 
LVL 3

Expert Comment

by:Octabun
ID: 13598563
Please note that according to microsoft there are 3 versions of RichEdit. Version numbers of RichEdit20.dll indicate that there are 5. The actual version used depends mainly on the versions of Windows, Word, IE installed.

I looked into the TJvRichEdit code and found that, naturally, new features are added with every new version. TJvRichEdit knows about version 4, so some WorldPad features on Windows XP may be missing.

Correct RichEdit component should look exactly like WordPad. If you are testing WPRichEdit on XP, check for the latest version.

Just in case RichEdit does not work for you, there is another, MSDN/SDK free, way to link HTML form with your application: create an ActiveX object to communicate with your application and use it in JavaScript.
0
 

Author Comment

by:efz
ID: 13604443
To Octabun: You're pushing the limits of my meager skill level, but here's how I followed up on your suggestion. I took a blank form and looked at the interface's "uses" command and noticed that when I added Delphi's TRichEdit control to the form, Delphi added the ComCtrls reference to the "uses" command. I looked up the ComCtrls.pas file and noted a call to RichEdit in its "uses" command. I followed that to the RichEdit.pas file and found the following code:

------------------------------------------
const
  {$EXTERNALSYM cchTextLimitDefault}
  cchTextLimitDefault     = 32767;


  {$EXTERNALSYM RICHEDIT_CLASSA}
  RICHEDIT_CLASSA       = 'RichEdit20A';     { Richedit2.0 Window Class. }
  {$EXTERNALSYM RICHEDIT_CLASSW}
  RICHEDIT_CLASSW       = 'RichEdit20W';     { Richedit2.0 Window Class. }
  {$EXTERNALSYM RICHEDIT_CLASS}
  RICHEDIT_CLASS = RICHEDIT_CLASSA;
  RICHEDIT_CLASS10A       = 'RICHEDIT';        { Richedit 1.0 }

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

Unless I don't understand what I'm reading (which could very well be the case), it looks to me like my Delphi TRichEdit control is NOT using the riched32.dll. Can you tell whether I'm correct about this? If so, how do I change it to utilize the riched32.dll instead of the riched20.dll? I'm excited about this  because it seems possible that making this switch might solve my problem.

Please accept my sincere thanks for any other light you may be able to shed on this issue.
0
 
LVL 3

Expert Comment

by:Octabun
ID: 13608769
I look at the D2K5 code (just trying to decide if it is still OK doing Borland).

When you add TRichEdit to the form, Delphi adds a reference into your form class, like

TRichedit1: TRichEdit;

If you press and hold Ctrl and point on "TRichEdit" with the mouse, it will get underlined as a Web link. Click it when underlined and Delphi will go to the declaration: ComCtrls will be opened and the cursor located at

TRichEdit = class(TCustomRichEdit)

You will see that TRichEdit is exactly TCustomRichEdit with published properties. This is for those who would like to modify TRichEdit: they will inherit from TCustomRichEdit and decide what properties are published themselves.

Do the same link navigation with TCustomRichedit and you will see that it inherits from TCustomMemo, which is the base for all memos and, as such, knows nothing about Windows RichEdit. Thus, all rich edit specific code is in TCustomRichEdit class.

Go to CreateParams member. The parameters for Windows window creation are made there. You will see a constant definition of the TRichEdit library

  RichEditModuleName = 'RICHED32.DLL';

and another constant name of the windows class

  CreateSubClass(Params, 'RICHEDIT');

Thus, Delphi per se is limited to RichEdit1. This can be tested in another way: start a Delphi app containing TRichEdit and look at the libraries it loads. Note TRichEd32.dll.

How come the RichEdit unit knows more? It has the following comments:

{       Copyright (c) 1985-1999, Microsoft Corporation  }
{       Translator: Borland Software Corporation        }

It indicates that this unit is a translation of the Microsoft C/C++ header file found in Platform SDK into Delphi. Yes, Microsoft knows everything about its RichEdit, but Delphi does not use all the knowledge.

For comparison, TJvRichEdit creates parameters as

  case RichEditVersion of
    1:
      CreateSubClass(Params, RICHEDIT_CLASS10A);
  else
    CreateSubClass(Params, RICHEDIT_CLASS);
  end;

So, it knows about 2 RichEdit classes and finds the proper one as

          if GetFileVersionInfo(PChar(FileName), Wnd, InfoSize, VerBuf) then
            if VerQueryValue(VerBuf, '\', Pointer(FI), VerSize) then
            begin
              RichEditVersion := (FI.dwFileVersionMS and $FFFF) div 10;
              if RichEditVersion = 0 then
                RichEditVersion := 2;
            end;

This looks into the version resource of RICHED20.DLL, which on WindowsXP SP2 with Office 2003 is 5.30.23.1221. So, there are 5 versions of RichEdit.

Now I search the Jedy code and see lots of strings like

  if RichEditVersion >= 2 then

with numbers 1 .. 3 and >= and <= operators. So, Jedy code knows about 4 versions of RichEdit.

Hope this helps.

0
 

Author Comment

by:efz
ID: 13632309
To Octabun: I obtained the lastest versions of JEDI's JvRichEdit control and I've come to the following conclusions. None of the RichEdit controls (Delphi's TRichEdit, Woll2Woll's TwwRichEdit, TRichView or JEDI's TJvRichEdit) is good enough at handling tables to do the kind of formatting I require. After reviewing these components I've noticed that the specific problem is always the same, that is, none of these components are able to preserve paragraph formatting within cells. In other words, if you have two or three paragraphs in a cell, even short lines of just a word or two, these components end up stringing the text together in one long line (sans line breaks) and run it right out of the cell boundaries. I thought WordPad handled this adequately, but I was wrong. WordPad has the same deficiency. I tried splitting cells in different ways as well as nesting tables in order to attempt to preserve paragraph formatting, but none of my workarounds worked. Some weren't able to preserve even character formatting and the ones that did couldn't preserve paragraph formatting, so after a year of toying with this problem on and off, I think that your assistance has finally made me realize I've exhausted my possibilities and I should give it up and try another method, i.e,, using HTML files as our form files. You and Jacco have been extremely kind and patient in helping me and for that you have my sincerest thanks.
0
 
LVL 3

Expert Comment

by:Octabun
ID: 13636639
And still the saga is not over. I tested your case (left/right justified, numbered, bulleted paragraphs in table cells, a table in a table): TRichEdit (naturally), TJvRichedit (unfortunately), and .NET RichTextBox (?!) all fail exactly as you describe.

But WordPad works OK!

I decided that something has changed recently and looked into "Platform SDK for Windows XP SP2". Now Microsoft counts 4 versions of RichEdit:

Rich Edit version / DLL / Class name:

1.0 / Riched32.dll / RichEdit
2.0 / Riched20.dll / RichEdit20A or RichEdit20W
3.0 / Riched20.dll / RichEdit20A or RichEdit20W
4.1 / Msftedit.dll / RICHEDIT50W
 
Version 4.1 should be available in Windows XP SP1 and up.

When I forced TRichEdit and TJvRichEdit to load Msftedit.dll and subclass RICHEDIT50W, both displayed tables perfectly. So, it must be possible to fix either component (IMHO, with TJvRichEdit it is easier) to solve your formatting problem. Or just wait until Jedi incorporates SP1 features.

INHO HTML is still the way to go since sooner or later you will need HTML of your forms, say for email, and there is no easy way to convert RTF to HTML.
0
 

Author Comment

by:efz
ID: 13637477
To Octabun: I hear what you're saying about evolving from RTF files to HTML files and I agree whole heartedly. The reasons I would abandon the RTF format with great reluctance is that (1) our company has hundreds of forms already in RTF format, (2) our programs offer a feature that allows the user to send any form to the word processor instead of the printer and the RTF format is handled better than HTML by both Word and WordPerfect, and (3) our forms can be layed out by a non-programmer using Word whereas the HTML versions would require substantially more knowledge on the part of the designer.

You may have noted that I first said WordPad worked okay with tables and then in my last comment I changed my tune saying it didn't. The reason was you hunch that "something has changed recently." I had been doing most of my testing using WordPad in XP (Version 5.1, Build 2600 ... : Serv Pack 2). My last comment was based on using WordPad in Win2000 (Version 5.0, Build 2195, Serv Pack 4).

Programming's changed alot since I began in 1984, and there's a lot I don't know, but your last comment raises two questions:

1. Could you describe in simple-to-follow steps how to "force" the Delphi TRichEdit component to use the latest version of RichEd? We currently use TwwRichEdit but I think I could apply the method if you showed me how to do it with the Delphi component. Actually the ww version is derived from TCustomRichEdit, so I may not have to do anything other than follow your instructions.

2. From a distribution standpoint, if "forced" it as you say, would my resulting program only run correctly on Windows XP machines? In other words, if my users had the correct RichEd dll, could they run our programs as desired even if they were using Windows 98SE for example?
0
 
LVL 3

Accepted Solution

by:
Octabun earned 2000 total points
ID: 13639026
1.

For Delphi 2005 TRichEdit:

Copy  ComCtrls to your project folder, so that your changes are local to the project.

Add ComCtrls to your project, to be sure that your modified file is used instead of Delphi stock ComCtrls.

Go to TCustomRichEdit.CreateParams and edit RichEditModuleName value as "RichEditModuleName = 'MSFTEDIT.DLL';"

Edit the CreateSubclass call as "CreateSubClass(Params, 'RICHEDIT50W');"

Run the project and find out that an exception is raised in TRichEditStrings.Insert. It is sort of saveguard check. Since the code looks reasonable, most likely the version 1.0 check does not hold with version 4.1, so comment it out:

    //if RichEdit.SelStart <> (Selection.cpMax + Length(Str)) then
    //  raise EOutOfResources.Create(sRichEditInsertError);

Now "richEdit.Lines.LoadFromFile(OpenDialog.FileName);" displays correctly formatted table. I do not know if there are other incompatibilities between Delphi version 1.0 code and used version 4.1.

In TJvRichEdit there is code that determines the RichEdit version trying to load RichEd20.dll and creates subclass accordingly. Just forcing it to load MSFTEDIT.DLL does not produce any exceptions, most likely to numerous RichEditVersion checks.

If TwwRichEdit does the same, try to load MSFTEDIT.DLL before RichEd20.dll and subclass RICHEDIT50W on success. This will provide code that will work on any Windows and work correctly on XP SP1 and up.

2.

Since MSFTEDIT.DLL is required for RichEdit to work correctly, yes, it will normally work correctly only on WinXP SP1 and up.

If you look at functions exported by MSFTEDIT.DLL, you will see that most likely it does 2 things: registers the RICHEDIT50W window class with REExtendedRegisterClass, and provides the window procedure for this class with RichEditWndProc.

If it is legal to redistribute MSFTEDIT.DLL with your application, which I doubt, it MAY work on Windows 98 if you a) register the RICHEDIT50W class yourself (trial and error playing with REExtendedRegisterClass parameters, starting with none), or b) do not subclass any Windows controls but use RichEditWndProc from MSFTEDIT.DLL to handle all messages not handled by the TwwRichEdit window procedure (trial and error play with WNDCLASSEX parameters when you register your class). I would estimate the chances of success for this hack at about 25%, so IMHO it is wise to require Windows XP SP1.
0
 

Author Comment

by:efz
ID: 13649042
To Octabun: Good gravy man! I think you're on to something. I did exactly as you said and got the Insert error. When I commented out the line of code you suggested, everything worked. The only flaw I noticed in my admittedly short test is that graphics in cells don't appear. I was using the Delphi component TRichEdit. Unfortunately for me, that shortcoming made the solution ng. I had ready access to the TwwDbRichEdit component (which I've been mistakenly referring to as TwwRichEdit) so I decided to try your solution on that component. I encountered a good omen right off the bat when I noticed while makeing the recommended changes that Woll2Woll had commented out the same code you recommend striking out. Excellent call on your part, Master Octabun. I'm elated to report that the TwwDbRichEdit control presented the embedded bmps fine and in brief testing I could detect no obvious shanks, so I consider your answer to be absolute gold. It worked so well I decided not to try the graphics testing on the JEDI version. The JEDI component also seemed top-notch and might have worked, but Help files were not available (if I understood correctly) and at this time I didn't want to make the investment of time it would take to learn how to use TJvRichEdit.

On the compatibility issue, we have a number of Windows environments on which to test your solution and it seemed to work on all of them so long as they have the msftedit.dll in the the system folder. My programming rarely involves registering classes, so (1) I wasn't able to follow your instructions on this point, and (2) your solution seemed to work without taking your suggested registration steps. Excellent work as far as I'm concerned.

0

Featured Post

Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

Question has a verified solution.

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

Introduction The parallel port is a very commonly known port, it was widely used to connect a printer to the PC, if you look at the back of your computer, for those who don't have newer computers, there will be a port with 25 pins and a small print…
Have you ever had your Delphi form/application just hanging while waiting for data to load? This is the article to read if you want to learn some things about adding threads for data loading in the background. First, I'll setup a general applica…
In this video we outline the Physical Segments view of NetCrunch network monitor. By following this brief how-to video, you will be able to learn how NetCrunch visualizes your network, how granular is the information collected, as well as where to f…
If you’ve ever visited a web page and noticed a cool font that you really liked the look of, but couldn’t figure out which font it was so that you could use it for your own work, then this video is for you! In this Micro Tutorial, you'll learn yo…
Suggested Courses

770 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