From Team Developer SqlWindows Wiki
Revision as of 14:51, 17 May 2013 by DaveRabelink (Talk | contribs)

Jump to: navigation, search

This page covers Multiline tips & tricks.


Pointer2.png How to place the cursor at a specific location in the text, text selection and insertion Pointer.png

This applies for datafields and multilines.

Using Windows API messages you can do the following:

  • Set the cursor/caret at a specific location within the text
  • Select a portion or all of the text
  • Insert text at a specific location within the text
  • Replace a preselected portion of text with another text
  • Delete a preselected portion of text
  • Get the current location/selection of text

First define these WinApi constants

   Number: EM_GETSEL         = 0x00B0
   Number: EM_SETSEL         = 0x00B1
   Number: EM_SCROLLCARET    = 0x00B7
   Number: EM_REPLACESEL     = 0x00C2

Place the cursor/caret at a specific character location

The first character position from the left is 0 (zero).
To position the cursor/caret to a specific location, send EM_SETSEL message to the field having wParam and lParam the same value.

   ! Place the cursor at position 200 in the text. Set left and right position at the same value
   Set nLeftPos = 200
   Set nRightPos = 200
   Call SalSendMsg( hWndField, EM_SETSEL, nLeftPos, nRightPos )
   ! When the cursor is out of view, the field does not scroll automatically, so you should scroll it by using :
   Call SalSendMsg( hWndField, EM_SCROLLCARET, 0, 0 )

To set the cursor at the end of the text, use -1 in wParam and lParam.

Select portion of the text

For this you have to define the starting and ending character position.
The wParam holds the start and lParam the end position.

   Set nLeftPos = 200
   Set nRightPos = 210
   Call SalSendMsg( hWndField, EM_SETSEL, nLeftPos, nRightPos )

To select all the text in the field, use wParam = 0 and lParam = -1

Deselect text

To deselect the text, use -1 as value for wParam and lParam.

   Call SalSendMsg( hWndField, EM_SETSEL, -1, -1 )

Insert text at a specific location

First place the cursor at the location you want to insert new text (see above).
Then send the EM_REPLACESEL message to the field using VisSendMsgString.

   ! Place the cursor at position 200 in the text. Set left and right position at the same value
   Set nLeftPos = 200
   Set nRightPos = 200
   Call SalSendMsg( hWndField, EM_SETSEL, nLeftPos, nRightPos )
   ! Now insert some text at the current caret position
   Call VisSendMsgString( hWndField, EM_REPLACESEL, TRUE, "This will be inserted" )

Replace text which is selected

Like above except use the appropriate nLeftPos and nRightPos values.
So first select the part of the text and then send the EM_REPLACESEL message.

Get the current position/selection boundaries

Send the EM_GETSEL message to the field.
It will return the start and end position of the cursor/caret.
The return value contains the start position in Low number and end position in the High number.

   Set nReturn = SalSendMsg( hWndField, EM_GETSEL, 0, 0 )
   Set nLeftPos = SalNumberLow( nReturn ) 
   Set nRightPos = SalNumberHigh( nReturn ) 

If no selections are performed above, you should first set the focus to the field

   Call SalSetFocus( hWndField )

Here you can download a sample:

Pointer2.png How to make a scrollable but disabled multiline Pointer.png

When you disable the field, the scrollbars are also disabled.

Use this instead to have scrolling

   Call VisWinSetFlags ( hWndField, WF_DisplayOnly, TRUE )

Pointer2.png Fast and smooth autoscroll multiline text appending Pointer.png

A common way to append text to a multiline field is to concatenate the text to the multiline field.
Like this:

   Set mlOutput = mlOutput || "Some text to append"

In some cases you could need to show the appended text, to put it into view.
For instance when displaying large amounts of text like for logging/tracing, a realtime and automatic scroll into view is preferable.

To do this, you need to programatically move the vertical thumb of the scrollbar to the bottom after the text is populated.

This is done by sending a message to the multiline field like this:

! Used WinApi constants
Number: WM_VSCROLL     = 0x0115
Number: SB_BOTTOM      = 7

! Scroll the vertical thumb scrollbar to the bottom
Call SalSendMsg( mlOutput, WM_VSCROLL, SB_BOTTOM, NUMBER_Null )

This works, the last text line in the multiline will be scrolled into view.

But when looking closely while populating, the multiline does this not very smoothly. For example the scroll thumb seems to
jump from top to bottom and the text has a flicker. This gives a somewhat unprofessional look & feel.
But another issue: the population is also not as fast as it could be.

To solve this we need another way to append the text. What actually happens when you append text to the multiline like above is that
the field is internally cleared. It is repopulated with the complete new text on every append. This results in the scrollbar jump
to the top and bottom when the new text is placed into the field and causes the text flickering.

Using WinApi, we can actually insert a new text at a specific position in the multiline field.
Position the caret (cursor) at the end of the text in the multiline and then insert the text.

First we need to position the caret at the end, doing this:

! Used WinApi constant
Number: EM_SETSEL    = 0x00B1

! Set the caret at the end of the current text in the multiline
Call SalSendMsg( mlOutput, EM_SETSEL, -1, -1 )

Now we need to insert the text at caret position:

! Used WinApi constant
Number: EM_REPLACESEL = 0x00C2

! Insert the text at the caret position. This will keep the text in the field and only insert the text at the end
! Include vtmisc.apl for the Vis function
Call VisSendMsgString( mlOutput, EM_REPLACESEL, TRUE, "Text to append" )

After this, the text is appended in the field. Only next action is to scroll it into view by sending WM_VSCROLL to the field
as described above.

This in fact will not only make the population smoother and less flicker, but also much faster.

Here you can download a sample: