Summary:
Using Windows API function calls, you can retrieve information about 
the status of a text box that is not available within the language 
set of Visual Basic.

The following windows message constants are available to the Visual 
Basic program that will perform the following:

* Copy a specific line of text from the edit control(EM_GETLINE).
* Retrieve the number of lines within the edit control 
   (EM_GETLINECOUNT).
* Position the cursor at a specific character location(EM_GETSEL).
* Retrieve the line number of a specific character location 
   (EM_LINEFROMCHAR).
* Retrieve the amount of lines prior to a specified character 
   position (EM_LINEINDEX).
* Retrieve the amount of characters in a specified line 
   (EM_LINELENGTH).
* Replace specified text with another text string(EM_REPLACESEL).

For separate articles that explain how to specify the amount of text 
allowable within a text control, query the Knowledge Base for 
EM_LIMITTEXT.

For a separate article on setting tab stops within a control, query 
the Knowledge Base for EM_SETTABSTOPS.

More information:

The Windows API file USER.EXE defines the SendMessage function which 
will return or perform specific event on your edit control.  To 
create an example which will display specific information about your 
edit control, perform the following:

1.  Create a form called Form1 with the following child controls and 
their properties.

Control	CtlName			H	L	T	W
-----------------------------------------------------------
Label	aGetLine				360	120
Label	aGetLineCount			360	480
Label	aGetSel				360	840
Label	aLineFromChar			360	1200
Label	aLineIndex			360	1560
Label	aLineLenght			360	1920
Label	aReplaceSel			360	2280
Command	Command1			375	360	2640	1815
Text		Text1			1815	2640	480	3495
Text		Text2			375	2520	2640	3615
	
2. Set each labels AZutoSize to TRUE

3. Set the Text1.MultiLine property to TRUE.  

4. Change the Text2.Caption to "Insert this text --->".

5. Within the Global-Declaration section, add the following code:

Declare Function GetFocus% Lib "user" ()
'* NOTE: SendMessage is coded on one line.
Declare Function SendMessage% Lib "user"(ByVal hWnd%, 
								ByVal wMsg%, 
								ByVal wParam%, 
								ByVal lParam As Any)

6. After adding the code listed below to your form, run the program.  
Whenever a key is released, the labels will updated with the new 
information about you text box.

'==============================================================
Sub Form_Load ()
  Show
  X% = fReplaceSel("")
End Sub

'==============================================================
Sub Text1_KeyUp (KeyCode As Integer, Shift As Integer)
  '* Update the text control information whenever the key
  '* is pressed and released.

    CharPos& = fGetSel()
    LineNumber& = fLineFromChar(CharPos&)
    X% = fGetLine(LineNumber&)
    X% = fGetLineCount()
    X% = fLineIndex(LineNumber&)
    X% = fLineLength(CharPos&)
End Sub

'==============================================================
Sub Command1_Click ()
  '* This routine will insert a line of text at the current location
  '* of the caret.
   D$ = Text2.text
   CharPos% = fGetSel()
   X% = fReplaceSel(D$)
   X% = fSetSel(CharPos%)

   '* Text has been inserted at the caret location.  No update the
   '* text controls information.  
   Call Text1_KeyUp(0, 0)
   Text1.SetFocus
End Sub


'==============================================================
Function fGetLineCount& ()
 '* This function will return the number of lines in the edit
 '* control.
   
   Const EM_GETLINECOUNT = &H400 + 10
   
   Text1.SetFocus
   Pos% = SendMessage(GetFocus(), EM_GETLINECOUNT, 0&, 0&)
   aGetLineCount.Caption = "GetLineCount = " + Str$(Pos%)
   fGetLineCount = Pos%
End Function

'==============================================================
Function fGetLine (LineNumber As Long)
  '* This function copies a line of text specified by LineNumber
  '* from the edit control. The first line starts at zero.

   Const MAX_CHAR_PER_LINE = 80
   Const EM_GETLINE = &H400 + 20
   
   Text1.SetFocus
   Buffer$ = Space$(MAX_CHAR_PER_LINE)
   Pos% = SendMessage(GetFocus(), EM_GETLINE, LineNumber, Buffer$)
   aGetLine.Caption = "GetLine = " + Buffer$
   fGetLine = Pos%
End Function

'==============================================================
Function fGetSel& ()
  '* This function returns the starting/ending position of the
  '* current selected text.  This is the current location of the
  '* cursor if start is equal to ending.

  '* LOWORD-start position of selected text
  '* HIWORD-first no selected text

   Const EM_GETSEL = &H400 + 0

   Text1.SetFocus
   location& = SendMessage(GetFocus(), EM_GETSEL, 0&, 0&)
   ending% = location& \ 2 ^ 16
   starting% = location& Xor high%
   aGetSel.Caption = "Caret Location = " + Str$(starting%)
   fGetSel = location&
End Function

'==============================================================
Function fLineFromChar& (CharPos&)
   '* This function will return the line number of the line that
   '* contains the character whose location(index) specified in the
   '* third argument of SendMessage.  If the third argument is -1,
   '* then the number of the line that contains the first character
   '* of the selected text is returned.  If start = end from GetSel, 
   '* then the current caret location is used.  Line numbers start at 
   '* zero.

   Const EM_LINEFROMCHAR = &H400 + 25
   
   Text1.SetFocus
   Pos% = SendMessage(GetFocus(), EM_LINEFROMCHAR, CharPos&, 0&)
   'aLineFromChar.Caption = "Current Line = " + Str$(Pos%)
   fLineFromChar = Pos%
End Function

'==============================================================
Function fLineIndex (LineNumber As Long)
  '* This function will return the number of bytes that
  '* precede the given line.  The returned number reflects the CR/LF 
  '* after each line.  The third argument to SendMessage specifies 
  '* the line number, where the first line number is zero.  If the 
  '* third argument to SendMessage is -1, then the current line 
  '* number is used.

   Const EM_LINEINDEX = &H400 + 11

   Text1.SetFocus
   Pos% = SendMessage(GetFocus(), EM_LINEINDEX, LineNumber, 0&)
   aLineIndex.Caption = "#Char's before line = " + Str$(Pos%)
   fLineIndex = Pos%
End Function

'==============================================================
Function fLineLength& (CharPos As Long)
   '* This function will return the length of a line in the edit
   '* control.  CharPos specifies the index of the character which is 
   '* part of the line that you would like to find the length. If 
   '* this argument is -1, the current selected character is used as 
   '* the index.

   Const EM_LINELENGTH = &H400 + 17
   Text1.SetFocus
   Pos% = SendMessage(GetFocus(), EM_LINELENGTH, CharPos, 0&)
   aLineLength.Caption = "LineLength = " + Str$(Pos%)
   fLineLength = Pos%
End Function

'==============================================================
Function fSetSel& (Pos%)
   '* This function selects all characters in the current text that
   '* are within the starting and ending positions given by Location.  
   '* The low-word is the starting position and the high word is the 
   '* ending position.  If you set start to end, this can be used to 
   '* position the cursor within the edit control.
   
   Const EM_SETSEL = &H400 + 1
   location& = Pos% * 2 ^ 16 + Pos%
   Text1.SetFocus
   X% = SendMessage(GetFocus(), EM_SETSEL, 0&, location&)
   fSetSel = Pos%
End Function

'==============================================================
Function fReplaceSel (Buffer$)
   '* This function will replace the current selected text with the
   '* new text specified in Buffer$.  You must call SendMessage with 
   '* the EM_GETSEL constant to select text.
   
   Const EM_REPLACESEL = &H400 + 18
   Text1.SetFocus
   Pos% = SendMessage(GetFocus(), EM_REPLACESEL, 0&, Buffer$)
   aReplaceSel.Caption = "String inserted = " + Buffer$
   fReplaceSel = Pos%
End Function



