Results 1 to 3 of 3

Thread: Determine Visible

  1. #1

    Thread Starter
    Junior Member
    Join Date
    Jul 2001
    Posts
    21

    Exclamation Determine Visible

    I have a large richtextbox and want to be able to select only the text that is currently visible. Nothing above/below. So if the text is:

    blaah
    asdf
    asdf
    asdf
    blaah

    and all they can see is the "asdf"s because they would have to scroll to see anything else. So I want to select just the "asdf"s..

    Is this possible at all?

  2. #2
    Fanatic Member
    Join Date
    Sep 2000
    Location
    UK.
    Posts
    728

    Info...

    This is by no means a solution, but it should help. You can send certain messages to the text box using the SendMessage API function, which retrieves certain information... There is a message which returns the topmost visible line. e.g.

    VB Code:
    1. Private Const EM_GETFIRSTVISIBLELINE = &HCE
    2. Private Declare Function SendMessage Lib "user32" Alias "SendMessageA" (ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, lParam As Any) As Long
    3.  
    4. 'Code...
    5. Private Sub RichTextBox1_KeyDown(KeyCode As Integer, Shift As Integer)
    6. Me.Caption = "First visible line: " & SendMessage(RichTextBox1.hwnd, EM_GETFIRSTVISIBLELINE, 0&, 0&)
    7. End Sub

    There are other messages (EM_GETLINE etc), but none which will get the visible area of text. If you could find a way of getting the number of visible lines, you could use the info. above to code a solution...

    Hope this has been of some help.
    Laterz
    Digital-X-Treme
    Contact me on MSN Messenger: [email protected]

    [VBCODE]Debug.Print Round(((1097) - ((55 ^ 5 + 311 ^ 3 - 11 ^ 3) _
    / (68 ^ 5))) ^ (1 / 7), 13)[/VBCODE]

  3. #3
    Fanatic Member Kaverin's Avatar
    Join Date
    Oct 2000
    Posts
    930
    I took this out of a class I had made for textboxes and adapted it to fit a more general way of use. It will give you those lines (which I think is what you were ultimately getting at). Even if not, it should help you see how to go about doing this.
    VB Code:
    1. Option Explicit
    2.  
    3. 'the last param was changed from Any to Long
    4. Public Declare Function SendMessage Lib "user32" Alias "SendMessageA" (ByVal hWnd As Long, ByVal wMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
    5. Public Declare Function GetWindowDC Lib "user32" (ByVal hWnd As Long) As Long
    6. Public Declare Function ReleaseDC Lib "user32" (ByVal hWnd As Long, ByVal hDC As Long) As Long
    7. Public Declare Function GetTextExtentPoint32 Lib "gdi32" Alias "GetTextExtentPoint32A" (ByVal hDC As Long, ByVal lpzText As String, ByVal nLength As Long, lpSize As SIZE) As Long
    8.  
    9. Public Type SIZE
    10.    cX As Long
    11.    cY As Long
    12. End Type
    13.  
    14. Public Const EM_GETLINECOUNT As Long = &HBA
    15. Public Const EM_LINEINDEX As Long = &HBB
    16. Public Const EM_LINELENGTH As Long = &HC1
    17. Public Const EM_GETLINE As Long = &HC4
    18. Public Const EM_GETFIRSTVISIBLELINE As Long = &HCE
    19.  
    20. Public Function GetLine(ByVal hWnd As Long, ByVal lngLineNumber As Long) As String
    21.    Dim lngLineCount As Long
    22.    Dim lngFirstChar As Long
    23.    Dim lngLineLength As Long
    24.    Dim abyteBuffer() As Byte
    25.    GetLine = ""
    26.    'get total number of lines
    27.    lngLineCount = SendMessage(hWnd, EM_GETLINECOUNT, 0, 0)
    28.    'exit if the requested value is outside the range
    29.    If (lngLineNumber < 0) Or (lngLineNumber > (lngLineCount - 1)) Then Exit Function
    30.    'get the number of characters that preceed the requested line
    31.    lngFirstChar = SendMessage(hWnd, EM_LINEINDEX, lngLineNumber, 0)
    32.    'get the length of the line containing character number lngFirstChar
    33.    lngLineLength = SendMessage(hWnd, EM_LINELENGTH, lngFirstChar, 0)
    34.    'exit if there's nothing in the line
    35.    If lngLineLength = 0 Then Exit Function
    36.    'resize the buffer
    37.    ReDim abyteBuffer(0 To (lngLineLength - 1))
    38.    'put the first byte of the size into the buffer (this is just how it's expected)
    39.    abyteBuffer(0) = lngLineLength And &HFF
    40.    'if the size is larger than a byte, place the next byte into the next position
    41.    If lngLineLength > 255 Then abyteBuffer(1) = (lngLineLength And &HFF00) \ &H100
    42.    'extract the line
    43.    SendMessage hWnd, EM_GETLINE, lngLineNumber, VarPtr(abyteBuffer(0))
    44.    'convert the byte array to a string
    45.    GetLine = StrConv(abyteBuffer, vbUnicode)
    46. End Function
    47.  
    48. Public Function VisibleLines(ByVal hWnd As Long, ByVal lngHeight As Long) As String
    49.    Dim hDC As Long, i As Long
    50.    Dim lngFirstLine As Long, lngNumLines As Long
    51.    Dim strLine As String
    52.    Dim lpSize As SIZE
    53.    'get the DC of the edit control
    54.    hDC = GetWindowDC(hWnd)
    55.    'get the index of the first visible line
    56.    lngFirstLine = SendMessage(hWnd, EM_GETFIRSTVISIBLELINE, 0, 0)
    57.    'get the text of that line
    58.    strLine = GetLine(hWnd, lngFirstLine)
    59.    'determine the width/height of that text with the current font of the DC
    60.    GetTextExtentPoint32 hDC, strLine, Len(strLine), lpSize
    61.    'release the DC
    62.    ReleaseDC hWnd, hDC
    63.    'estimate the number of lines shown based on the visible height and the height of a row
    64.    lngNumLines = lngHeight \ lpSize.cY
    65.    'if only one is visible, you already have it
    66.    If lngNumLines = 1 Then
    67.       VisibleLines = strLine
    68.       Exit Function
    69.    End If
    70.    'otherwise, go through the rest of the lines grabbing their text
    71.    For i = (lngFirstLine + 1) To (lngFirstLine + lngNumLines - 1)
    72.       strLine = strLine & vbCrLf & GetLine(hWnd, i)
    73.    Next i
    74.    'return it
    75.    VisibleLines = strLine
    76. End Function
    This makes a couple of assumptions, and it's only a generality, but it does pretty much get the visible part. It may be off by a line or so as I noticed, but I don't know of a way to get the number of visible lines directly if there is a way. Perhaps something with GetDeviceCaps() and the hDC of the edit control. The height that you pass in to the VisibleLines() function is the height of the edit control in pixels btw. It will work on RTBs as well, but when you have different fonts, this most likely won't work that well unless they have the same general height line wise.
    I'm baaaack...
    VB5 Professional Edition, VC++ 6
    Using a 1 gHz Thunderbird, 256 mb RAM, 40 gb HD system with Win98se

    I feel special because I finally figured out how to loop midis: Post link
    I'm a fanatic too

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