Results 1 to 10 of 10

Thread: [RESOLVED] Find vbCrLf in multiline textbox

  1. #1

    Thread Starter
    PowerPoster SamOscarBrown's Avatar
    Join Date
    Aug 2012
    Location
    NC, USA
    Posts
    9,145

    Resolved [RESOLVED] Find vbCrLf in multiline textbox

    I populated a multiline textbox with code like:

    Code:
     Do While Not rs.EOF        Text2.Text = Text2.Text & rs!Chapter & ":" & rs!verse & " " & rs!body & vbCrLf
            rs.MoveNext
        Loop
    Am declaring Sendmessage API and Constants as follows:

    Code:
    Private Declare Function SendMessage Lib "user32" Alias "SendMessageA" (ByVal HWnd As Long, ByVal wMsg As Long, ByVal wParam As Long, lParam As Any) As LongConst EM_LINEFROMCHAR = &HC9
    Private Const EM_GETLINE = &HC4
    Private Const EM_LINEINDEX = &HBB
    Private Const EM_LINELENGTH = &HC1
    Here is first sendmessage call to get selected line number (with Mouse):

    Code:
    Public Function TB_LineIndex(ByRef sTextBox As TextBox) As Long    
    Dim lngRet As Long
        '
        lngRet = SendMessage(sTextBox.HWnd, EM_LINEFROMCHAR, -1, ByVal 0&)
        TB_LineIndex = lngRet + 1
    End Function
    Here is second sendmessage call to get actual text of the line:

    Code:
    Public Function GetTextBoxLine(objTB As TextBox, ByVal LineNum As Integer) As String    Dim lngRet As Long
        Dim lngLen As Long
        Dim lngFirstCharPos As Long
        Dim lngHwnd As Long
        Dim bytBuffer() As Byte
        Dim strAns As String
        If LineNum < 0 Then Exit Function
        If objTB.MultiLine = False Then
            GetTextBoxLine = objTB.Text
        Else
            lngHwnd = objTB.HWnd
            lngFirstCharPos = SendMessage(lngHwnd, EM_LINEINDEX, LineNum - 1, 0&)
            lngLen = SendMessage(lngHwnd, EM_LINELENGTH, lngFirstCharPos, 0&)
            ReDim bytBuffer(lngLen) As Byte
            bytBuffer(0) = lngLen
            lngRet = SendMessage(lngHwnd, EM_GETLINE, LineNum - 1, bytBuffer(0))
            If lngRet Then strAns = Left$(StrConv(bytBuffer, vbUnicode), lngLen)
            GetTextBoxLine = strAns
        End If
    End Function
    Now, here is the code I am using to try to find the vbCrLf in the selected line of the multiline textbox (with mouse):

    Code:
    Private Sub Text2_Click()    
        Dim myLine As Integer
        myLine = TB_LineIndex(Text2)
        Dim sLine As String
        sLine = GetTextBoxLine(Text2, myLine)
        If InStr(1, sLine, vbCrLf) > 0 Then
            Debug.Print sLine
        End If
        
    End Sub
    Although sLine IS the selected line of the textbox (when shown outside of if-then-end), there is no vbCrLf in it (the InStr call is always zero)..

    What I want to find is the location of that vbCrLf I added when I populated the textbox; but first, just the test above to see if in exists in the line selected by Mouse.

  2. #2
    VB-aholic & Lovin' It LaVolpe's Avatar
    Join Date
    Oct 2007
    Location
    Beside Waldo
    Posts
    19,541

    Re: Find vbCrLf in multiline textbox

    Sam, per MSDN
    EM_LINELENGTH

    For multiline edit controls, the return value is the length, in TCHARs, of the line specified by the wParam parameter. For ANSI text, this is the number of bytes; for Unicode text, this is the number of characters. It does not include the carriage-return character at the end of the line.
    If you need to know if a vbCrLf follows the end of the returned line, you could probably use VB's Text2.SelStart value:
    Code:
    ' following needs to be tested well..
    Private Sub Text2_Click()
        Dim myLine As Integer
        myLine = TB_LineIndex(Text2)
        Dim sLine As String
        sLine = GetTextBoxLine(Text2, myLine)
        Dim lRawPos As Long, lStart As Long, lSize As Long
        lSize = Len(sLine)
        lStart = Text2.SelStart - lSize
        If lStart < 1 Then lStart = 1
        lRawPos = InStr(lStart, Text2.Text, sLine)
        If Mid$(Text2.Text, lRawPos + lSize, 2) = vbCrLf Then
            Debug.Print "sLine does have a carriage return at end of line in source text"
        End If    
    End Sub
    Edited: Also note that "bytBuffer(0) = lngLen" will error if the line consists of more than 255 characters. The 1st two bytes of that buffer are used to define the size of the buffer, not just the 1st byte.

    Another gotcha. This line:
    Code:
    If lngRet Then strAns = Left$(StrConv(bytBuffer, vbUnicode), lngLen)
    Should read as shown, no guarantee that lngRet & lngLen will be identical (though they should be)
    Code:
    If lngRet Then strAns = Left$(StrConv(bytBuffer, vbUnicode), lngRet)
    Last edited by LaVolpe; May 23rd, 2018 at 07:45 PM.
    Insomnia is just a byproduct of, "It can't be done"

    Classics Enthusiast? Here's my 1969 Mustang Mach I Fastback. Her sister '67 Coupe has been adopted

    Newbie? Novice? Bored? Spend a few minutes browsing the FAQ section of the forum.
    Read the HitchHiker's Guide to Getting Help on the Forums.
    Here is the list of TAGs you can use to format your posts
    Here are VB6 Help Files online


    {Alpha Image Control} {Memory Leak FAQ} {Unicode Open/Save Dialog} {Resource Image Viewer/Extractor}
    {VB and DPI Tutorial} {Manifest Creator} {UserControl Button Template} {stdPicture Render Usage}

  3. #3

    Thread Starter
    PowerPoster SamOscarBrown's Avatar
    Join Date
    Aug 2012
    Location
    NC, USA
    Posts
    9,145

    Re: Find vbCrLf in multiline textbox

    Ah, very good, Fox.
    Didn't catch the lngRet either...thanks.

    So, here is my dilemma... I have a multiline textbox with Bible verses that wrap...some take up more than one line (several, do, as a matter of a fact.). My goal is to click on a "LINE" (well, actually, a VERSE---so, if a verse took up, say, three lines, I'd want to 'select' that line, but recognize it to be part of a verse). I thought if I were to find vbCrLf's, I could finagle it to produce what I wanted. Essentially, each 'verse' will begin with a chapter and verse number (like "3:23 ", followed by the actual verse (which will probably take up more than one line in the ML textbox.)). I guess I could search any previous lines until I found one that began with the chapter and verse number, and then go back to my database with a query to display the entire verse in a separate textbox. Guess I try that approach.
    Thanks for the correction and the MSDN info...

    In summary: I simply want to display in another textbox ONE of the verses a user clicks on (no matter what line of that verse he/she selects)...the ML textbox (text2) in my program (I know, a better naming convention would be wise!!!, but then, I am the only 'developer') contains at any one given time, an entire chapter in a Bible book. Maybe the use of an RTB or even a Grid would have been better choices instead of the ML textbox, but that is what I got, so thought I'd muddle through.

    Again, thanks

    Sam

  4. #4
    VB-aholic & Lovin' It LaVolpe's Avatar
    Join Date
    Oct 2007
    Location
    Beside Waldo
    Posts
    19,541

    Re: Find vbCrLf in multiline textbox

    Sam, look at my edited reply. I included a possible fix if I understood correctly

    The idea was to get the line from textbox via API as you are doing. Then locate that line in the actual source text, overlap the API returned line and see if a carriage return immediately follows.
    Insomnia is just a byproduct of, "It can't be done"

    Classics Enthusiast? Here's my 1969 Mustang Mach I Fastback. Her sister '67 Coupe has been adopted

    Newbie? Novice? Bored? Spend a few minutes browsing the FAQ section of the forum.
    Read the HitchHiker's Guide to Getting Help on the Forums.
    Here is the list of TAGs you can use to format your posts
    Here are VB6 Help Files online


    {Alpha Image Control} {Memory Leak FAQ} {Unicode Open/Save Dialog} {Resource Image Viewer/Extractor}
    {VB and DPI Tutorial} {Manifest Creator} {UserControl Button Template} {stdPicture Render Usage}

  5. #5

    Thread Starter
    PowerPoster SamOscarBrown's Avatar
    Join Date
    Aug 2012
    Location
    NC, USA
    Posts
    9,145

    Re: Find vbCrLf in multiline textbox

    Yeah....didn't even read your 'fix' with selStart. But, already did it my way...simply looped backwards until I found the line with the 'chapter and verse' (e.g. 2:23)...that is all I really needed...simple call now to the DB to pull that info the other textbox.

    'Twas easy...as I am sure selStart would have been as well.

    Marking as resolved...sometimes I just need to bounce things off folks to figure it out...but your input is ALWAYS spot on...thanks

    Sam

  6. #6
    VB-aholic & Lovin' It LaVolpe's Avatar
    Join Date
    Oct 2007
    Location
    Beside Waldo
    Posts
    19,541

    Re: [RESOLVED] Find vbCrLf in multiline textbox

    That's pretty much what my solution was. SelStart was a starting point to go find the target string. And also it's a more solid position to begin looking should the API-returned line exist more than once in your overall text.
    Insomnia is just a byproduct of, "It can't be done"

    Classics Enthusiast? Here's my 1969 Mustang Mach I Fastback. Her sister '67 Coupe has been adopted

    Newbie? Novice? Bored? Spend a few minutes browsing the FAQ section of the forum.
    Read the HitchHiker's Guide to Getting Help on the Forums.
    Here is the list of TAGs you can use to format your posts
    Here are VB6 Help Files online


    {Alpha Image Control} {Memory Leak FAQ} {Unicode Open/Save Dialog} {Resource Image Viewer/Extractor}
    {VB and DPI Tutorial} {Manifest Creator} {UserControl Button Template} {stdPicture Render Usage}

  7. #7
    PowerPoster
    Join Date
    Feb 2006
    Posts
    24,482

    Re: [RESOLVED] Find vbCrLf in multiline textbox

    Too bad you can't use a RichTextBox or InkEdit control for this. It all becomes pretty simple then:

    Code:
    Option Explicit
    
    Private Const WM_USER As Long = &H400&
    Private Const EM_GETOLEINTERFACE As Long = WM_USER + 60&
    Private Const EM_SETEDITSTYLEEX As Long = WM_USER + 275&
    Private Const SES_EX_NOACETATESELECTION As Long = &H100000
    
    Private Declare Function SendMessage Lib "user32" Alias "SendMessageW" ( _
        ByVal hWnd As Long, _
        ByVal wMsg As Long, _
        ByVal wParam As Long, _
        ByVal lParam As Long) As Long
    
    Private Const CP_ACP = 0 'Default ANSI codepage of the process.
    
    Private TextDocument As tom.ITextDocument
    
    Private Sub Form_Initialize()
        Dim IUnknown As stdole.IUnknown
    
        With InkEdit1
            SendMessage .hWnd, _
                        EM_SETEDITSTYLEEX, _
                        SES_EX_NOACETATESELECTION, _
                        SES_EX_NOACETATESELECTION
            SendMessage .hWnd, EM_GETOLEINTERFACE, 0, VarPtr(IUnknown)
            Set TextDocument = IUnknown
        End With
        TextDocument.Open "KJB-Chap-1.rtf", tomRTF Or tomReadOnly, CP_ACP
    End Sub
    
    Private Sub Form_Resize()
        If WindowState <> vbMinimized Then
            With Text1
                .Move 0, ScaleHeight - .Height, ScaleWidth
                InkEdit1.Move 0, 0, ScaleWidth, .Top
            End With
        End If
    End Sub
    
    Private Sub InkEdit1_Click()
        With TextDocument.Selection
            .MoveStart tomParagraph, -1
            .MoveEnd tomParagraph, 1
            Text1.Text = .Text
        End With
    End Sub
    Name:  sshot.png
Views: 1375
Size:  12.5 KB


    Note that the only difference with an InkEdit control is that I am setting the SES_EX_NOACETATESELECTION extended style so that selected text highlighting matches that of an intrinsic TextBox and other controls. Without that you'd see the system "Acetate" selection which is typically a lighter translucent blue shade.

    With a RichTextBox you have the creakier old RichEdit 1.0 inside, where selected text is always highlighted using color complementing.
    Attached Files Attached Files

  8. #8
    PowerPoster
    Join Date
    Feb 2006
    Posts
    24,482

    Re: [RESOLVED] Find vbCrLf in multiline textbox

    I have no idea why some of the lines in the sample text contain paragraph marker (pilcrow) characters: "ΒΆ" in them.

    This was just some sample text I chopped off the start of a Bible RTF I have in my test data folder. The original source had those funky symbols in it. They seem to be setting off quotes or something.

  9. #9
    PowerPoster
    Join Date
    Feb 2006
    Posts
    24,482

    Re: [RESOLVED] Find vbCrLf in multiline textbox

    Ok, a search turned this up: The Pilcrow.

    I got bored quickly though and never did manage to weed a definition out of the guy's purple prose. Maybe somebody else will have more patience and better luck.

  10. #10

    Thread Starter
    PowerPoster SamOscarBrown's Avatar
    Join Date
    Aug 2012
    Location
    NC, USA
    Posts
    9,145

    Re: [RESOLVED] Find vbCrLf in multiline textbox

    Yes...I coulda (and probably shoulda) used an RTB....But I just threw this together really quickly (it's for my sole use, BTW). I wanted a program to display/search/etc in the OT Apocrypha...I already have a program I created for several versions of the Christian Bible (which gets my use daily).

    I'll keep this in mind (the RTB), however, if I decide on some other similar project.

    Thanks, dile

    Sam

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width