Using a RichTextEdit control – PB Docs 70

Using a RichTextEdit control

A RichTextEdit control in a window or user object lets the
user view or edit formatted text. Functions allow you to manipulate
the contents of the control by inserting text, getting the selected
text, managing input fields, and setting properties of all or some
of the contents.

You define RichTextEdit controls in the Window painter or
the User Object painter.

Giving the user control

In the Window or User Object painter, on the Document page
of the RichTextEdit control’s property sheet, you can enable
or disable:

  • Editing bars (a toolbar for text formatting, a ruler bar, and a tab bar
    for setting tabs)
  • A popup menu (provides access to the Insert File and clipboard commands,
    as well as the property sheet)
  • Display of nonprinting characters (carriage returns, tabs, and spaces)
  • Display of fields (whether they are visible at all or whether the field name
    or data displays) and a background color for fields
  • Wordwrap
  • Margins for printing relative to the default page size

You can also specify a name for the document that is displayed
in the print queue. The document name has nothing to do with a text
file you might insert in the control.

note.gif About word wrap The word wrap setting only affects newly entered text. If
the user enters new text in an existing paragraph, word wrap is
triggered when the text reaches the right edge of the control.

To get existing text to wrap within the display, the user
can tweak the size of the control (if it is resizable).

Users can change the available tools

When users display the property sheet for the rich text document,
they can change the tools that are available to them, which you
may not want. For example, they might:

  • Remove the display-only setting so that they can
    begin editing a document you set up as protected
  • Turn off the tool, ruler, or tab bars
  • View input fields names instead of data
  • Disable the popup menu so that they cannot restore
    tools they turn off

You may want to guard against some of these possibilities.
You can reset the property values for these settings in a script.
For example, this statement restores the popup menu when assigned
to a CommandButton:

Undoing changes

You can enable an undo feature in your application by setting
the UndoDepth property. The user can press ctrl+z to
undo a change. You can also program a button or menu item that calls
the Undo function.

If Undo is called repeatedly, it continues to undo changes
to the maximum number of changes specified in UndoDepth. The script
can check whether there are changes that can be undone (meaning
UndoDepth has not been reached) by calling the CanUndo function:

Text for the control

In the Window painter, you do not enter text in the control.
Instead, in your application, you can programmatically insert text
or let the user enter text using the editing tools.

Inserting text

From a file If you have prepared a text file for your application, you
can insert it with the InsertFile function. The file can be rich
text or ASCII:

The boolean clearflag argument lets you
specify whether to insert the file into existing text or replace

From a database If you have saved rich text as a string in a database, you can
use a DataStore to retrieve the text.

After retrieving data, paste the string into the RichTextEdit

note.gif Rich text and the clipboard The CopyRTF and PasteRTF functions let you get rich text with
formatting instructions

and store it in a string. If
you use the clipboard via the Copy, Cut, and Paste functions, you
get the text only–the formatting is lost.

Example of saving rich text in a database

Suppose you have a database table that records tech support
calls. Fields record the call’s date, support engineer,
and customer. Another field stores notes about the call. You can
let the user record notes with bold and italic formatting for emphasis
by storing rich text instead of plain text.

The window for editing call information includes these controls:

  • A DataWindow control that
    retrieves all the data and displays everything except the call notes
  • A RichTextEdit control that displays the call notes
  • A button for updating the database

RowFocusChanged event As row focus changes, the notes for the current row are pasted
into the RichTextEdit control. The RowFocusChanged event has this

LoseFocus event When the user makes changes, the changes are transferred to
the DataWindow control. It is assumed that the user will click on
the button or the DataWindow control when the user is through editing,
triggering the LoseFocus event, which has this script:

note.gif LoseFocus and the toolbars A LoseFocus event occurs for the RichTextEdit control even
when the user clicks a RichTextEdit toolbar. Technically, this is
because the toolbars are in their own windows. However, the RichTextEdit
control still has focus, which you can check with the GetFocus function.

Saving rich text in a file

You can save the rich text in the control, with the input
field definitions, with the SaveDocument function. You have the
choice of rich text format (RTF) or ASCII:

SaveDocument does not save the data in the input fields. It
saves the document template.

Does the file exist? If the file exists, calling SaveDocument triggers the FileExists
event. In the event script, you might ask the user if they want
to overwrite the file.

To cancel the saving process, specify a return code of 1 in
the event script.

Are there changes that need saving? The Modified property indicates whether any changes have been
made to the contents of the control. It indicates that the contents
are in an unsaved state. When the first change occurs, PowerBuilder triggers
the Modified event and sets the Modified property to TRUE. Calling
SaveDocument sets Modified to FALSE, indicating that the document
is clean.

Opening a file triggers the Modified event and sets the property
because the control’s contents changed. Usually, though,
what you really want to know is whether the contents of the control
still correspond to the contents of the file. Therefore, in the
script that opens the file, you can set the Modified property to FALSE
yourself. Then when the user begins editing, the Modified event
is triggered again and the property is reset to TRUE.

Opening and saving files: an example

This example consists of several scripts that handle opening
and saving files. The user can open existing files and save changes.
They can also save the contents to another file. If users save the
file they opened, saving proceeds without interrupting the user.
If users save to a filename that exists, but is not the file they
opened, they are asked whether to overwrite the file:


The example includes instance variable declarations, scripts,
functions, and events.

Instance variable declarations

ib_saveas A flag for the FileExists event. When FALSE, the user is saving to
the same file they opened so overwriting is expected:

is_filename The current filename for the contents, initially set to “Untitled”:

Open Document script

This script opens a file chosen by the user. Since opening
a file triggers the Modified event and sets the Modified property,
the script resets Modified to FALSE. The Checked property of the
Modified checkbox is set to FALSE too:

Scripts that save the document

The user might choose to save the document to the same name
or to a new name. These scripts could be assigned to menu items
as well as buttons.

The Save button script checks whether the instance variable
is_filename holds a valid name. If so, it passes that filename
to the of_save function. If not, it triggers the SaveAs
button’s script instead:

The SaveAs script sets the instance variable ib_saveas
so that the FileExists event, if triggered, knows to ask about overwriting
the file. It calls of_getfilename to prompt for a filename
before passing that filename to the of_save function.

Functions for saving and getting a filename

of_save function This function accepts a filename argument and saves the document.
It updates the filename instance variable with the new name and
sets the checkbox to correspond with the Modified property, which
is automatically set to FALSE after you call SaveDocument successfully:

of_getfilename function The function prompts the user for a name and returns the filename
the users selects. It is called when a filename has not yet been
specified or when the user chooses Save As. It returns a filename:

Events for saving and closing

FileExists event When the user has selected a filename and the file already exists,
this script warns the user and allows the save to be canceled. The
event occurs when SaveDocument tries to save a file and it already
exists. The script checks whether ib_saveas is TRUE and,
if so, asks if the user wants to proceed with overwriting the existing

Modified event This script sets a checkbox so the user can see that changes have
not been saved. The Modified property is set automatically when
the event occurs. The event is triggered when the first change is
made to the contents of the control:

CloseQuery event This script for the window’s CloseQuery event checks whether
the control has unsaved changes and asks whether to save the document
before the window closes:

Formatting of rich text

In a RichText control, there are several user-addressable

  • The whole document
  • Selected text and paragraphs
  • Input fields
  • Pictures

The user can make selections, use the toolbars, and display
the property sheets for these objects.

Input fields get values either because you or the user specify
a value or because you have called DataSource to associated the
control with a DataWindow object or DataStore.

Input fields

An input field is a named value. You name it and you determine
what it means by setting its value. The value is associated with
the input field name–you can have several fields with the
same name and they will all display the same value. If the user
edits one of them, they all will change.

In this sample text, an input field for the customer’s
name is repeated throughout:

  • Hello {customer}!
  • We know that you, {customer},
    will be excited about our new deal. Please call soon, {customer},
    and save money now.

In a script, you can set the value of the customer field:

Then the text would look like this:

  • Hello Mary!
  • We know that you, Mary, will be excited about our
    new deal. Please call soon, Mary, and save money now.

The user can also set the value. There are two methods:

  • Selecting it (clicking
    it so that it flashes) and typing a new value
  • Displaying the Input Field property sheet and editing
    the Data Value textbox

Inserting input fields in a script The InputFieldInsert function inserts a field at the insertion

In a rich text editing application, you might want the user
to insert input fields. The user needs a way to specify the input
field name.

In this example, the user selects a name from a ListBox containing
possible input field names. The script inserts an input field at
the insertion point using the selected name:

Input fields for dates and page numbers

To display a date or a page number in a printed document,
you define an input field and set the input field’s value.

proc.gif To include today’s date in the opening
of a letter, you might:

  1. Create an input field in the text. Name
    it anything you want.

  2. In the script that opens the window or some other
    script, set the value of the input field to the current date.

For example, if the body of the letter included an input field
called TODAY, you would write a script like the following to set

For information about setting page number
values when printing, see “Preview and printing”.

Using database data

You can make a connection between a RichTextEdit control and
a DataWindow control or DataStore object. When an input field in
the RichTextEdit control has the same name as a column or computed
column in the DataWindow object, it displays the associated data.

Whether or not the RichTextEdit control has a data source,
there is always only one copy
of the rich text
content. While editing, you might visualize the RichTextEdit contents
as a template into which row after row of data can be inserted.
While scrolling from row to row, you might think of many instances of
the document in which the text is fixed but the input field data

To share data between a DataWindow object or DataStore, use
the DataSource function:

Example of sharing data

If the DataWindow object associated with the DataStore ds_empdata
has four columns: emp_id, emp_lname, emp_fname,
and state, the RichTextEdit content might include text and input
fields like this:

note.gif Sample letter with columns from the employee table ID: {emp_id}

Dear {emp_fname} {emp_lname}:
We are opening a new plant in Mexico. If you would like to
transfer from {state} to Mexico, the company will
cover all expenses.

Navigating rows and pages

For the RichTextEdit control, navigation keys let the user
move among the pages of the document. However, you must provide
scrolling controls so that the user can move from row to row.

You will want to provide Prior Row and Next Row buttons. The
scripts for the buttons are simple. For Next Row:

For Prior Row:

If you also provide page buttons, then when the user is on
the last page of the document for one row, scrolling to the next
page moves to the first page for the next row:

Cursor position in the RichTextEdit control

Functions provide several ways to find out what is selected
and to select text in the RichTextEdit control.

Where is the insertion point or what is selected?

The text always contains an insertion point and it can contain
a selection, which is shown as highlighted text. When there is a
selection, the position of the insertion point can be at the start
or the end of the selection, depending on how the selection is made.
If the user drags from beginning to end, the insertion point is
at the end. If the user drags from end to beginning, the insertion
point is at the beginning.

The Position function provides information about the selection
and the insertion point.

For more information, see Position in the PowerScript


Selecting text programmatically

There are several functions that select portions of the text
relative to the position of the insertion point:

  • SelectTextWord
  • SelectTextLine
  • SelectTextAll

A more general text selection function is SelectText. You
specify the line and character number of the start and end of the

Passing values to SelectText Because values obtained with Position provide more information
than simply a selection range, you cannot pass the values directly
to SelectText. In particular, zero is not a valid character position when
selecting text, although it is meaningful in describing the selection.

For more information, see Position in the PowerScript


For an example of selecting words one by one
for the purposes of spellchecking, see the SelectTextWord function
in the PowerScript Reference

Tab order, focus, and the selection

Tab order For a window or user object, you include the RichTextEdit
control in the tab order of controls. However, after the user tabs
to the RichTextEdit control, pressing the tab key
inserts tabs into the text. The user cannot tab out to other controls.
Keep this in mind when you design the tab order for a window.

Focus and the selection When the user tabs to the RichTextEdit control, the control
gets focus and the current insertion point or selection is maintained.
If the user clicks the RichTextEdit control to set focus, the insertion
point moves to the place the user clicks.

Therefore, although the selection is maintained when the user
changes focus to another control, the user cannot return focus to
the control without changing the selection.

LoseFocus event When the user clicks on a RichTextEdit toolbar, a LoseFocus
event occurs. However, the RichTextEdit control still has focus. You
can check whether the control has lost focus with the GetFocus function.

Preview and printing

The user can preview the layout and print the contents of
the RichTextEdit control.

Previewing the layout

The user can preview the document layout in preview mode.
In preview mode, users see a view of the document, reduced so that
it fits in the control. If the control is small, the preview will
be tiny:


Users can use preview mode to:

  • Set document margins
  • View all the pages using the scrolling arrows
    If the RichTextEdit control is sharing data with a DataWindow
    object, preview shows only the first row of data merged with the

There are two ways to enter preview mode:

  • The user can press ctrl+f2 to
    switch between editing and preview mode
  • You can call the Preview function in a script


If the RichTextEdit is using DataWindow object data, you can
limit the number of rows that are printed by setting the Print.Page.Range
property for the DataWindow control. Its value is a string that
lists the page numbers that you want to print. A dash indicates
a range.

Example of a page range Suppose your RichTextEdit control has a data source in the
control dw_source. Your rich text document is three pages
and you want to print the information for rows 2 and 5. You can
set the page range property before you print:

You can also filter or discard rows so they won’t
be printed.

For more information, see the SetFilter, Filter,
RowsMove, and RowsDiscard functions in the PowerScript

and the Print DataWindow object property in
the DataWindow Reference

Setting the page number

To print page numbers, you can use an input field in the header
or footer.

proc.gif To include a page number in the header or footer,
you might:

  1. Create an input field in the header or
    footer. Name it anything you want.

  2. In the script for the PrintHeader or PrintFooter
    event, set the value of the input field to the current page.

You decide how you want to number the pages. The event has
three arguments that you can use to calculate the page number. You
might use the value of the currentpage argument
with no alteration or you might restart page numbering for each
row of data.

Continuous numbering For example, suppose the footer of the document included text
with two input fields called PAGE and TOTAL:

In the PrintFooter event, write a script like the following
to set the values:

Restarting numbering for each row If you wanted to restart page numbering for each row, the
footer might look like this:

As before, the script for PrintFooter sets the values. The
value for page is derived from the arguments passed to the script
(assuming there is the same number of pages for each row).

Inserting footer text programmatically

This sample code sets the insertion point in the footer and
inserts two blank lines, text, and two input fields:

Document get from Powerbuilder help
Thank you for watching.
Was this article helpful?
Notify of
Inline Feedbacks
View all comments
Would love your thoughts, please comment.x