How can I create an rtf file?

New to FreeBASIC? Post your questions here.
DonW
Posts: 40
Joined: Feb 16, 2013 0:56
Location: Longview, WA

How can I create an rtf file?

Post by DonW »

I have an application that can print formatted output to printers supporting IBM Proprinter, Epson or HP PCL emulation. The problem is that more and more printers these days do not support any of these emulations...they are designed to use Windows printer drivers. So it occurred to me that if I could change my application to print a formatted .rtf file instead of printing directly to a printer, I could then shell out and have the Windows "Wordpad" program print the formatted document to a designated printer.

So my question is how does one create .rtf formatted documents? Does anyone have examples or could point me to a link showing me how to do it?

Thanks
Imortis
Moderator
Posts: 1926
Joined: Jun 02, 2005 15:10
Location: USA
Contact:

Re: How can I create an rtf file?

Post by Imortis »

DonW
Posts: 40
Joined: Feb 16, 2013 0:56
Location: Longview, WA

Re: How can I create an rtf file?

Post by DonW »

I looked at the link, and all I can say is "WOW"! Microsoft's rtf document specifications are a bit overwhelming to say the least.

I posted this question on another forum and received a suggestion to create some text examples in Wordpad, save the document as .rtf, and open it in Notepad to look at the corresponding rtf formatting code.

My application has minimal print formatting...mainly switching from 10 cpi to 12 or 15 cpi (and back) for some reports and limited use of bold printing. So I'm hoping that it should be relatively easy to flesh out what I need by using the above technique.

Don
TJF
Posts: 3809
Joined: Dec 06, 2009 22:27
Location: N47°, E15°
Contact:

Re: How can I create an rtf file?

Post by TJF »

For printing purposes consider to generate PostScript instead of rtf
led-bloon
Posts: 33
Joined: Jan 06, 2010 8:16

Re: How can I create an rtf file?

Post by led-bloon »

Here is some code snippets from a demo program of a RichEdit control
in RapidFRM form Designer Editor for RapidQ & FreeBASIC.
Hope it helps:

This code takes text in a QRichEdit control and randomly changes each word
with color, size, font etc. The text initially is plain text, but randomly changes
with each successive call to the sub.

Code: Select all

    FontNames(0) = "FixedSys"+CHR$(0): FontNames(1) = "Courier"+CHR$(0)
    FontNames(2) = "Lucida Console"+CHR$(0): FontNames(3) = "Terminal"+CHR$(0)
    FontNames(4) = "MS Serif"+CHR$(0): FontNames(5) = "MS Sans Serif"+CHR$(0)

' Convert plain text to (random) Rich Text Format
SUB RandText(Sender AS QBUTTON)
DIM AS string sText, sFontName=SPACE(LF_FACESIZE)
DIM AS integer i, iLen, iChar, iEffect, iSelStart=0, iSelEnd=0, Addm=0

    iLen = SendMessage (RichEd1.Handle, WM_GETTEXTLENGTH, 0, 0)+1
    IF iLen<= 0 THEN EXIT SUB
    sText=SPACE(iLen)

    IF SendMessage(RichEd1.Handle, WM_GETTEXT, iLen, CAST(LPARAM, STRPTR(sText))) = 0 THEN
        ShowMessage ("ERROR: WM_GETTEXT")
        EXIT SUB
    END IF
    sText=rqReplaceSubStr(sText,CHR(13),"")
    sText=RTRIM(stExt)
    iLen=LEN(sText)

    Randomize(,3)

    CharFormat.cbSize = SIZEOF(CharFormat)
    SendMessage(RichEd1.Handle, EM_GETCHARFORMAT, SCF_DEFAULT, CAST(LPARAM, @CharFormat))
    CharFormat.dwMask = &HFFFFFFFF              ' All = CFM_COLOR Or CFM_BOLD Or CFM_SIZE Or CFM_FAC

    LockWindowUpdate(RichEd1.Handle)
    IF (CINT(sText[0])>32) AND (CINT(sText[0])<127) THEN Addm=True      ' For first char only iSelStart=0
    FOR i=1 TO iLen-1                                                   ' Loop from 2nd char on
        iChar=CINT(sText[i])
        SELECT CASE iChar
            CASE 33 TO 126
                IF Addm=False THEN
                    iSelStart=i-1                                       ' Preceding char - start
                    Addm=True
                END IF
            CASE ELSE
                IF iSelEnd=0 THEN iSelEnd=i                             ' Last char - end marker
        END SELECT
        IF (Addm=True) AND (iSelEnd>0) THEN
            iEffect = 0                                                 ' Add some random special effects?
            IF Int(Rnd * 5) = 0 THEN iEffect = iEffect OR CFE_BOLD
            IF Int(Rnd * 6) = 0 THEN iEffect = iEffect OR CFE_ITALIC
            IF Int(Rnd * 7) = 0 THEN iEffect = iEffect OR CFE_UNDERLINE
            IF Int(Rnd * 8) = 0 THEN iEffect = iEffect OR CFE_STRIKEOUT

            CharFormat.dwEffects = iEffect
            CharFormat.crTextColor = (Int(240 * Rnd) SHL 16) + (Int(240 * Rnd) SHL 8) + Int(240 * Rnd)
            CharFormat.yHeight = 50 + Int(Rnd * 401)                    ' min 50, max 450 : 1440 per inch
            CharFormat.szFaceName = FontNames(Int(RND * 6))

            SendMessage(RichEd1.Handle, EM_SETSEL, iSelStart, iSelEnd)
            IF SendMessage(RichEd1.Handle, EM_SETCHARFORMAT, SCF_SELECTION, CAST(LPARAM, @CharFormat)) = 0 THEN
                ShowMessage("ERROR: EM_SETCHARFORMAT")
                EXIT SUB
            END IF
            iSelStart=0: iSelEnd=0: Addm=False
        END IF
    NEXT i
    LockWindowUpdate(0)
    sText=""
END SUB

Rgds

latent led

[edit] Added more explanation of code snippet
marcov
Posts: 3463
Joined: Jun 16, 2005 9:45
Location: Netherlands
Contact:

Re: How can I create an rtf file?

Post by marcov »

I don't agree with TJF too often, but I now I do. Go postscript or the PDF way.

RTF is an early nineties thing that is nearly dead, no good reason to invest in it now.

If you need to create something Office compatible, using an UNO bridge to Open Office might be an alternative, but only if PS/PDF is out of the question.
dbickin
Posts: 59
Joined: Aug 03, 2005 16:40

Re: How can I create an rtf file?

Post by dbickin »

If your formatting is relatively simple, another alternative would be to generate HTML code, and pass it thru a browser to print. The formatting text to be inserted would be much simpler than RTF, PS, or PDF.

David
DonW
Posts: 40
Joined: Feb 16, 2013 0:56
Location: Longview, WA

Re: How can I create an rtf file?

Post by DonW »

Thanks for the various suggestions. My application is written primarily with QB compatible code. It was born out of the DOS days, but it still runs fine in console mode in a variety of Windows versions. However, it knows nothing of Windows printers. So if writing a simple .rtf file and then shelling Windows Wordpad to print it to a Windows printer can do the trick for the simple formatting that I need, then there is no reason for me to get any more sophisticated. I print reports and labels with my application...no graphics are involved.

I have already created a few simple documents in Wordpad with text in the sizes that my app would output to, for example, an IBM Proprinter. Other than font sizes, the only other formatting I need is bold fonts. In examining these Wordpad documents in Notepad, I see that there is relatively few .rtf format codes that I would need to incorporate in my Basic code to write the necessary .rtf files for printing the reports and labels with Wordpad.

Regards, Don
Imortis
Moderator
Posts: 1926
Joined: Jun 02, 2005 15:10
Location: USA
Contact:

Re: How can I create an rtf file?

Post by Imortis »

When you are finished, it might be interesting to see what you found out here. I would be interested for sure. The info might help others in the future.
marcov
Posts: 3463
Joined: Jun 16, 2005 9:45
Location: Netherlands
Contact:

Re: How can I create an rtf file?

Post by marcov »

DonW wrote:Thanks for the various suggestions. My application is written primarily with QB compatible code. It was born out of the DOS days, but it still runs fine in console mode in a variety of Windows versions.
Win32 console programs afaik should be able to access windows printers just fine?!
MichaelW
Posts: 3500
Joined: May 16, 2006 22:34
Location: USA

Re: How can I create an rtf file?

Post by MichaelW »

marcov wrote:
DonW wrote:Thanks for the various suggestions. My application is written primarily with QB compatible code. It was born out of the DOS days, but it still runs fine in console mode in a variety of Windows versions.
Win32 console programs afaik should be able to access windows printers just fine?!
Using the API you can access the Windows printers, control the font typeface, style, and size, and more or less control the output (see DrawTextEx) but only at a document level. AFAIK any changes within the document, a change in the font for example, must be managed by the app that sends the document text to the printer, using a sequence something like this:
Print the text up to the point of the font change
Select the new font into the printer DC
Print the text in the new font
Select the previous font into the printer DC

Depending on the complexity of the document the process could be cumbersome. For “minimal print formatting” you could embed a simple set of control codes in the documents, and code the app to detect these codes and modify the output accordingly.
counting_pine
Site Admin
Posts: 6323
Joined: Jul 05, 2005 17:32
Location: Manchester, Lancs

Re: How can I create an rtf file?

Post by counting_pine »

DonW wrote:I posted this question on another forum and received a suggestion to create some text examples in Wordpad, save the document as .rtf, and open it in Notepad to look at the corresponding rtf formatting code.
It shouldn't take too long to work that out.
Here's what I came up with as a rough minimum rtf file. It opens in Wordpad, at least:

Code: Select all

{\rtf1
\b This text is bold.\b0\par
\fs20 The text is now font size 10.\par
\fs24 The text is now font size 12.\par
These characters are escaped: "\{\\\}"\par
}
It looks like, unlike HTML, tags don't contain text, rather just change the text formatting from that point. This is noticeable with font size '\fs' tags, but probably applies to other formatting tags too - e.g. '\b' makes the text bold; '\b0' makes the text "unbold". It seems font sizes need to be doubled, e.g. '\fs24' for size 12.

Document tags seem to need either a space or another tag following. '{', '}' and '\' (and perhaps others) need to be escaped by a preceding '\'.

Font faces are slightly harder, and will probably involve a larger header and a little more reverse-engineering.

I can't say much about the elegance or reliability of this method, or compare with other options like PostScript or TeX. Though if something goes wrong, HTML will probably be easiest to debug or find help with.
MichaelW
Posts: 3500
Joined: May 16, 2006 22:34
Location: USA

Re: How can I create an rtf file?

Post by MichaelW »

This demonstrates the basic idea, but it leaves out the file handling and some things that a practical application would need to do. In my test a 48-point font was necessary to get the characters up to a reasonable size on my 600-dpi LaserJet. If sizing the font by trial is not workable, the size can be calculated from the available metrics. The layout and font sizing would be easier to manage with a fixed-pitch font.

Code: Select all

''=============================================================================
#include "windows.bi"
#include "win\winspool.bi"
''=============================================================================

''--------------------------------------------------------------------------
'' This function returns the system-defined error string for the last-error
'' code value.
''
'' Note that the last-error code value is meaningful only immediately after
'' a function that sets the last-error code value returns an error. See the
'' function documentation to determine if the function does so.
''
'' Note also that you cannot depend on subsequent successful function calls
'' to clear the last-error code value. To reliably clear the value call the
'' SetLastError function with the dwErrCode parameter set to ERROR_SUCCESS.
''--------------------------------------------------------------------------

function LastErrorStr() as string
    dim as string * 1024 buffer
    dim as integer p
    FormatMessage( FORMAT_MESSAGE_FROM_SYSTEM,_
                   0,_
                   GetLastError(),_
                   0,_
                   strptr( buffer ),_
                   1024,_
                   0 )
    buffer = rtrim( buffer )
    p = instr( buffer, chr(13) )
    if p then buffer = left( buffer, p - 1 )
    return buffer
end function

''=============================================================================

function MakeFont( byval pointSize as integer, _
                    byval fnWeight as integer, _
                    byval fdwItalic as BOOL, _
                    byval lpszFace as zstring ptr ) as HFONT
    dim as integer nHeight
    dim as HDC hdc
    hdc = GetDC( 0 )
    nHeight = -MulDiv( pointSize, GetDeviceCaps( hdc, LOGPIXELSY), 72)
    ReleaseDC( 0, hdc )
    return CreateFont( nHeight, _
                        0, _
                        0, _
                        0, _
                        fnWeight, _
                        fdwItalic, _
                        0, _
                        0, _
                        DEFAULT_CHARSET, _
                        OUT_TT_PRECIS, _
                        CLIP_DEFAULT_PRECIS, _
                        PROOF_QUALITY, _
                        DEFAULT_PITCH or FF_DONTCARE, _
                        lpszFace )
end function

''=============================================================================

dim as HDC hdcPrinter
dim as HFONT hFont, hFontBold, hFontDef
dim as DOCINFO di
dim as SIZE szMetric
dim as zstring * 100 printerName
dim as integer i = 100
dim as string docName = "test doc"
dim as string sample = "my other brother darryl"

''--------------------------------------
'' Get the name of the default printer.
''--------------------------------------

if GetDefaultPrinter( @printerName, @i ) = 0 then
    print "GetDefaultPrinter ";LastErrorStr()
else
    print printerName
end if

''---------------------------
'' Get a DC for the printer.
''---------------------------

hdcPrinter = CreateDC( "WINSPOOL", @printerName, NULL, NULL )
if hdcPrinter = 0 then
    print "CreateDC ";LastErrorStr()
end if

''-----------------------------------------------------
'' Get handles for two fonts, one normal and one bold.
''-----------------------------------------------------

hFont = MakeFont( 48, FW_NORMAL, 0, "Comic Sans MS" )
if hFont = 0  then
    print "MakeFont ";LastErrorStr()
end if
hFontBold = MakeFont( 48, FW_BOLD, 0, "Comic Sans MS" )
if hFontBold = 0 then
    print "MakeFont ";LastErrorStr()
end if

''------------------------------------------------------------
'' Initialize the necessary members of the DOCINFO structure.
''------------------------------------------------------------

di.cbSize = sizeof(DOCINFO)
di.lpszDocName = strptr(docName)

''--------------------
'' Start a print job.
''--------------------

if StartDoc( hdcPrinter, @di ) <= 0 then
    print "StartDoc ";LastErrorStr()
end if

''--------------------------------------------
'' Prepare the printer driver to accept data.
''--------------------------------------------

if StartPage( hdcPrinter ) <= 0 then
    print "StartPage ";LastErrorStr()
end if

''-----------------------------------------------------------------------
'' Select the normal font into the printer DC and save the default font.
''-----------------------------------------------------------------------

hFontDef = SelectObject( hdcPrinter, hFont )

''------------------------------------------------
'' Get the width and height of the sample string.
'' Note that the values depend on the font that
'' is selected into the DC.
''------------------------------------------------

if GetTextExtentPoint32( hdcPrinter, strptr(sample), _
                                     len(sample), @szMetric ) = 0 then
    print "GetTextExtent... ";LastErrorStr()
end if

''---------------------------------------------------
'' Display the sample text 2 lines down on the page.
''---------------------------------------------------

TextOut( hdcPrinter, 0, szMetric.cy * 2, strptr(sample), len(sample) )

''---------------------------------------------------
'' Select the default font back into the printer DC.
''---------------------------------------------------

SelectObject( hdcPrinter, hFontDef )

''---------------------------------------------------------------------
'' Select the bold font into the printer DC and save the default font.
''---------------------------------------------------------------------

hFontDef = SelectObject( hdcPrinter, hFontBold )

''-----------------------------------------------------
'' Display the sample text 4 lines down on the page.
''-----------------------------------------------------

TextOut( hdcPrinter, 0, szMetric.cy * 4, strptr(sample), len(sample) )

''---------------------------------------------------
'' Select the default font back into the printer DC.
''---------------------------------------------------

SelectObject( hdcPrinter, hFontDef )

''----------------------------------------------------------------------
'' Notify the printer driver that we have finished writing to the page.
''----------------------------------------------------------------------

EndPage( hdcPrinter )

''--------------------
'' End the print job.
''--------------------

EndDoc( hdcPrinter )

''-------------------
'' Delete the fonts.
''-------------------

DeleteObject( hFont )
DeleteObject( hFontBold )

''------------------------
'' Delete the printer DC.
''------------------------

DeleteDC( hdcPrinter )

sleep
RockTheSchock
Posts: 252
Joined: Mar 12, 2006 16:25

Re: How can I create an rtf file?

Post by RockTheSchock »

dbickin wrote:If your formatting is relatively simple, another alternative would be to generate HTML code, David
You can generate a simple HTML file. Execute the html file with shell so that the standard browser opens that file. If you insert a little javascript snippet it opens the print dialog immediatly after load.

Code: Select all

<html>
<head>
.....
<script type="text/javascript">
window.print();
</script>
</head>
<body>
...
</body>
</html>
DonW
Posts: 40
Joined: Feb 16, 2013 0:56
Location: Longview, WA

Re: How can I create an rtf file?

Post by DonW »

After much experimentation, I have discovered that Wordpad is not a very good command line print client for *.rtf documents. The main drawback is the fact that unlike MS Word (and other word processing programs), Wordpad does not respect .rtf page formatting codes. It's page size, margins, etc, are fixed by whatever the user has set in the program's "page setup", and it does not allow them to be overridden with page format codes embedded in the .rtf document.

A few posters in this thread have suggested using html. I have looked into that as well, because all versions of Windows have Microsoft's Internet Explorer which can be called from the command line with "RUNDLL32.EXE MSHTML.DLL,PrintHTML "path\filename" to print an html document. But so far after experimenting with this approach, I find that it is still difficult, if not impossible, to embed page format controls for a client designed to print web pages and not page formatted documents. But maybe I'm just missing something with this approach.

Don
Post Reply