[Okta Webinar] Learn how to a build a cloud-first strategyRegister Now


Need Third Party RTF Control for VB6 Compatible with 98/2000/NT/XP

Posted on 2005-04-09
Medium Priority
Last Modified: 2013-11-22
I have been using the Microsoft Rich Textbox Control 6.0 (Richtx32.ocx) for printing RTF files after replacing some text. I am running into some limitations such as support for page breaks and inverted text colors. I have found some third party controls that range in price from about $250 to $500. Does anyone have any recomendations? I only need to be able to load the control with a stream of RTF text and print it. Editing and displaying text is a nice-to-have but not a requirement. No other features such file conversions are required. Budget is tight so I would like to get something at the $250 mark or lower.

Question by:zorvek (Kevin Jones)
  • 2
  • 2
LVL 22

Accepted Solution

danaseaman earned 1500 total points
ID: 13746570
Try Edanmos' free RichEdit at this Link: http://www.mvps.org/emorcillo/en/code/vb6/index.shtml and http://www.mvps.org/emorcillo/download/vb6/ctl_riched.msi . It may throw a Bad Implements error on first compile. Turn off Binary compatability, compile and then turn it back on and it should then work. Also make sure you are using Vb6 and at least ServicePack 5.
Don't forget to download and register dependencies OleLib.tlb and OleLib2.Tlb.
If you need any help with this let me know. I have been using it for over 2 years.
LVL 81

Author Comment

by:zorvek (Kevin Jones)
ID: 13749096

The control handles page breaks better than Richtx32.ocx but not still not correctly. An inserted page break does cause a new page to be started but the line counter is not reset so the control still puts an automatic page break in where it would have been had I not inserted the page break. In other words, if I have an RTF document that is one and a half pages long then without an inserted page break the control creates an automatic break two thirds down. If I insert a page break one third down then that page break causes a new page to be started but the control still generates a page break two thirds down the document. The end result is three pages versus two.

Do you have a work-around that solves this problem?

Another thing I noticed is that it does not support shaded table cells.

LVL 22

Expert Comment

ID: 13749394
I looked at the code in Public Sub PrintRange() and I can see that they are building an array of pages without checking for embedded page breaks. I don't have a workaround for this but I suspect it could be done by modifying the code in PrintRange.
LVL 81

Author Comment

by:zorvek (Kevin Jones)
ID: 14363505
Given my innability to find a reasonable rtf printing tool I have decided to take a different path. I also needed to text stamp and print pdf documents and, since I have found a good solution in that department, have decided to convert my existing rtf documents to pdf and go from there.

I'll accept the reference to Edanmos' free RichEdit since others may not have as stringent requirements as I do. I also will post the workaround I developed to handle page breaks. To handle manually inserted page breaks I use my own marker I insert into the rtf text:

Private Type tRect
   Left As Long
   Top As Long
   Right As Long
   Bottom As Long
End Type

Private Type tCharRange
   cpMin As Long      ' First character of range (0 for start of doc)
   cpMax As Long      ' Last character of range (-1 for end of doc)
End Type

Private Type tFormatRange
   hdc As Long        ' Actual DC to draw on
   hdcTarget As Long  ' Target DC for determining text formatting
   rc As tRect        ' Region of the DC to draw to (in twips)
   rcPage As tRect    ' Region of the entire DC (page size) (in twips)
   chrg As tCharRange ' Range of text to draw (see above declaration)
End Type

Private Const WM_USER As Long = &H400
Private Const EM_FORMATRANGE As Long = WM_USER + 57
Private Const EM_SETTARGETDEVICE As Long = WM_USER + 72
Private Const PHYSICALOFFSETX As Long = 112
Private Const PHYSICALOFFSETY As Long = 113
Private Const mPageBreakTag = "\_PageBreak_\"

Private Declare Function GetDeviceCaps Lib "gdi32" ( _
   ByVal hdc As Long, ByVal nIndex As Long) As Long
Private Declare Function SendMessage Lib "user32" Alias "SendMessageA" ( _
   ByVal hwnd As Long, _
   ByVal msg As Long, ByVal wp As Long, _
   lp As Any) As Long
Private Declare Function CreateDC Lib "gdi32" Alias "CreateDCA" ( _
   ByVal lpDriverName As String, _
   ByVal lpDeviceName As String, _
   ByVal lpOutput As Long, _
   ByVal lpInitData As Long) As Long

Public Sub PrintRTF( _
   RTFText As String, _
   rtbPrint As RichTextBox, _
   LeftMarginInches As Single, _
   TopMarginInches As Single, _
   RightMarginInches As Single, _
   BottomMarginInches As Single)

' Prints RTFText to default printer using the provided RichTextBox control. The control must be created on an
' existing form. Include the Microsoft Rich Textbox Control to access.

   Dim LeftMarginTwips As Long
   Dim TopMarginTwips As Long
   Dim RightMarginTwips As Long
   Dim BottomMarginTwips As Long
   Dim LeftOffset As Long
   Dim TopOffset As Long
   Dim LeftMargin As Long
   Dim TopMargin As Long
   Dim RightMargin As Long
   Dim BottomMargin As Long
   Dim FormatRange As tFormatRange
   Dim DrawToRect As tRect
   Dim PageRect As tRect
   Dim TextLength As Long
   Dim NextPageCharPos As Long
   Dim NextPageBreakCharPos As Long
   Dim PageBreakTagFound As Boolean

   ' Start print job
   Printer.Print Space(1)
   Printer.ScaleMode = vbTwips
   ' Convert the margins from inches to twips
   LeftMarginTwips = Printer.ScaleX(LeftMarginInches, vbInches)
   TopMarginTwips = Printer.ScaleY(TopMarginInches, vbInches)
   RightMarginTwips = Printer.ScaleX(RightMarginInches, vbInches)
   BottomMarginTwips = Printer.ScaleY(BottomMarginInches, vbInches)

   ' Get offset to printable area
   LeftOffset = Printer.ScaleX(GetDeviceCaps(Printer.hdc, PHYSICALOFFSETX), vbPixels, vbTwips)
   TopOffset = Printer.ScaleY(GetDeviceCaps(Printer.hdc, PHYSICALOFFSETY), vbPixels, vbTwips)

   ' Calculate margins
   LeftMargin = LeftMarginTwips - LeftOffset
   TopMargin = TopMarginTwips - TopOffset
   RightMargin = (Printer.Width - RightMarginTwips) - LeftOffset
   BottomMargin = (Printer.Height - BottomMarginTwips) - TopOffset

   ' Set printable area rect
   PageRect.Left = 0
   PageRect.Top = 0
   PageRect.Right = Printer.ScaleWidth
   PageRect.Bottom = Printer.ScaleHeight

   ' Set rect in which to print which is relative to printable area
   DrawToRect.Left = LeftMargin
   DrawToRect.Top = TopMargin
   DrawToRect.Right = RightMargin
   DrawToRect.Bottom = BottomMargin

   ' Set up the print instructions
   FormatRange.hdc = Printer.hdc
   FormatRange.hdcTarget = Printer.hdc
   FormatRange.rc = DrawToRect
   FormatRange.rcPage = PageRect
   FormatRange.chrg.cpMin = 0
   FormatRange.chrg.cpMax = -1

   ' Get length of text in RTF control
   TextLength = Len(rtbPrint.Text)
   ' Print each page until done
      PageBreakTagFound = False
      NextPageBreakCharPos = InStr(FormatRange.chrg.cpMin + 1, rtbPrint.Text, mPageBreakTag)
      If NextPageBreakCharPos > 0 Then
         ' Inserted page break found
         PageBreakTagFound = True
         ' Instruct control to only print to that point
         FormatRange.chrg.cpMax = NextPageBreakCharPos - 1
         ' Move back over line feeds and carraige returns
         While Mid(rtbPrint.Text, FormatRange.chrg.cpMax + 1, 1) = vbCr Or Mid(rtbPrint.Text, FormatRange.chrg.cpMax + 1, 1) = vbLf
            FormatRange.chrg.cpMax = FormatRange.chrg.cpMax - 1
         ' Instruct control to print to end of document of page, whichever is first
         FormatRange.chrg.cpMax = -1
      End If
      ' Print the page by sending EM_FORMATRANGE message; Message returns next character position to print
      NextPageCharPos = SendMessage(rtbPrint.hwnd, EM_FORMATRANGE, True, FormatRange)
      ' If next character is beyond end of document then exit loop
      If NextPageCharPos >= TextLength Then Exit Do
      ' Next start is after inserted page break or after end of last printed page, whichever is first
      FormatRange.chrg.cpMin = IIf(PageBreakTagFound, NextPageBreakCharPos + Len(mPageBreakTag) - 1, NextPageCharPos)
      ' Skip any line feeds and carraige returns
      While Mid(rtbPrint.Text, FormatRange.chrg.cpMin + 1, 1) = vbCr Or Mid(rtbPrint.Text, FormatRange.chrg.cpMin + 1, 1) = vbLf
         FormatRange.chrg.cpMin = FormatRange.chrg.cpMin + 1
      ' Start new page
      ' Initialize hDC
      Printer.Print Space(1)
      FormatRange.hdc = Printer.hdc
      FormatRange.hdcTarget = Printer.hdc

   ' Commit job

   ' Free memory
   SendMessage rtbPrint.hwnd, EM_FORMATRANGE, False, ByVal CLng(0)

End Sub


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

Introduction While answering a recent question about filtering a custom class collection, I realized that this could be accomplished with very little code by using the ScriptControl (SC) library.  This article will introduce you to the SC library a…
Introduction Raise your hands if you were as upset with FireMonkey as I was when I discovered that there was no TListview.  I use TListView in almost all of my applications I've written, and I was not going to compromise by resorting to TStringGrid…
Get people started with the process of using Access VBA to control Outlook using automation, Microsoft Access can control other applications. An example is the ability to programmatically talk to Microsoft Outlook. Using automation, an Access applic…
Show developers how to use a criteria form to limit the data that appears on an Access report. It is a common requirement that users can specify the criteria for a report at runtime. The easiest way to accomplish this is using a criteria form that a…
Suggested Courses
Course of the Month19 days, 16 hours left to enroll

873 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