Results 1 to 9 of 9

Thread: [SRC] cListBoxMultiAlign [by Mr. Frog ©]

  1. #1

    Thread Starter
    Addicted Member *PsyKE1*'s Avatar
    Join Date
    Jun 2010
    Location
    Spain
    Posts
    243

    Thumbs up [SRC] cListBoxMultiAlign [by Mr. Frog ©]

    I leave my last class used to justify text in a ListBox, the novelty is that you can specifically act on each Item, I leave the code:
    vb Code:
    1. Option Explicit
    2. '==================================================================================================
    3. ' º Class     : MultiAlignListBox.cls
    4. ' º Version   : 1.1
    5. ' º Author    : Mr.Frog ©
    6. ' º Country   : Spain
    7. ' º Mail      : [email protected]
    8. ' º Date      : 14/12/2010
    9. ' º Twitter   : http://twitter.com/#!/PsYkE1
    10. ' º Tested on : WinXp & Win7
    11. ' º Greets    : LaVolpe & Raul338 & BlackZer0x
    12. ' º Reference : http://www.elguille.info/colabora/vb2006/karmany_centrartextolistbox.htm
    13. ' º Recommended Websites :
    14. '       http://visual-coders.com.ar
    15. '       http://InfrAngeluX.Sytes.Net
    16. '==================================================================================================
    17.  
    18. Private Declare Function GetDialogBaseUnits Lib "user32" () As Long
    19. Private Declare Function GetDC Lib "user32" (ByVal hwnd As Long) As Long
    20. Private Declare Function ReleaseDC Lib "user32" (ByVal hwnd As Long, ByVal hDC As Long) As Long
    21. Private Declare Function GetClientRect Lib "user32" (ByVal hwnd As Long, lpRect As RECT) As Long
    22. Private Declare Function SelectObject Lib "gdi32" (ByVal hDC As Long, ByVal hObject As Long) As Long
    23. 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
    24. Private Declare Function GetTextExtentPoint32 Lib "gdi32" Alias "GetTextExtentPoint32A" (ByVal hDC As Long, ByVal lpString As String, ByVal cbString As Long, lpSize As SIZE) As Long
    25.  
    26. Private Type RECT
    27.     Left    As Long
    28.     Top     As Long
    29.     Right   As Long
    30.     Bottom  As Long
    31. End Type
    32.  
    33. Private Type SIZE
    34.     cX      As Long
    35.     cY      As Long
    36. End Type
    37.  
    38. Private Const LB_SETTABSTOPS                        As Long = &H192&
    39. Private Const WM_GETFONT                            As Long = &H31&
    40.  
    41. Private Const CHARS_LIST                            As String = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890"
    42. Private Const CHARS_LEN                             As Long = &H3E&
    43.  
    44. Private myListBox                                   As ListBox
    45. Private lListhWnd                                   As Long
    46. Private lWidth                                      As Long
    47.  
    48. Public Sub SetListBox(myList As ListBox)
    49.     If Not (myList Is Nothing) Then
    50.         Set myListBox = myList
    51.         lListhWnd = myListBox.hwnd
    52.         SetRightTab
    53.     End If
    54. End Sub
    55.  
    56. Public Sub AddAlignItem(ByVal Item As String, ByVal Align As AlignmentConstants, Optional ByVal Index As Long = (-1))
    57. Dim lCenterAlign                                    As Long
    58.  
    59.     With myListBox
    60.         lCenterAlign = Int(.Width - PixelsPerUnit(Item))
    61.         If lCenterAlign < 0 Then Align = vbLeftJustify
    62.        
    63.         If Index = (-1) Then Index = .ListCount
    64.        
    65.         Select Case Align
    66.             Case vbRightJustify
    67.                 .AddItem vbTab & Item, Index
    68.                 If Not (lWidth = GetListSize) Then SetRightTab
    69.             Case vbCenter
    70.                 .AddItem Space$(Abs(Int(lCenterAlign / PixelsPerUnit(Space$(1)) / 2) - 1.5)) & Item, Index
    71.             Case Else
    72.                 .AddItem Item, Index
    73.         End Select
    74.     End With
    75. End Sub
    76.  
    77. Public Sub ChangeListBoxAlign(Optional ByVal Index As Long = (-1), Optional ByVal Align As AlignmentConstants = vbAlignLeft)
    78. Dim Q                                               As Long
    79.  
    80.     If Index > -1 Then
    81.         SetAlign Index, Align
    82.     Else
    83.         For Q = 0 To (myListBox.ListCount - 1)
    84.             SetAlign Q, Align
    85.         Next Q
    86.     End If
    87. End Sub
    88.  
    89. Public Function GetItem(ByVal Index As Long) As String
    90.     GetItem = LTrim$(myListBox.List(Index))
    91.    
    92.     If (GetItem Like (vbTab & "*")) Then
    93.         GetItem = Right$(GetItem, (Len(GetItem) - 1))
    94.     End If
    95. End Function
    96.  
    97. Private Sub SetAlign(ByVal Index As Long, ByVal Align As AlignmentConstants)
    98. Dim sItem                                           As String
    99.  
    100.     With myListBox
    101.         sItem = GetRealItem(Index)
    102.         If Not (.List(Index) = sItem) Then
    103.             .RemoveItem (Index)
    104.             AddAlignItem sItem, Align, Index
    105.         End If
    106.     End With
    107. End Sub
    108.  
    109. Private Sub SetRightTab()
    110. Dim lRightAlignTab                                  As Long
    111.  
    112.     lWidth = GetListSize
    113.     lRightAlignTab = -(lWidth / PixelsPerUnit)
    114.    
    115.     SendMessage lListhWnd, LB_SETTABSTOPS, &H0&, ByVal &H0&
    116.     SendMessage lListhWnd, LB_SETTABSTOPS, &H1&, lRightAlignTab
    117.    
    118.     myListBox.Refresh
    119. End Sub
    120.  
    121. Private Function GetListSize() As Long
    122. Dim RCT                                             As RECT
    123.  
    124.     GetClientRect lListhWnd, RCT
    125.     With RCT
    126.         GetListSize = (.Right - .Left)
    127.     End With
    128. End Function
    129.  
    130.  
    131. Private Function PixelsPerUnit(Optional ByVal sText As String) As Single
    132. Dim hDC                                             As Long
    133. Dim hFont                                           As Long
    134. Dim hFontOld                                        As Long
    135. Dim SZ                                              As SIZE
    136.  
    137.     hDC = GetDC(lListhWnd)
    138.     If CBool(hDC) = True Then
    139.         hFont = SendMessage(lListhWnd, WM_GETFONT, &H0&, ByVal &H0&)
    140.         hFontOld = SelectObject(hDC, hFont)
    141.        
    142.         If sText = vbNullString Then
    143.             If GetTextExtentPoint32(hDC, CHARS_LIST, CHARS_LEN, SZ) Then
    144.                 PixelsPerUnit = CSng((2 * CLng(SZ.cX / CHARS_LEN)) / (GetDialogBaseUnits And &HFFFF&))
    145.             End If
    146.         Else
    147.             If GetTextExtentPoint32(hDC, sText, Len(sText), SZ) Then
    148.                 PixelsPerUnit = (SZ.cX * Screen.TwipsPerPixelX)
    149.             End If
    150.         End If
    151.        
    152.         SelectObject hDC, hFontOld
    153.         ReleaseDC lListhWnd, hDC
    154.     End If
    155. End Function
    156.  
    157. Private Sub Class_Initialize()
    158.     Debug.Print "--> cListBoxMultiAlign.cls By Mr.Frog © <--"
    159. End Sub

    A picture is worth a thousand words:

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

    Re: [SRC] cListBoxMultiAlign [by Mr. Frog ©]

    Mr. Frog. Good job, couple things...

    1) If you add just enough right/center aligned items to fill up the listbox before a scrollbar appears then add 1 more item, left aligned, to force a scrollbar, your right align items are partially hidden by the scrollbar and centered items are no longer centered.

    2) It should be noted that center aligned items are space padded, so if one needs to get the item from the listbox, they should remove any leading spaces. Same applies to right aligned items, user must strip the tab from the item

    3) I don't think SendMessage with LB_FINDSTRING, LB_FINDSTRINGEXACT will work with your listbox implementation due to added leading characters

    4) Not an issue per se, if someone changes the font of the listbox after items are loaded, alignment will go nuts. But who does that anyway?
    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
    Addicted Member *PsyKE1*'s Avatar
    Join Date
    Jun 2010
    Location
    Spain
    Posts
    243

    Re: [SRC] cListBoxMultiAlign [by Mr. Frog ©]

    Really thanks for your opinion LaVolpe!
    I have some questions for you:

    1.-How i Know what is the last item before scrollbar appears?

    2.-I thounght that it would be better like this:

    vb Code:
    1. '...
    2. Private myListBox                                   As ListBox
    3. Private lListhWnd                                   As Long
    4. Private lWidth                                      As Long
    5.  
    6. Public Sub SetListBox(myList As ListBox)
    7.     If Not (myList Is Nothing) Then
    8.         Set myListBox = myList
    9.         lListhWnd = myListBox.hWnd
    10.         SetRightTab
    11.     End If
    12. End Sub
    13.  
    14. Public Sub AddAlignItem(ByVal Item As String, ByVal Align As AlignmentConstants, Optional ByVal Index As Long = (-1))
    15.     If Index = (-1) Then Index = myListBox.ListCount
    16.    
    17.     Select Case Align
    18.         Case vbRightJustify
    19.             myListBox.AddItem vbTab & Item, Index
    20.             If lWidth <> myListBox.Width Then SetRightTab
    21.         Case vbCenter
    22.             myListBox.AddItem Space$(Abs(Int(Int(Int(myListBox.Width - UnitPerPixels(Item))) / UnitPerPixels(Space$(1)) / 2) - 1.5)) & Item, Index
    23.         Case Else
    24.             myListBox.AddItem Item, Index
    25.     End Select
    26. End Sub
    27. '...
    28. Private Sub SetRightTab()
    29. Dim RCT                                             As RECT
    30. Dim lRightAlignTab                                  As Long
    31.    
    32.     lWidth = myListBox.Width
    33.    
    34.     GetClientRect lListhWnd, RCT
    35.     With RCT
    36.         lRightAlignTab = -((.Right - .Left) / UnitPerPixels)
    37.     End With
    38.    
    39.     SendMessage lListhWnd, LB_SETTABSTOPS, 0&, ByVal 0&
    40.     SendMessage lListhWnd, LB_SETTABSTOPS, 1&, lRightAlignTab
    41.     myListBox.Refresh
    42. End Sub
    43. '...
    Like this i wouldn't have to set tab everytime, only if the width of my listbox changes. But it return this:
    your right align items are partially hidden by the scrollbar and centered items are no longer centered.
    3.-And i can add function called "RefreshList" wich comprobe if the fontsize or fontbold... changes (it would be too ugly?)

    4.-Why you don't like my GetRealItem() function to remove tabs and/or spaces?

    It's all by now, thanks again friend!

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

    Re: [SRC] cListBoxMultiAlign [by Mr. Frog ©]

    Quote Originally Posted by *PsyKE1*
    1.-How i Know what is the last item before scrollbar appears?
    2.-I thounght that it would be better like this...
    ^^ Good idea.
    Quote Originally Posted by *PsyKE1*
    3.-And i can add function called "RefreshList" wich comprobe if the fontsize or fontbold... changes (it would be too ugly?)
    ^^ Ugly, no. But can be time consuming if there are 1000s of items in the list
    Quote Originally Posted by *PsyKE1*
    4.-Why you don't like my GetRealItem() function to remove tabs and/or spaces?
    ^^ That will work. Just didn't notice it because I wasn't looking for it.

    Doing this using the VB listbox as-is, has its inherent problems. For small lists, it isn't a problem re-centering center aligned items when the scrollbar is added/removed, but large lists will be. If you had control over drawing the listbox, then things would be different and more efficient because you wouldn't have to re-align every list item, only the ones displayed. However, this requires subclassing and owner-drawing the listbox and would be an entire project on its own, not just a relatively simple class.

    For large lists, the ability to search the listbox using LB_FINDSTRING & LB_FINDSTRINGEXACT is a huge advantage because it is very fast. By appending spaces & tabs to list items, one can no longer use the API to search. That, I think, is the biggest downside. Otherwise, good job and could be very useful for specific purposes.

    One more item. You might want to test your centering routine for very long list items that would extend past the client rect
    Last edited by LaVolpe; Dec 15th, 2010 at 08:48 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}

  5. #5

    Thread Starter
    Addicted Member *PsyKE1*'s Avatar
    Join Date
    Jun 2010
    Location
    Spain
    Posts
    243

    Re: [SRC] cListBoxMultiAlign [by Mr. Frog ©]

    I updated the code again.
    Check it.

    1.-I added SearchSimilarItem function which returns the index of the first similar/equal item (that's what you said I should do?)
    Example:
    vb Code:
    1. MsgBox List1.List(LMA.SearchSimilarItem("verda")) ' It returns 'Verdana'

    I did this funtion long ago: Check_SimilarWords
    I may be able to deploy in some way.

    2.-Finally I only check the Width becouse i would spend too time as you have said.

    3.-I fixed this:
    One more item. You might want to test your centering routine for very long list items that would extend past the client rect
    4.-Now my last (I hope :P) problem is this:
    your right align items are partially hidden by the scrollbar and centered items are no longer centered.
    A solution may be this (but I don't like it ):

    Chage this:
    vb Code:
    1. If Not (lWidth = myListBox.Width) Then SetRightTab

    by this:
    vb Code:
    1. SetRightTab

    I learn a lot with you, i hope your reply.. :P

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

    Re: [SRC] cListBoxMultiAlign [by Mr. Frog ©]

    Your search won't work for center/right aligned items. Try it. Result is always -1 (failure)
    Code:
        Dim c As New Class1
        c.SetListBox List1
        c.AddAlignItem "LaVolpe", vbCenter
        MsgBox c.SearchSimilarItem("LaVolpe")
        c.AddAlignItem "Mr.Frog", vbRightJustify
        MsgBox c.SearchSimilarItem("Mr.Frog")
    Now regarding the width. Testing the width isn't the correct logic here I think. The width will only change when the physical size of the listbox changes, not when scrollbar is added/removed. But the client rect's .Right will change when scroll bar is added/removed or when the physical size of the listbox changes.

    Here's an idea for that problem. When the listbox is first assigned, set lWidth = client rect's .Right member. After list items are added, check the client rect again and if the .Right <> lWidth then cache new lWidth and reset the right tab. This should work well except for removing items or someone resizing the listbox during runtime. You have no way to know if items are being removed or not or if listbox is resized. You can fix the remove problem by creating a function like RemoveItem. Regarding the changing of the listbox size... just a matter of the user being aware that they need to call some function (not yet created) of your class that will validate the tabs, specifically the right tab. And not much you can do about center aligned items other than looping thru each & every listbox item to add/remove a couple of spaces - time consuming for very large lists.
    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

    Thread Starter
    Addicted Member *PsyKE1*'s Avatar
    Join Date
    Jun 2010
    Location
    Spain
    Posts
    243

    Re: [SRC] cListBoxMultiAlign [by Mr. Frog ©]

    Your search won't work for center/right aligned items. Try it. Result is always -1 (failure)
    Oops! True
    That's becouse the tabs and spaces... i can fix it...
    I did this funtion long ago: Check_SimilarWords
    I may be able to deploy in some way.


    Now for me is late, i'll follow tomorrow, thanks for the time!

  8. #8

    Thread Starter
    Addicted Member *PsyKE1*'s Avatar
    Join Date
    Jun 2010
    Location
    Spain
    Posts
    243

    Re: [SRC] cListBoxMultiAlign [by Mr. Frog ©]

    I got it! : D
    Using ClienRect!
    Please see the code again, I have updated and improved.
    Already corrected the problem with the ScrollBar.
    In the end decided not to add the function SearchSimilarItem.
    Try it when you can, I apologize for giving you a lot of work.
    Thanks! : P

  9. #9

    Thread Starter
    Addicted Member *PsyKE1*'s Avatar
    Join Date
    Jun 2010
    Location
    Spain
    Posts
    243

    Re: [SRC] cListBoxMultiAlign [by Mr. Frog ©]

    sorry for the double post, my webbrowser it's crazy... ¬¬

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