PMGuide - Multiple-Line Entry Field Controls: Difference between revisions
Created page with "==About Multiple-Line Entry Field Controls== ===MLE Styles=== ===MLE Notification Codes=== ===MLE Text Editing=== ===MLE Text Formatting=== ===MLE Text Import and Export Operations=== ===MLE Cut, Copy, and Paste Operations=== ===MLE Search and Replace Operations=== ===MLE Colors === ==Using Multiple-Line Entry Field Controls== ===Creating an MLE=== ===Importing and Exporting MLE Text=== ====Importing MLE Text==== ====Exporting MLE Text ==== ===Searching MLE Text ===" |
No edit summary |
||
Line 1: | Line 1: | ||
{{IBM-Reprint}} | |||
{{PMGuide}} | |||
A ''multiple-line entry (MLE)'' field is a sophisticated control window that enables a user to view and edit multiple lines of text. This chapter describes how to create and use multiple-line entry field controls in PM applications. | |||
==About Multiple-Line Entry Field Controls== | ==About Multiple-Line Entry Field Controls== | ||
An MLE field control gives an application the text-editing capabilities of a simple text editor. The application can create a multiple-line entry field by using WinCreateWindow or by specifying the MLE statement in a dialog-window template in a resource-definition file. | |||
===MLE Styles=== | ===MLE Styles=== | ||
The style of an MLE field control determines how the MLE field appears and behaves. An application can specify a combination of the following styles for an MLE field: | |||
<pre> | |||
┌────────────────────┬────────────────────────────────────────┐ | |||
│Style Name │Description │ | |||
├────────────────────┼────────────────────────────────────────┤ | |||
│MLS_BORDER │Draws a border around the MLE field. │ | |||
├────────────────────┼────────────────────────────────────────┤ | |||
│MLS_DISABLEUNDO │Directs the MLE control not to allow │ | |||
│ │undo actions. │ | |||
├────────────────────┼────────────────────────────────────────┤ | |||
│MLS_HSCROLL │Adds a horizontal scroll bar to the MLE │ | |||
│ │field. The MLE control enables this │ | |||
│ │scroll bar whenever any line exceeds the│ | |||
│ │width of the MLE field. │ | |||
├────────────────────┼────────────────────────────────────────┤ | |||
│MLS_IGNORETAB │Directs the MLE control to ignore the │ | |||
│ │Tab key. It passes the appropriate │ | |||
│ │WM_CHAR to its owner window. │ | |||
├────────────────────┼────────────────────────────────────────┤ | |||
│MLS_LIMITVSCROLL │Displays the last MLE line at the bottom│ | |||
│ │of the screen page. When this style is │ | |||
│ │not used, the MLE control shows an empty│ | |||
│ │space between the last MLE line and the │ | |||
│ │bottom of the screen page. │ | |||
├────────────────────┼────────────────────────────────────────┤ | |||
│MLS_READONLY │Prevents the MLE field from accepting │ | |||
│ │text from the user. This style is useful│ | |||
│ │for displaying lengthy static text in a │ | |||
│ │client or dialog window. │ | |||
├────────────────────┼────────────────────────────────────────┤ | |||
│MLS_VSCROLL │Adds a vertical scroll bar to the MLE │ | |||
│ │field. The MLE control enables this │ | |||
│ │scroll bar whenever the number of lines │ | |||
│ │exceeds the height of the MLE field. │ | |||
├────────────────────┼────────────────────────────────────────┤ | |||
│MLS_WORDWRAP │Automatically breaks lines that are │ | |||
│ │longer than the width of the MLE field. │ | |||
└────────────────────┴────────────────────────────────────────┘ | |||
</pre> | |||
===MLE Notification Codes=== | ===MLE Notification Codes=== | ||
An MLE field control sends WM_CONTROL messages containing notification codes to its owner whenever certain events occur, for example, when the user or application tries to insert too much text, or when the user uses the scroll bars. The owner window uses the notification codes either to carry out custom operations for the MLE field or to respond to errors. | |||
The MLE field control sends the MLN_HSCROLL or MLN_VSCROLL notification codes when the user enables the scroll bars so that the application can monitor the visible contents of the MLE field. The application also can monitor the contents of an MLE field by using the MLM_QUERYFIRSTCHAR message, which specifies the offset of the character in the upper-left corner of the MLE field. This represents the first MLE character that is visible to the user. To provide an alternative way of scrolling the contents of an MLE field, an application can move the character at the specified offset to the upper-left corner of an MLE field using the MLM_SETFIRSTCHAR message. | |||
The MLE field control sends an MLN_CHANGE notification code when the user changes the text in some way. This notification code is especially useful when the MLE field is in a dialog window, because the dialog procedure can use this code to determine whether it should process the contents of the MLE field. If an application does not process MLN_CHANGE notification codes, it can use the MLM_QUERYCHANGED message to determine whether the user has made changes to the MLE text. The MLM_SETCHANGED message makes the MLE field control send an MLN_CHANGE notification code with every event that occurs in the MLE field, regardless of whether the user has changed anything. This code also can be used to hide a change made by a user. | |||
===MLE Text Editing=== | ===MLE Text Editing=== | ||
An MLE field contains one or more lines of text. Each line consists of one or more characters and ends with one or more characters that represent the end of the line. The end-of-line characters are determined by the format of the text. | |||
The user can type text in an MLE field when the MLE field has the focus. The application can insert text at any time by using the MLM_INSERT message and specifying the text as a null-terminated string. The MLE field control inserts the text at the cursor position or replaces the selected text. | |||
The MLE field control entry mode, insert or overstrike, determines what happens when the user inserts text. The user sets the entry mode by pressing the Insert key. The entry mode alternates each time the user presses Insert. When overstrike mode is enabled, at least one character is selected. This means that the MLM_INSERT message always replaces at least one character. If insert mode is enabled, the MLM_INSERT message replaces only those characters the user or application has selected. Otherwise, the MLE field makes room for the inserted characters by moving existing characters to the right, starting at the cursor position. | |||
The cursor position, identified by a blinking bar, is specified as a character offset relative to the beginning of the text. The user can set the cursor position by using the mouse or Arrow keys to move the blinking bar. An application can set the cursor position by using the MLM_SETSEL message, which directs the MLE field control to move the blinking bar to a given character position. The MLM_SETSEL message also can set the selection. | |||
The selection is one or more characters of text on which the MLE field control carries out an operation, such as deleting or copying. The user selects text by pressing the Shift key while moving the cursor or by pressing mouse button 1 while moving the mouse. The user also can select a word in a block of text by double-clicking on the word. An application selects text by using the MLM_SETSEL message to specify the cursor position and the anchor point. The selection is all the text between the cursor position and the anchor point. If the cursor position and anchor point are equal, there is no selection. An application can retrieve the cursor position, anchor point, or both, by using the MLM_QUERYSEL message. | |||
The user can delete characters, one at a time, by pressing the Delete key or the Backspace key. Pressing the Delete key deletes the character to the right of the cursor; pressing the Backspace key deletes the character to the left of the cursor and changes the cursor position. An application can delete one or more characters by using the MLM_DELETE message, which directs the MLE field control to delete a specified number of characters, starting at the given position. This message does not change the cursor position. An application can delete selected text by using the MLM_CLEAR message. | |||
An application can reverse the previous operation by using the MLM_UNDO message, which restores the MLE field to its previous state. This is a quick way to fix editing mistakes. However, not all operations can be undone. | |||
The application determines whether the previous operation can be undone by using the MLM_QUERYUNDO message, which returns TRUE and indicates the type of operation that can be undone. Using the MLM_RESETUNDO message, an application can prevent a subsequent MLM_UNDO message from changing the state of an MLE field. | |||
===MLE Text Formatting=== | ===MLE Text Formatting=== | ||
An application can retrieve the number of lines of text in an MLE field by using the MLM_QUERYLINECOUNT message and can retrieve the number of characters in the MLE field by using the MLM_QUERYTEXTLENGTH message. The amount of text and, subsequently, the number of lines to be entered in an MLE field depend on the text limit. An application sets the text limit by using the MLM_SETTEXTLIMIT message and determines the current limit by using the MLM_QUERYTEXTLIMIT message. The user cannot set the text limit. If the user types to the text limit, the MLE field control beeps and ignores any subsequent keystrokes. If the application attempts to add text beyond the limit, the MLE field control truncates the text. | |||
An application can control the length of each line in an MLE field by enabling word wrapping. When word wrapping is enabled, the MLE field control automatically breaks any line that is longer than the width of the MLE field. An application can set word wrapping by using the MLM_SETWRAP message, and it can determine whether the MLE field control is wrapping text by using the MLM_QUERYWRAP message. Word wrapping is disabled by default unless the application specifies the MLS_WORDWRAP style when creating the MLE field control. | |||
An application can set tab stops for an MLE control by using the MLM_SETTABSTOP message. Tab stops specify the maximum width of a tab character. When the user or an application inserts a tab character, the MLE field control expands the character so that it fills the space between the cursor position and the next tab stop. The MLM_SETTABSTOP message sets the distance (in pels) between tab stops, and the MLE field control provides as many tab stops as necessary, no matter how long the line gets. An application can retrieve the distance between tab stops using the MLM_QUERYTABSTOP message. | |||
An application can use the MLM_SETFORMATRECT message to set the format rectangle (MLE field). The format rectangle is used to set the horizontal and vertical limits for text. The MLE control sends a notification message to the parent window of the MLE field if text exceeds either of those limits. An application typically uses the format rectangle to provide its own word wrapping or other special text processing. An application can retrieve the current format rectangle by using the MLM_QUERYFORMATRECT message. | |||
An application can prevent the user's editing of the MLE field by setting the MLS_READONLY style in WinCreateWindow or in the MLE statement in the resource-definition file. The application also can set and query the read-only state by using the MLM_SETREADONLY and MLM_QUERYREADONLY messages, respectively. | |||
An application can set the colors and font for an MLE field by using the MLM_SETTEXTCOLOR, MLM_SETBACKCOLOR, and MLM_SETFONT messages. These messages affect all text in the MLE field. An MLE field cannot contain a mixture of fonts and colors. An application can retrieve the current values for the colors and font by using the MLM_QUERYTEXTCOLOR, MLM_QUERYBACKCOLOR, and MLM_QUERYFONT messages. | |||
To prevent scrolling within the MLE when the MLS_READONLY style bit is set, use the MLM_DISABLEREFRESH message. The keyboard and mouse input can be enabled using the MLM_ENABLEREFRESH message. | |||
===MLE Text Import and Export Operations=== | ===MLE Text Import and Export Operations=== | ||
An application can copy text to and from an MLE field by importing and exporting. To import text to an MLE field, an application can use the MLM_IMPORT message, which copies text from a buffer to the MLE field. To export text from an MLE field, the application can use the MLM_EXPORT message, which copies text from the MLE field to a buffer. The application uses the MLM_SETIMPORTEXPORT message to set the import and export buffers. | |||
An application can import and export text in a variety of formats. A text format, set with the MLM_FORMAT message, identifies which characters are used for the end-of-line characters. An MLE field can have the following text formats: | |||
<pre> | |||
┌────────────────────┬────────────────────────────────────────┐ | |||
│Format Name │Description │ | |||
├────────────────────┼────────────────────────────────────────┤ | |||
│MLFIE_CFTEXT │Exported lines end with a carriage │ | |||
│ │return/newline character pair (0x0D, │ | |||
│ │0x0A). Imported lines must end with a │ | |||
│ │newline character, carriage │ | |||
│ │return/newline character pair, or │ | |||
│ │newline/carriage return character pair. │ | |||
├────────────────────┼────────────────────────────────────────┤ | |||
│MLFIE_NOTRANS │Imported and exported lines end with a │ | |||
│ │newline character (0x0A). │ | |||
├────────────────────┼────────────────────────────────────────┤ | |||
│MLFIE_WINFMT │For exported lines, the carriage │ | |||
│ │return/newline character pair marks a │ | |||
│ │hard linebreak (a break entered by the │ | |||
│ │user). Two carriage-return characters │ | |||
│ │and a newline character (0x0D, 0x0D, │ | |||
│ │0x0A) mark a soft linebreak (a break │ | |||
│ │inserted during word wrapping and not │ | |||
│ │entered by the user). For imported │ | |||
│ │lines, the extra carriage-return in soft│ | |||
│ │linebreak characters is ignored. │ | |||
└────────────────────┴────────────────────────────────────────┘ | |||
</pre> | |||
The text format can affect the number of characters in a selection. To ensure that the export buffer is large enough to hold exported text, an application can send the MLM_QUERYFORMATLINELENGTH message. The application can send the MLM_QUERYFORMATTEXTLENGTH message to determine the number of bytes in the text to be exported. | |||
Each time an application inserts text in an MLE field, the MLE field control automatically refreshes (repaints) the display by drawing the new text. When an application copies large amounts of text to an MLE field, refreshing can be quite time-consuming, so the application should disable the refresh state. The application disables the refresh state by sending the MLM_DISABLEREFRESH message. After copying all the text, the application can restore the refresh state by sending the MLM_ENABLEREFRESH message. | |||
===MLE Cut, Copy, and Paste Operations=== | ===MLE Cut, Copy, and Paste Operations=== | ||
The user can cut, copy, and paste text in an MLE field by using the Shift+Delete, Ctrl+Insert, and Shift+Insert key combinations, respectively. An application-either by itself or in response to the user-can cut, copy, and paste text by using the MLM_CUT, MLM_COPY, and MLM_PASTE messages. The MLM_CUT and MLM_COPY messages copy the selected text to the clipboard. The MLM_CUT message also deletes the text from the MLE field; MLM_COPY does not. The MLM_PASTE message copies the text from the clipboard to the current position in the MLE field, replacing any existing text with the copied text. An application can delete the selected text without copying it to the clipboard by using the MLM_CLEAR message. | |||
An application also can copy the selected text from an MLE field to a buffer by using the MLM_QUERYSELTEXT message. This message does not affect the contents of the clipboard. | |||
===MLE Search and Replace Operations=== | ===MLE Search and Replace Operations=== | ||
An application can search for a specified string within MLE field text by using the MLM_SEARCH message, which searches for the string. The MLE field control returns TRUE if the string is found. The cursor does not move to the string unless the message specifies the MLFSEARCH_SELECTMATCH option. | |||
An application also can use the MLM_SEARCH message to replace one string with another. If the message specifies the MLFSEARCH_CHANGEALL option, the MLE field control replaces all occurrences of the search string with the replacement string. Both the search string and the replacement string must be specified in an MLE_SEARCHDATA data structure passed with the message. | |||
===MLE Colors === | ===MLE Colors === | ||
For version 3, or lower, of the OS/2 operating system, MLE supports indexed (solid) colors only; it does not support dithered (RGB) colors. | |||
For versions, higher than version 3, of the OS/2 operating system, MLE supports RGB colors. Indexed colors are changed to the closest RGB color representation. | |||
==Using Multiple-Line Entry Field Controls== | ==Using Multiple-Line Entry Field Controls== | ||
This section explains how to create an MLE field control by using [[WinCreateWindow]] and by specifying the MLE statement in a dialog template in a resource-definition file. | |||
===Creating an MLE=== | ===Creating an MLE=== | ||
The following sample code fragment shows how to create an MLE by using WinCreateWindow: | |||
<pre> | |||
#define MLE_WINDOW_ID 2 | |||
HWND hwndParent; | |||
HWND hwndMLE; | |||
hwndMLE = WinCreateWindow( | |||
hwndParent, /* Parent window */ | |||
WC_MLE, /* Window class */ | |||
"Test", /* Initial text */ | |||
WS_VISIBLE | /* Window style */ | |||
MLS_BORDER, /* Window style */ | |||
100, 100, /* x and y positions */ | |||
100, 100, /* Width and height */ | |||
hwndParent, /* Owner window */ | |||
HWND_TOP, /* Top of z-order */ | |||
MLE_WINDOW_ID, /* Identifier */ | |||
NULL, /* Control data */ | |||
NULL); /* Presparam */ | |||
</pre> | |||
It also is common to create an MLE field control by using an MLE statement in a dialog-window template in a resource file, as shown in the following code fragment: | |||
<pre> | |||
MLE "", | |||
IDD_MLETEXT, | |||
110, 10, 50, 100, | |||
WS_VISIBLE | | |||
MLS_BORDER | | |||
MLS_WORDWRAP | |||
</pre> | |||
The predefined class for an MLE control is WC_MLE. If you do not specify a style for the MLE control, the default styles used are MLS_BORDER, WS_GROUP, and WS_TABSTOP. | |||
===Importing and Exporting MLE Text=== | ===Importing and Exporting MLE Text=== | ||
Importing and exporting MLE text takes place through a buffer. An import operation copies text from the buffer to the MLE field; an export operation copies text from the MLE to the buffer. Before an application can import or export MLE text, it must send an MLM_SETIMPORTEXPORT message to the MLE field control, specifying the address and size of the buffer. | |||
For version 3, or lower, of the OS/2 operating system the maximum size of import/export buffer is 64K. Once the data is into the buffer, the data is manipulated (verified for carriage returns, line feeds and so forth), and is finally placed in the MLE's memory. | |||
====Importing MLE Text==== | ====Importing MLE Text==== | ||
To import text, an application sends the MLM_IMPORT message to the MLE field control. This message requires two parameters: plOffset and cbCopy. The plOffset parameter is a pointer to a variable that specifies the position in the MLE field where the text from the buffer is to be placed. The position is an offset from the beginning of the MLE text, that is, the number of characters from the beginning of the MLE text. If plOffset points to a variable that equals -1, the MLE field control places the text starting at the current cursor position. On return, this variable contains the offset to the first character beyond the imported text. The cbCopy parameter of the MLM_IMPORT message points to a variable that specifies the number of bytes to import. | |||
The following criterias apply when importing MLE text: | |||
*If the text ends by a line feed (LF), the import logic generates a blank line. | |||
*If the text ends by a carriage return (CR), MLE prevents a line break (LB) but flags the condition. | |||
*If the plOffset field points to the current cursor position (-1) and the import text contains a LF: | |||
**If the MLE text is imported before the text being edited, then the cursor does not move and the text being edited is shifted down to make room for the text being imported. | |||
**If the MLE text is imported after the text being edited, then the cursor does not move and the text being imported is inserted starting at the current cursor position. | |||
If the plOffset field points to the current cursor position (-1) and the import text does not contain a LF: | |||
*If the MLE text is imported before the text being edited, then the cursor does not move and the text being edited is shifted to the right to make room for the text being imported. | |||
*If the MLE text is imported after the text being edited, then the cursor does not move and the text being imported is inserted starting at the current cursor position. | |||
====Exporting MLE Text ==== | ====Exporting MLE Text ==== | ||
Before using the MLM_EXPORT message the number of characters to export needs to be determined. The MLM_QUERYFORMATTEXTLENGTH message is used to determine the number of characters to be copied from the MLE to the buffer (including LF and CR) and to allocate the room in the buffer. MLM_EXPORT is then used to export the MLE text into the buffer. | |||
Note: The MLM_QUERYTEXTLENGTH message does not consider the CR and LF characters as the MLM_QUERYFORMATTEXTLENGTH message does. | |||
The following code fragment reads text from a file to a buffer, then imports the text to an MLE field: | |||
<pre> | |||
HWND hwndMle; | |||
CHAR szMleBuf[512]; | |||
IPT lOffset = 0; | |||
PSZ pszTextFile; | |||
HFILE hf; | |||
ULONG cbCopied; | |||
ULONG ulAction; | |||
ULONG cbBytesRead; | |||
/* Obtain a file name from the user */ | |||
/* Open the file */ | |||
DosOpen(pszTextFile, | |||
&hf, | |||
&ulAction, | |||
0, | |||
FILE_NORMAL, | |||
FILE_OPEN | | |||
FILE_CREATE, | |||
OPEN_ACCESS_READONLY | | |||
OPEN_SHARE_DENYNONE, | |||
NULL); | |||
/* Zero-fill the buffer using memset, a C run-time function */ | |||
memset(szMleBuf, 0, sizeof(szMleBuf)); | |||
/* Set the MLE import-export buffer */ | |||
WinSendMsg(hwndMle, | |||
MLM_SETIMPORTEXPORT, | |||
MPFROMP(szMleBuf), | |||
MPFROMSHORT((USHORT) sizeof(szMleBuf))); | |||
/**********************************************************************/ | |||
/* Read the text from the file to the buffer, */ | |||
/* then import it to the MLE. */ | |||
/**********************************************************************/ | |||
do { | |||
DosRead(hf, | |||
szMleBuf, | |||
sizeof(szMleBuf), | |||
&cbBytesRead); | |||
cbCopied = (ULONG) WinSendMsg(hwndMle, | |||
MLM_IMPORT, | |||
MPFROMP( &lOffset), | |||
MPFROMP(&cbBytesRead)); | |||
} while (cbCopied); | |||
/* Close the file */ | |||
DosClose(hf); | |||
</pre> | |||
To export MLE text, an application sends the MLM_EXPORT message to the MLE control. Like MLM_IMPORT, the MLM_EXPORT message takes the plOffset and cbCopy parameters. The plOffset parameter is a pointer to a variable that specifies the offset to the first character to export. A value of -1 specifies the current cursor position. On return, the variable contains the offset to the first character in the MLE field not copied to the buffer. The cbCopy parameter is a pointer to a variable that specifies the number of bytes to export. On return, this variable equals 0 if the number of characters actually copied does not exceed the number specified to be copied. The following code fragment shows how to export text from an MLE field, then store the text in a file: | |||
<pre> | |||
HWND hwndMle; | |||
CHAR szMleBuf[512]; | |||
IPT lOffset = 0; | |||
PSZ pszTextFile; | |||
HFILE hf; | |||
ULONG cbCopied; | |||
ULONG ulAction; | |||
ULONG cbBytesWritten; | |||
ULONG cbCopy; | |||
/* Zero-fill the buffer using memset, a C run-time function */ | |||
memset(szMleBuf, 0, sizeof(szMleBuf)); | |||
/* Set the MLE import-export buffer */ | |||
WinSendMsg(hwndMle, | |||
MLM_SETIMPORTEXPORT, | |||
MPFROMP(szMleBuf), | |||
MPFROMSHORT ((USHORT) sizeof(szMleBuf))); | |||
. | |||
. | |||
. | |||
/* Obtain a filename from the user */ | |||
. | |||
. | |||
. | |||
/* Open the file */ | |||
DosOpen(pszTextFile, | |||
&hf, | |||
&ulAction, | |||
0, | |||
FILE_NORMAL, | |||
FILE_OPEN | | |||
FILE_CREATE, | |||
OPEN_ACCESS_WRITEONLY | | |||
OPEN_SHARE_DENYNONE, | |||
NULL); | |||
/* Find out how much text is in the MLE */ | |||
cbCopy = (ULONG) WinSendMsg(hwndMle, | |||
MLM_QUERYFORMATTEXTLENGTH, | |||
MPFROMLONG(lOffset), | |||
MPFROMLONG((-1))); | |||
/* Copy the MLE text to the buffer */ | |||
cbCopied = (ULONG) WinSendMsg(hwndMle, | |||
MLM_EXPORT, | |||
MPFROMP(&lOffset), | |||
MPFROMP(&cbCopy)); | |||
/* Write the contents of the buffer to the file */ | |||
DosWrite(hf, | |||
szMleBuf, | |||
sizeof(szMleBuf), | |||
&cbBytesWritten); | |||
/* Close the file */ | |||
DosClose(hf); | |||
</pre> | |||
===Searching MLE Text === | ===Searching MLE Text === | ||
An application uses the MLM_SEARCH message and the MLE_SEARCHDATA data structure to search for strings in MLE text. The first parameter of the MLM_SEARCH message is an array of flags that specify the style of the search. The application can set the MLFSEARCH_CASESENSITIVE flag if a case-sensitive search is required. If the application sets the MLFSEARCH_SELECTMATCH flag, the MLE field control highlights a matching string and, if necessary, scrolls the string into view. An application can use the MLFSEARCH_CHANGEALL flag to replace every occurrence of the string with the string specified in the pchReplace member of the MLE_SEARCHDATA data structure. | |||
The second parameter of the MLM_SEARCH message is a pointer to an MLE_SEARCHDATA data structure that contains information required to perform the search operation. This data structure includes a pointer to the string and, if the MLFSEARCH_CHANGEALL flag is set in the MLM_SEARCH message, a pointer to the replacement string. The iptStart and iptStop members specify the starting and ending positions of the search. These positions are specified as offsets from the beginning of the MLE field. A value of -1 in the iptStart member causes the search to start at the current cursor position. A negative value in the iptStop member causes the search to end at the end of the MLE field. If a matching string is found, the MLE field control returns the length of the string in the cchFound member. | |||
The following code fragment uses an entry field to obtain a search string from the user, then searches an MLE field for an occurrence of the string. The search begins at the current cursor position and ends at the end of the MLE text. When the MLFSEARCH_SELECTMATCH flag is specified, the MLE field control highlights a matching string and scrolls it into view. | |||
The following code fragment shows how to search MLE text: | |||
<pre> | |||
#define IDD_SEARCHFIELD 101 | |||
HWND hwnd; | |||
HWND hwndEntryFld; | |||
HWND hwndMle; | |||
MLE_SEARCHDATA mlesrch; | |||
CHAR szSearchString[64]; | |||
/* Obtain the handle of the entry field containing the search string */ | |||
hwndEntryFld = WinWindowFromID(hwnd, IDD_SEARCHFIELD); | |||
/* Obtain the search string from the entry field */ | |||
WinQueryWindowText(hwndEntryFld, | |||
sizeof(szSearchString), | |||
szSearchString); | |||
/* Fill the MLE_SEARCHDATA data structure */ | |||
mlesrch.cb = sizeof(mlesrch); /* Structure size */ | |||
mlesrch.pchFind = szSearchString; /* Search string */ | |||
mlesrch.pchReplace = NULL; /* No replacement string */ | |||
mlesrch.cchFind = 0; /* Not used */ | |||
mlesrch.cchReplace = 0; /* Not used */ | |||
mlesrch.iptStart = -1; /* Start at cursor position */ | |||
mlesrch.iptStop = -1; /* Stop at end of file */ | |||
/* Start the search operation */ | |||
WinSendMsg(hwndMle, | |||
MLM_SEARCH, | |||
MPFROMLONG(MLFSEARCH_SELECTMATCH), | |||
MPFROMP(&mlesrch)); | |||
</pre> |
Latest revision as of 03:48, 29 April 2025
Reprint Courtesy of International Business Machines Corporation, © International Business Machines Corporation
A multiple-line entry (MLE) field is a sophisticated control window that enables a user to view and edit multiple lines of text. This chapter describes how to create and use multiple-line entry field controls in PM applications.
About Multiple-Line Entry Field Controls
An MLE field control gives an application the text-editing capabilities of a simple text editor. The application can create a multiple-line entry field by using WinCreateWindow or by specifying the MLE statement in a dialog-window template in a resource-definition file.
MLE Styles
The style of an MLE field control determines how the MLE field appears and behaves. An application can specify a combination of the following styles for an MLE field:
┌────────────────────┬────────────────────────────────────────┐ │Style Name │Description │ ├────────────────────┼────────────────────────────────────────┤ │MLS_BORDER │Draws a border around the MLE field. │ ├────────────────────┼────────────────────────────────────────┤ │MLS_DISABLEUNDO │Directs the MLE control not to allow │ │ │undo actions. │ ├────────────────────┼────────────────────────────────────────┤ │MLS_HSCROLL │Adds a horizontal scroll bar to the MLE │ │ │field. The MLE control enables this │ │ │scroll bar whenever any line exceeds the│ │ │width of the MLE field. │ ├────────────────────┼────────────────────────────────────────┤ │MLS_IGNORETAB │Directs the MLE control to ignore the │ │ │Tab key. It passes the appropriate │ │ │WM_CHAR to its owner window. │ ├────────────────────┼────────────────────────────────────────┤ │MLS_LIMITVSCROLL │Displays the last MLE line at the bottom│ │ │of the screen page. When this style is │ │ │not used, the MLE control shows an empty│ │ │space between the last MLE line and the │ │ │bottom of the screen page. │ ├────────────────────┼────────────────────────────────────────┤ │MLS_READONLY │Prevents the MLE field from accepting │ │ │text from the user. This style is useful│ │ │for displaying lengthy static text in a │ │ │client or dialog window. │ ├────────────────────┼────────────────────────────────────────┤ │MLS_VSCROLL │Adds a vertical scroll bar to the MLE │ │ │field. The MLE control enables this │ │ │scroll bar whenever the number of lines │ │ │exceeds the height of the MLE field. │ ├────────────────────┼────────────────────────────────────────┤ │MLS_WORDWRAP │Automatically breaks lines that are │ │ │longer than the width of the MLE field. │ └────────────────────┴────────────────────────────────────────┘
MLE Notification Codes
An MLE field control sends WM_CONTROL messages containing notification codes to its owner whenever certain events occur, for example, when the user or application tries to insert too much text, or when the user uses the scroll bars. The owner window uses the notification codes either to carry out custom operations for the MLE field or to respond to errors.
The MLE field control sends the MLN_HSCROLL or MLN_VSCROLL notification codes when the user enables the scroll bars so that the application can monitor the visible contents of the MLE field. The application also can monitor the contents of an MLE field by using the MLM_QUERYFIRSTCHAR message, which specifies the offset of the character in the upper-left corner of the MLE field. This represents the first MLE character that is visible to the user. To provide an alternative way of scrolling the contents of an MLE field, an application can move the character at the specified offset to the upper-left corner of an MLE field using the MLM_SETFIRSTCHAR message.
The MLE field control sends an MLN_CHANGE notification code when the user changes the text in some way. This notification code is especially useful when the MLE field is in a dialog window, because the dialog procedure can use this code to determine whether it should process the contents of the MLE field. If an application does not process MLN_CHANGE notification codes, it can use the MLM_QUERYCHANGED message to determine whether the user has made changes to the MLE text. The MLM_SETCHANGED message makes the MLE field control send an MLN_CHANGE notification code with every event that occurs in the MLE field, regardless of whether the user has changed anything. This code also can be used to hide a change made by a user.
MLE Text Editing
An MLE field contains one or more lines of text. Each line consists of one or more characters and ends with one or more characters that represent the end of the line. The end-of-line characters are determined by the format of the text.
The user can type text in an MLE field when the MLE field has the focus. The application can insert text at any time by using the MLM_INSERT message and specifying the text as a null-terminated string. The MLE field control inserts the text at the cursor position or replaces the selected text.
The MLE field control entry mode, insert or overstrike, determines what happens when the user inserts text. The user sets the entry mode by pressing the Insert key. The entry mode alternates each time the user presses Insert. When overstrike mode is enabled, at least one character is selected. This means that the MLM_INSERT message always replaces at least one character. If insert mode is enabled, the MLM_INSERT message replaces only those characters the user or application has selected. Otherwise, the MLE field makes room for the inserted characters by moving existing characters to the right, starting at the cursor position.
The cursor position, identified by a blinking bar, is specified as a character offset relative to the beginning of the text. The user can set the cursor position by using the mouse or Arrow keys to move the blinking bar. An application can set the cursor position by using the MLM_SETSEL message, which directs the MLE field control to move the blinking bar to a given character position. The MLM_SETSEL message also can set the selection.
The selection is one or more characters of text on which the MLE field control carries out an operation, such as deleting or copying. The user selects text by pressing the Shift key while moving the cursor or by pressing mouse button 1 while moving the mouse. The user also can select a word in a block of text by double-clicking on the word. An application selects text by using the MLM_SETSEL message to specify the cursor position and the anchor point. The selection is all the text between the cursor position and the anchor point. If the cursor position and anchor point are equal, there is no selection. An application can retrieve the cursor position, anchor point, or both, by using the MLM_QUERYSEL message.
The user can delete characters, one at a time, by pressing the Delete key or the Backspace key. Pressing the Delete key deletes the character to the right of the cursor; pressing the Backspace key deletes the character to the left of the cursor and changes the cursor position. An application can delete one or more characters by using the MLM_DELETE message, which directs the MLE field control to delete a specified number of characters, starting at the given position. This message does not change the cursor position. An application can delete selected text by using the MLM_CLEAR message.
An application can reverse the previous operation by using the MLM_UNDO message, which restores the MLE field to its previous state. This is a quick way to fix editing mistakes. However, not all operations can be undone.
The application determines whether the previous operation can be undone by using the MLM_QUERYUNDO message, which returns TRUE and indicates the type of operation that can be undone. Using the MLM_RESETUNDO message, an application can prevent a subsequent MLM_UNDO message from changing the state of an MLE field.
MLE Text Formatting
An application can retrieve the number of lines of text in an MLE field by using the MLM_QUERYLINECOUNT message and can retrieve the number of characters in the MLE field by using the MLM_QUERYTEXTLENGTH message. The amount of text and, subsequently, the number of lines to be entered in an MLE field depend on the text limit. An application sets the text limit by using the MLM_SETTEXTLIMIT message and determines the current limit by using the MLM_QUERYTEXTLIMIT message. The user cannot set the text limit. If the user types to the text limit, the MLE field control beeps and ignores any subsequent keystrokes. If the application attempts to add text beyond the limit, the MLE field control truncates the text.
An application can control the length of each line in an MLE field by enabling word wrapping. When word wrapping is enabled, the MLE field control automatically breaks any line that is longer than the width of the MLE field. An application can set word wrapping by using the MLM_SETWRAP message, and it can determine whether the MLE field control is wrapping text by using the MLM_QUERYWRAP message. Word wrapping is disabled by default unless the application specifies the MLS_WORDWRAP style when creating the MLE field control.
An application can set tab stops for an MLE control by using the MLM_SETTABSTOP message. Tab stops specify the maximum width of a tab character. When the user or an application inserts a tab character, the MLE field control expands the character so that it fills the space between the cursor position and the next tab stop. The MLM_SETTABSTOP message sets the distance (in pels) between tab stops, and the MLE field control provides as many tab stops as necessary, no matter how long the line gets. An application can retrieve the distance between tab stops using the MLM_QUERYTABSTOP message.
An application can use the MLM_SETFORMATRECT message to set the format rectangle (MLE field). The format rectangle is used to set the horizontal and vertical limits for text. The MLE control sends a notification message to the parent window of the MLE field if text exceeds either of those limits. An application typically uses the format rectangle to provide its own word wrapping or other special text processing. An application can retrieve the current format rectangle by using the MLM_QUERYFORMATRECT message.
An application can prevent the user's editing of the MLE field by setting the MLS_READONLY style in WinCreateWindow or in the MLE statement in the resource-definition file. The application also can set and query the read-only state by using the MLM_SETREADONLY and MLM_QUERYREADONLY messages, respectively.
An application can set the colors and font for an MLE field by using the MLM_SETTEXTCOLOR, MLM_SETBACKCOLOR, and MLM_SETFONT messages. These messages affect all text in the MLE field. An MLE field cannot contain a mixture of fonts and colors. An application can retrieve the current values for the colors and font by using the MLM_QUERYTEXTCOLOR, MLM_QUERYBACKCOLOR, and MLM_QUERYFONT messages.
To prevent scrolling within the MLE when the MLS_READONLY style bit is set, use the MLM_DISABLEREFRESH message. The keyboard and mouse input can be enabled using the MLM_ENABLEREFRESH message.
MLE Text Import and Export Operations
An application can copy text to and from an MLE field by importing and exporting. To import text to an MLE field, an application can use the MLM_IMPORT message, which copies text from a buffer to the MLE field. To export text from an MLE field, the application can use the MLM_EXPORT message, which copies text from the MLE field to a buffer. The application uses the MLM_SETIMPORTEXPORT message to set the import and export buffers.
An application can import and export text in a variety of formats. A text format, set with the MLM_FORMAT message, identifies which characters are used for the end-of-line characters. An MLE field can have the following text formats:
┌────────────────────┬────────────────────────────────────────┐ │Format Name │Description │ ├────────────────────┼────────────────────────────────────────┤ │MLFIE_CFTEXT │Exported lines end with a carriage │ │ │return/newline character pair (0x0D, │ │ │0x0A). Imported lines must end with a │ │ │newline character, carriage │ │ │return/newline character pair, or │ │ │newline/carriage return character pair. │ ├────────────────────┼────────────────────────────────────────┤ │MLFIE_NOTRANS │Imported and exported lines end with a │ │ │newline character (0x0A). │ ├────────────────────┼────────────────────────────────────────┤ │MLFIE_WINFMT │For exported lines, the carriage │ │ │return/newline character pair marks a │ │ │hard linebreak (a break entered by the │ │ │user). Two carriage-return characters │ │ │and a newline character (0x0D, 0x0D, │ │ │0x0A) mark a soft linebreak (a break │ │ │inserted during word wrapping and not │ │ │entered by the user). For imported │ │ │lines, the extra carriage-return in soft│ │ │linebreak characters is ignored. │ └────────────────────┴────────────────────────────────────────┘
The text format can affect the number of characters in a selection. To ensure that the export buffer is large enough to hold exported text, an application can send the MLM_QUERYFORMATLINELENGTH message. The application can send the MLM_QUERYFORMATTEXTLENGTH message to determine the number of bytes in the text to be exported.
Each time an application inserts text in an MLE field, the MLE field control automatically refreshes (repaints) the display by drawing the new text. When an application copies large amounts of text to an MLE field, refreshing can be quite time-consuming, so the application should disable the refresh state. The application disables the refresh state by sending the MLM_DISABLEREFRESH message. After copying all the text, the application can restore the refresh state by sending the MLM_ENABLEREFRESH message.
MLE Cut, Copy, and Paste Operations
The user can cut, copy, and paste text in an MLE field by using the Shift+Delete, Ctrl+Insert, and Shift+Insert key combinations, respectively. An application-either by itself or in response to the user-can cut, copy, and paste text by using the MLM_CUT, MLM_COPY, and MLM_PASTE messages. The MLM_CUT and MLM_COPY messages copy the selected text to the clipboard. The MLM_CUT message also deletes the text from the MLE field; MLM_COPY does not. The MLM_PASTE message copies the text from the clipboard to the current position in the MLE field, replacing any existing text with the copied text. An application can delete the selected text without copying it to the clipboard by using the MLM_CLEAR message.
An application also can copy the selected text from an MLE field to a buffer by using the MLM_QUERYSELTEXT message. This message does not affect the contents of the clipboard.
MLE Search and Replace Operations
An application can search for a specified string within MLE field text by using the MLM_SEARCH message, which searches for the string. The MLE field control returns TRUE if the string is found. The cursor does not move to the string unless the message specifies the MLFSEARCH_SELECTMATCH option.
An application also can use the MLM_SEARCH message to replace one string with another. If the message specifies the MLFSEARCH_CHANGEALL option, the MLE field control replaces all occurrences of the search string with the replacement string. Both the search string and the replacement string must be specified in an MLE_SEARCHDATA data structure passed with the message.
MLE Colors
For version 3, or lower, of the OS/2 operating system, MLE supports indexed (solid) colors only; it does not support dithered (RGB) colors.
For versions, higher than version 3, of the OS/2 operating system, MLE supports RGB colors. Indexed colors are changed to the closest RGB color representation.
Using Multiple-Line Entry Field Controls
This section explains how to create an MLE field control by using WinCreateWindow and by specifying the MLE statement in a dialog template in a resource-definition file.
Creating an MLE
The following sample code fragment shows how to create an MLE by using WinCreateWindow:
#define MLE_WINDOW_ID 2 HWND hwndParent; HWND hwndMLE; hwndMLE = WinCreateWindow( hwndParent, /* Parent window */ WC_MLE, /* Window class */ "Test", /* Initial text */ WS_VISIBLE | /* Window style */ MLS_BORDER, /* Window style */ 100, 100, /* x and y positions */ 100, 100, /* Width and height */ hwndParent, /* Owner window */ HWND_TOP, /* Top of z-order */ MLE_WINDOW_ID, /* Identifier */ NULL, /* Control data */ NULL); /* Presparam */
It also is common to create an MLE field control by using an MLE statement in a dialog-window template in a resource file, as shown in the following code fragment:
MLE "", IDD_MLETEXT, 110, 10, 50, 100, WS_VISIBLE | MLS_BORDER | MLS_WORDWRAP
The predefined class for an MLE control is WC_MLE. If you do not specify a style for the MLE control, the default styles used are MLS_BORDER, WS_GROUP, and WS_TABSTOP.
Importing and Exporting MLE Text
Importing and exporting MLE text takes place through a buffer. An import operation copies text from the buffer to the MLE field; an export operation copies text from the MLE to the buffer. Before an application can import or export MLE text, it must send an MLM_SETIMPORTEXPORT message to the MLE field control, specifying the address and size of the buffer.
For version 3, or lower, of the OS/2 operating system the maximum size of import/export buffer is 64K. Once the data is into the buffer, the data is manipulated (verified for carriage returns, line feeds and so forth), and is finally placed in the MLE's memory.
Importing MLE Text
To import text, an application sends the MLM_IMPORT message to the MLE field control. This message requires two parameters: plOffset and cbCopy. The plOffset parameter is a pointer to a variable that specifies the position in the MLE field where the text from the buffer is to be placed. The position is an offset from the beginning of the MLE text, that is, the number of characters from the beginning of the MLE text. If plOffset points to a variable that equals -1, the MLE field control places the text starting at the current cursor position. On return, this variable contains the offset to the first character beyond the imported text. The cbCopy parameter of the MLM_IMPORT message points to a variable that specifies the number of bytes to import.
The following criterias apply when importing MLE text:
- If the text ends by a line feed (LF), the import logic generates a blank line.
- If the text ends by a carriage return (CR), MLE prevents a line break (LB) but flags the condition.
- If the plOffset field points to the current cursor position (-1) and the import text contains a LF:
- If the MLE text is imported before the text being edited, then the cursor does not move and the text being edited is shifted down to make room for the text being imported.
- If the MLE text is imported after the text being edited, then the cursor does not move and the text being imported is inserted starting at the current cursor position.
If the plOffset field points to the current cursor position (-1) and the import text does not contain a LF:
- If the MLE text is imported before the text being edited, then the cursor does not move and the text being edited is shifted to the right to make room for the text being imported.
- If the MLE text is imported after the text being edited, then the cursor does not move and the text being imported is inserted starting at the current cursor position.
Exporting MLE Text
Before using the MLM_EXPORT message the number of characters to export needs to be determined. The MLM_QUERYFORMATTEXTLENGTH message is used to determine the number of characters to be copied from the MLE to the buffer (including LF and CR) and to allocate the room in the buffer. MLM_EXPORT is then used to export the MLE text into the buffer.
Note: The MLM_QUERYTEXTLENGTH message does not consider the CR and LF characters as the MLM_QUERYFORMATTEXTLENGTH message does.
The following code fragment reads text from a file to a buffer, then imports the text to an MLE field:
HWND hwndMle; CHAR szMleBuf[512]; IPT lOffset = 0; PSZ pszTextFile; HFILE hf; ULONG cbCopied; ULONG ulAction; ULONG cbBytesRead; /* Obtain a file name from the user */ /* Open the file */ DosOpen(pszTextFile, &hf, &ulAction, 0, FILE_NORMAL, FILE_OPEN | FILE_CREATE, OPEN_ACCESS_READONLY | OPEN_SHARE_DENYNONE, NULL); /* Zero-fill the buffer using memset, a C run-time function */ memset(szMleBuf, 0, sizeof(szMleBuf)); /* Set the MLE import-export buffer */ WinSendMsg(hwndMle, MLM_SETIMPORTEXPORT, MPFROMP(szMleBuf), MPFROMSHORT((USHORT) sizeof(szMleBuf))); /**********************************************************************/ /* Read the text from the file to the buffer, */ /* then import it to the MLE. */ /**********************************************************************/ do { DosRead(hf, szMleBuf, sizeof(szMleBuf), &cbBytesRead); cbCopied = (ULONG) WinSendMsg(hwndMle, MLM_IMPORT, MPFROMP( &lOffset), MPFROMP(&cbBytesRead)); } while (cbCopied); /* Close the file */ DosClose(hf);
To export MLE text, an application sends the MLM_EXPORT message to the MLE control. Like MLM_IMPORT, the MLM_EXPORT message takes the plOffset and cbCopy parameters. The plOffset parameter is a pointer to a variable that specifies the offset to the first character to export. A value of -1 specifies the current cursor position. On return, the variable contains the offset to the first character in the MLE field not copied to the buffer. The cbCopy parameter is a pointer to a variable that specifies the number of bytes to export. On return, this variable equals 0 if the number of characters actually copied does not exceed the number specified to be copied. The following code fragment shows how to export text from an MLE field, then store the text in a file:
HWND hwndMle; CHAR szMleBuf[512]; IPT lOffset = 0; PSZ pszTextFile; HFILE hf; ULONG cbCopied; ULONG ulAction; ULONG cbBytesWritten; ULONG cbCopy; /* Zero-fill the buffer using memset, a C run-time function */ memset(szMleBuf, 0, sizeof(szMleBuf)); /* Set the MLE import-export buffer */ WinSendMsg(hwndMle, MLM_SETIMPORTEXPORT, MPFROMP(szMleBuf), MPFROMSHORT ((USHORT) sizeof(szMleBuf))); . . . /* Obtain a filename from the user */ . . . /* Open the file */ DosOpen(pszTextFile, &hf, &ulAction, 0, FILE_NORMAL, FILE_OPEN | FILE_CREATE, OPEN_ACCESS_WRITEONLY | OPEN_SHARE_DENYNONE, NULL); /* Find out how much text is in the MLE */ cbCopy = (ULONG) WinSendMsg(hwndMle, MLM_QUERYFORMATTEXTLENGTH, MPFROMLONG(lOffset), MPFROMLONG((-1))); /* Copy the MLE text to the buffer */ cbCopied = (ULONG) WinSendMsg(hwndMle, MLM_EXPORT, MPFROMP(&lOffset), MPFROMP(&cbCopy)); /* Write the contents of the buffer to the file */ DosWrite(hf, szMleBuf, sizeof(szMleBuf), &cbBytesWritten); /* Close the file */ DosClose(hf);
Searching MLE Text
An application uses the MLM_SEARCH message and the MLE_SEARCHDATA data structure to search for strings in MLE text. The first parameter of the MLM_SEARCH message is an array of flags that specify the style of the search. The application can set the MLFSEARCH_CASESENSITIVE flag if a case-sensitive search is required. If the application sets the MLFSEARCH_SELECTMATCH flag, the MLE field control highlights a matching string and, if necessary, scrolls the string into view. An application can use the MLFSEARCH_CHANGEALL flag to replace every occurrence of the string with the string specified in the pchReplace member of the MLE_SEARCHDATA data structure.
The second parameter of the MLM_SEARCH message is a pointer to an MLE_SEARCHDATA data structure that contains information required to perform the search operation. This data structure includes a pointer to the string and, if the MLFSEARCH_CHANGEALL flag is set in the MLM_SEARCH message, a pointer to the replacement string. The iptStart and iptStop members specify the starting and ending positions of the search. These positions are specified as offsets from the beginning of the MLE field. A value of -1 in the iptStart member causes the search to start at the current cursor position. A negative value in the iptStop member causes the search to end at the end of the MLE field. If a matching string is found, the MLE field control returns the length of the string in the cchFound member.
The following code fragment uses an entry field to obtain a search string from the user, then searches an MLE field for an occurrence of the string. The search begins at the current cursor position and ends at the end of the MLE text. When the MLFSEARCH_SELECTMATCH flag is specified, the MLE field control highlights a matching string and scrolls it into view.
The following code fragment shows how to search MLE text:
#define IDD_SEARCHFIELD 101 HWND hwnd; HWND hwndEntryFld; HWND hwndMle; MLE_SEARCHDATA mlesrch; CHAR szSearchString[64]; /* Obtain the handle of the entry field containing the search string */ hwndEntryFld = WinWindowFromID(hwnd, IDD_SEARCHFIELD); /* Obtain the search string from the entry field */ WinQueryWindowText(hwndEntryFld, sizeof(szSearchString), szSearchString); /* Fill the MLE_SEARCHDATA data structure */ mlesrch.cb = sizeof(mlesrch); /* Structure size */ mlesrch.pchFind = szSearchString; /* Search string */ mlesrch.pchReplace = NULL; /* No replacement string */ mlesrch.cchFind = 0; /* Not used */ mlesrch.cchReplace = 0; /* Not used */ mlesrch.iptStart = -1; /* Start at cursor position */ mlesrch.iptStop = -1; /* Stop at end of file */ /* Start the search operation */ WinSendMsg(hwndMle, MLM_SEARCH, MPFROMLONG(MLFSEARCH_SELECTMATCH), MPFROMP(&mlesrch));