Pen for OS/2 Version 1.03: Text Entry Control Data

by Mario Galliano

On this volume of The Developer Connection for OS/2, you'll find Pen for OS/2 Version 1.03. This version has been enhanced to include features that let you customize text-entry windows in your application.

This article explains the Presentation Manager data structures used by Pen for OS/2 to control text-entry windows, and also provides examples of how to program to these new Pen features.

Note: To run Pen for OS/2 Version 1.03, you must have OS/2 Warp installed on your system.

First, let's take a look at some of the enhancements included in Version 1.03 of the Pen for OS/2 product:
 * You can write and edit directly in OS/2 multi-line entry (MLE) field control windows, single-line entry (SLE) field control windows, spin button control windows, and prompted entry field control windows ("combo" boxes).
 * You can write directly in a DOS command window, an OS/2 command window, and WIN-OS/2, DOS, and OS/2 windows that have an "I-beam" pointer.
 * For programs that are started from an object, Pen for OS/2 provides an Overrides page in the object's Settings notebook where you can select an entry method: force gesture only, force text only, or force gesture and text. This lets you write directly into any text window, even if the window does not have an I-beam pointer.
 * You can copy your personal handwriting style to multiple computers. This means you don't have to "train" each computer you use, but only train your personal handwriting style once and then copy the style to other computers that you use.
 * You can select the size and type of Handwriting Pad you prefer--either a boxed pad, a lined pad, or an unlined pad.
 * You can now communicate with Telepen using a modem or serial-cable connection in addition to the network support.
 * A Keystroke Recorder option makes it easy to assign a keystroke to a gesture.
 * You can display the Pen Toolbar vertically or horizontally.

Pen for OS/2 Version 1.03 automatically provides writing and editing support in applications that use standard Presentation Manager (PM) controls for data input. All MLE field control windows, SLE field control windows, spin button control windows, and combo boxes are aware of Pen for OS/2 1.03, without you having to change your OS/2 Warp application. However, you can control the following Pen functions:
 * Color and width of ink
 * The mode, color, and width of lines in entry fields
 * Text recognition constraints, such as numerical or all-caps only entry input

The New Pen Data Structures
You can implement the new features of Pen for OS/2 Version 1.03 three ways:
 * You can pass a Pen control data at WinCreateWindow time.
 * Send Pen PM messages to the controls.
 * Use the Universal Resource Editor (URE). (Refer to the article titled "New Tool: Universal Resource Editor" in this issue of The Developer Connection News.)

All of the PM text entry control data structures have been expanded to support Pen. They include the following: PVOID pHWXCtlData;   /* reserved for Pen CtlData (penpm.h)  */

To make the Pen control structure easier to use with the PM text entry controls, Pen for OS/2 has defined typedefs in the PENPM.H file. (PENPM.H is located in the Developer's Toolkit for OS/2 Warp on your accompanying Developer Connection for OS/2 CD-ROMs.)

Understanding the Data Structures
This section describes some of the elements of the Pen control data structure. I have tried to provide helpful details and hints about using these elements. You can also find information about them in the Pen for OS/2 Programming Guide and Reference, which is on your accompanying Developer Connection for OS/2 CD-ROMs.


 * ULONG ulVersion is the Pen for OS/2 version. The low two bytes are for the Pen version and the high two bytes are for control flags. The following flags can be ORed together:
 * PEN_DIALOG_UNIT tells the control if the elements arclList, rclInclude, ptlBox, and lSpacing are in dialog units. If PEN_DIALOG_UNIT is not set, arclList, rclInclude, ptlBox, and lSpacing are in window coordinates.
 * PEN_ID_RECT tells the control that arclList is a list of windows IDs. If PEN_ID_RECT is not set, arclList is a list of rectangles.
 * PEN_FLAT identifies if the HWXCTLDATA structure has a flat layout or pointer layout. If PEN_FLAT is not set, the HWXCTLDATA structure has a pointer layout. PEN_FLAT should only be used if you are building a resource compiler. If your are using the Pen control data from a program, you should use pointers because they are easier to work with in your program.
 * PEN_SPTR_PROXIMITY tells the control that the structure element idProximityPtr has an ID to a system pointer handle. The proximity pointer will be displayed when the pointing device is over the control and is capable of writing.
 * PEN_SPTR_WRITING tells the control that the structure element idWritingPointer has an ID to a system pointer handle. The writing pointer will be displayed when the user is writing on the control. Pen for OS/2 Version 1.03 has added three system pointers: SPTR_PEN_BLOB (the default writing pointer), SPTR_PEN_ERASER, and SPTR_PEN_PENCIL (the default proximity pointer).
 * PEN_IGNORE_OVERRIDES tells the control to ignore the setting on the Overrides page of a program object's Settings notebook. With the Pen system, the user can set specific overrides for program objects (Enable pause time, Hide pointer, and Recognizing gesture and text). When this flag is set, the control will ignore the override and always use the programmed options.
 * ULONG ulInkingStyle must be set to IDM_INK_WINDOW if you want to control how the ink is drawn when writing in the controls. The default value for ulInkingStyle without any Pen control data is System Inking (IDM_INK_SYSTEM).
 * LONG lInkType defines the inking type used when writing. Because of the way the ink is drawn, most of the values of lInkType do not display as expected; therefore, I suggest you use the default value for lInkType (a solid line): LINETYPE_DEFAULT.
 * LONG lInkMix sets how the ink is mixed with the background. I found the best value to set lInkMix for handwriting is the default value of FM_OVERPAINT. Setting the value of lInkMix to FM_LEAVEALONE will produce invisible ink.
 * ULONG ulEOWevents defines when Pen for OS/2 stops writing and begins recognizing the handwriting to ASCII text. ulEOWevents works in conjunction with the rclInclude (include rectangle) and uIDMRectList.pidmrectList (exclude rectangle) structure elements to determine when Pen for OS/2 will start handwriting recognition. The following can be ORed together and set in ulEOWevents:
 * EOW_WRTTIMEOUT sets the Pen system to start recognizing the handwriting at a specified time after the user stops writing. The specified time is defined in the PPMSV_WRITING_TIMEOUT system variable.
 * EOW_EXITPROX sets the Pen system to start recognizing the handwriting if the user moves the pen pointing device from proximity to the digitizer. Proximity is the distance the pen can be from the digitizer while the digitizer is still aware of pen movement. This distance is usually about one inch.
 * EOW_LIFTOFF sets the Pen system to start recognizing the handwriting if the user lifts the pen from the surface of the digitizer. This is not recommended for standard handwriting because most letters require more than one stroke to write.
 * RECTL rclInclude defines the region where handwriting will be recognized. Once a user starts writing inside the region defined in rclInclude, a touchdown outside of this region will start an End of Writing (EOW) event. The user will not be able to start writing outside the region defined in rclInclude. If rclInclude is set to all zeros (the default), the control window size will be used as the handwriting region, and the user will only be allowed to write inside the control window. If the control window is small (for example, an SLE), you might want to make the include rectangle larger than the window so the user doesn't have to use smaller handwriting. The only restriction is that the first user touchdown must be inside the control. If a rectangle is chosen, the coordinates must be mapped to the desktop unless the PEN_DIALOG_UNIT flag is set. In this case, the coordinates must be in dialog units mapped to the parent window of the control. If the rclInclude structure element is set, you must remap the coordinates every time the control is moved or sized. Remapping must be done by sending the HWX_SET_INCLUDE_RECTL message to the control with the new include region coordinates mapped to the desktop.
 * ULONG ulSetMask is used in conjunction with cSymList if the PEN_FLAT flag is set, or if you don't want to set pidrsymsetList. The value in ulSetMask is ignored if you set the pidrsymsetList structure element. The ulSetMask structure element is used to help the recognition engine to be more accurate. For example, if the control should only take digit input, you should set ulSetMask to IDR_SYMSET_DIGIT. This tells the recognition engine to recognize the user's handwriting as digits.

The unions in the pen control data provide support for both pointer and flat structures in the same data structure. Unless you are creating a resource compiler, I would suggest using pointers because they are easier to use and manipulate in your applications.


 * uIDMRectList.pidmrectList is a pointer to an IDM_RECTLIST structure. IDM_RECTLIST is a structure that will let the application writer identify exclude rectangles. Exclude rectangles are regions the user is not allowed to write in. If the user touches down in an exclude region, an End of Writing (EOW) event will begin. The coordinates of exclude rectangles must be mapped to the desktop. The following flags should not be specified: PEN_DIALOG_UNIT, PEN_ID_RECT, and PEN_FLAT. If the uIDMRectList.pidmrectList structure element is set, you must remap the coordinates every time one of the exclude rectangles is moved or sized. Remapping must be done by sending the HWX_SET_EXCLUDE_RECTL message to the control with the new IDM_RECTLIST structure, and mapping the exclude rectangles' coordinates to the desktop.
 * uIDRSymSet.pidrsymsetList can be used if ulSetMask does not restrict the handwriting input enough. You can set uIDRSymSet.pidrsymsetList to point to an IDR_SYMSET structure and specify which symbols will be the only ones recognized by the recognition engine. uIDRSymSet.pidrsymsetList->cbSize must be set to sizeof(IDR_SYMSET).uIDRSymSet.pidrsymsetList->ulSymCnt must be set to (number of symbols to set). uIDRSymSet.pidrsymsetList->ulSetMask must be set to 0UL. uIDRSymSet.pidrsymsetList->pSyms[n]->usSymType must be set to IDR_TYPE_ASCII. uIDRSymSet.pidrsymsetList->pSyms[n]->usSymValue must be set to the ASCII value that you want to recognize. If you are only setting uIDRSymSet.pidrsymsetList->ulSetMask, you should use the HWXCTLDATA.ulSetMask structure element instead.
 * uIDRGestSet.pidrsymsetGest restricts the gestures that will be recognized by the recognition engine. uIDRGestSet.pidrsymsetGest points to an IDR_SYMSET structure that specifies which symbols will be recognized by the recognition engine. uIDRGestSet.pidrsymsetList->cbSize must be set to sizeof(IDR_SYMSET). uIDRGestSet.pidrsymsetList->ulSymCnt must be set to (number of symbols to set). uIDRGestSet.pidrsymsetList->ulSetMask must be set to 0UL. uIDRGestSet.pidrsymsetList->pSyms[n]->usSymType must be set to IDR_TYPE_SYSGESTURE.uIDRGestSet. pidrsymsetList->pSyms[n]->usSymValue must be set to the VE_* value (virtual ID for the gesture) that you want to recognize.

Changing Pen Data
Another way to control the Pen functions in text entry PM controls is to use the WinSendMsg function. All of the variables in the HWXCTLDATA structure can be set or query after window creation by sending PM messages to the control. The following messages have different parameters from the HWXCTLDATA data structure:
 * HXM_SET_PROXIMITY_POINTER and HXM_SET_WRITING_POINTER messages take a handle to a pointer instead of an ID to a pointer handle. You can still set them to (-1) to use the default pointers.
 * HXM_SET_EXCLUDE_RECTL only takes a pointer to IDM_RECTLIST structure.

Additional information is available in the Developer's Toolkit for OS/2 Warp and the Pen for OS/2 Toolkit.

As mentioned previously, a third way to control Pen functions in text entry PM controls is to use the Universal Resource Editor (URE) for OS/2 from Prominare, Inc. URE supports all PM controls for Pen for OS/2. You can find URE in the Developer's Toolkit for OS/2 Warp, which is on your accompanying Developer Connection for OS/2 CD-ROMs. URE has been updated to support Pen functions in OS/2 Warp. (Note: You must run URE on a system that has Pen for OS/2 Version 1.03 installed in order to use the Pen functions.)