Using Windows API Functions to Better Manipulate Text Boxes

ID Number: Q76518

1.00

WINDOWS

docerr

Summary:

By calling Windows API functions from Visual Basic, you can retrieve

text box (or edit control) information that you cannot obtain using

only Visual Basic's built-in features.

This article supplies a sample program that performs the following

useful features (making use of the Windows message constants shown in

parentheses, obtained by calling Windows API routines):

- Copy a specific line of text from the text box (EM_GETLINE).

- Retrieve the number of lines within the text box (EM_GETLINECOUNT).

- Position the cursor at a specific character location (EM_GETSEL) in

the text box.

- Retrieve the line number of a specific character location in the

text box (EM_LINEFROMCHAR).

- Retrieve the amount of lines before a specified character position

in the text box (EM_LINEINDEX).

- Retrieve the amount of characters in a specified line in the text

box (EM_LINELENGTH).

- Replace specified text with another text string (EM_REPLACESEL).

For a separate article that explains how to specify the amount of text

allowable within a text control, query on the following word in the

Microsoft Knowledge Base:

EM_LIMITTEXT

This information applies to Microsoft Visual Basic programming system

version 1.0 for Windows.

More Information:

(Note that as of 3/25/92, the code below corrects the VBKNOWLG.HLP

file Knowledge Base shipped with Microsoft Professional Toolkit for

Visual Basic version 1.0.)

(Note that using the SelStart, SelLength, and SelText properties may

be easier than using EM_GETSEL and EM_REPLACESEL below.)

The Windows API file USER.EXE defines the SendMessage function that

will return or perform a specific event on your edit control. To

create an example that will display specific information about your

edit control, do the following:

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

properties:

Control CtlName Height Left Top Width

------- ------- ------ ---- --- -----

Label aGetLine 360 120

Label aGetLineCount 360 480

Label aGetSel 360 840

Label aLineFromChar 360 1200

Label aLineIndex 360 1560

Label aLineLength 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 label's AutoSize property to True.

3. Set the Text1.MultiLine property to True.

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

5. Within the global Declarations section, add the following code:

Declare Function GetFocus% Lib "user" ()

Declare Function SendMessage& Lib "user"(ByVal hWnd%, ByVal wMsg%,

ByVal wParam%,

ByVal lParam As Any)

'lParam is actually a double word, or long, but declaring

' lParam "As Any" allows flexibility for certain cases of

' using SendMessage.

'* NOTE: The SendMessage Declare above must be placed on one line.

6. After adding the code listed below to your form, run the program.

Whenever a key is released, the labels will be updated with the new

information about your text box.

Sub Form_Load ()

Show

X% = fReplaceSel("") '* used to display the correct text.

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

byteLo% = MAX_CHAR_PER_LINE And (255) '[changed 3/25/92]

byteHi% = Int(MAX_CHAR_PER_LINE / 256) '[changed 3/25/92, two lines:]

Buffer$ = chr$(byteLo%) + chr$(byteHi%) + Space$(MAX_CHAR_PER_LINE-2)

Text1.SetFocus

Pos& = SendMessage(GetFocus(), EM_GETLINE, CINT(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& mod 65536

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, CINT(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, CINT(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 that

'* 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, CINT(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

Reference(s):

"Programming Windows: The Microsoft Guide to Writing Applications for

Windows 3," Charles Petzold, Microsoft Press, 1990

"Microsoft Windows Software Development Kit: Reference Volume 1,"

version 3.0

WINSDK.HLP file shipped with Microsoft Windows 3.0 Software

Development Kit

Additional reference words: 1.00 3.00