Link to home
Start Free TrialLog in
Avatar of Jeanette Durham
Jeanette DurhamFlag for United States of America

asked on

vba or api hilite partial text in a textbox and place the text cursor (not the mouse) after the hilited text

Dear Experts,

I am taking a multi-line textbox in access (I cannot add a rich text box control to the form, access says it cannot add it, so this is a regular textbox) and when the user types in something on the first line and then types in something on the second line that matches the first I want it to automatically fill in the first word (the one from line1) on the second line, hilite it in case the user is trying to type something else, and then put the cursor position for the textbox right after the hilited text.

So, if user types this on the first line:
SMITH JOE
And then on the second line types
SM
I want it to automatically fill in SMITH on the second line, hilite SMITH and then put the caret right next to it on the right (right now it is putting it on the left)

The simple answer would be to simply set the selstart to the length of the line, but doing so unhilites the text, I will post my partially working code below in the code section..

Note: I am willing to use windows API calls if that's what it takes to do this.

Thanks! ~Michael
Private Sub Seller_KeyUp(KeyCode As Integer, Shift As Integer)
    Dim myText$, buyerText$, currKey$
    currKey = Chr(KeyCode): myText = UCase(Nz(Me.Seller.text)): buyerText = UCase(Nz(Me.Buyer))
    If InStr("ABCDEFGHIJKLMNOPQRSTUVWXYZ ", UCase(currKey)) > 0 Then
        If InStr(myText, vbCr) > 0 Then
            Dim line2$, line1$, line1_word1$, line2_word1$, newText$, newPos As Integer
            line1 = firstLine(myText)
            line1_word1 = firstWord(myText)
            line2 = secondLine(myText)
            line2_word1 = firstWord(line2)
            If InStr(line2, " ") > 0 Then Exit Sub 'must be still typing the first word of the second line
            If Len(line2_word1) < 2 Then Exit Sub
            If line2_word1 = Left(line1_word1, Len(line2_word1)) Then
                'words are matching, insert word and hilite just that word
                newText = line1 & vbCrLf
                newPos = Len(newText) + 1
                newText = newText & line1_word1 & " "
                Me.Seller = newText
                Me.Seller.SelStart = newPos
                Me.Seller.SelLength = Len(line1_word1) + 1	'now the cursor is on the left of the hilited text (selstart) which is wrong
            End If
       end if
end sub

'Other supporting functions

Public Function firstLine(ByVal someStr$) As String
    firstLine = myTrim(someStr, vbCrLf)
    If InStr(firstLine, vbCrLf) = 0 Then Exit Function
    firstLine = Left(firstLine, InStr(firstLine, vbCrLf) - 1)
End Function

Public Function secondLine(ByVal someStr$)
    'returns "" if there is no 2nd line
    Dim linePos As Integer
    linePos = InStr(someStr, vbCrLf)
    If linePos = 0 Then Exit Function
    secondLine = Mid(someStr, linePos + 2)
    linePos = InStr(secondLine, vbCrLf)
    If linePos > 0 Then secondLine = Mid(secondLine, 1, linePos - 1)
End Function

Public Function firstWord(ByVal someStr$) As String
    firstWord = Trim(someStr)
    If InStr(firstWord, " ") = 0 Then Exit Function
    firstWord = Left(firstWord, InStr(firstWord, " ") - 1)
End Function

Open in new window

ASKER CERTIFIED SOLUTION
Avatar of SStory
SStory
Flag of United States of America image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
If not, here is an article on getting and setting the textbox caret from vb.net:

http://dotnet.mvps.org/dotnet/faqs/?id=textboxcaretpos&lang=en

It uses SendMessage,GetCaretPos, and SetCaretPos API calls - note you will need the pre vb.net version of DECLARES for use in VBA
Avatar of puppydogbuddy
puppydogbuddy

this link uses an html tag in a rich texbox....see if it helps for what you want it to do:
                http://allenbrowne.com/AppSearchHighlight.html
I would suggest a completely different approach.  Make a table to store the values that are now typed into lines of the multi-line textbox, and display it in a datasheet subform.  This is better from the point of view of normalization, and much easier to work with besides.
Avatar of Jeanette Durham

ASKER

JDettman:
No worries Jim Dettman, my first name is Jeffrey, and my second name is Michael. So for work, money, taxes, etc, I go by Jeffrey, but I otherwise go by Michael, which is why I will end comments or letters or whatever with Michael. But yeah, it's just me.

SStory:
Actually I like your idea for how to track it using an array or whatnot. The only reason I wanted the caret at the end is if the user liked the word and kept typing, I wanted them to be able to hit the arrow key once to get over and then keep typing, or I was debating trapping the space, and if the word is good just keep going. But basically, the reason was the cursor was way to the left of the word and that was awkward for entering data and stuff. Umm, lemme toy with your idea and if that doesn't go I'll do the API. Thanks!
Helen_Feddema:
For this field I really only need to deal with two lines of text, so I don't think it's really necessary to make a table to hold the data. I think just holding the text in memory wouldn't be a big deal since it's so little, and would probably be faster.
Well yeah... You could still trap the tab key, deselect, move caret to the end.  
Thank you SStory!

Yep, keeping it in memory and altering it to fit is an excellent approach. Thanks for the good idea! Also, thanks for the api info too, now I know everything I wanted to know!

~Jeffrey
Hey you are welcome.