AutoHotkey Homepage AutoHotkey Community
Let's help each other out
 
 FAQFAQ   SearchSearch   MemberlistMemberlist   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

How to properly add a horizontal scrollbar to a listbox

 
Reply to topic    AutoHotkey Community Forum Index -> Scripts & Functions
View previous topic :: View next topic  
Author Message
TheGood



Joined: 30 Jul 2007
Posts: 516

PostPosted: Sun Dec 21, 2008 8:06 pm    Post subject: How to properly add a horizontal scrollbar to a listbox Reply with quote

While I was working on a project (which I'll hopefully also post here when I'm done), I found myself needing an horizontal scrollbar for my listboxes, because of very long items. No problem I thought. I'll simply use the GuiControl +HScroll command. The only problem is that the only way to use this command is to specify how many pixels you want the scrollbar to scroll. That's not practical because the longest item in the listbox might be less or more than the specified scrolling limit.

So then I made some research, and found this, straight from Microsoft. It tells you in details how to add a horizontal scrollbar to the listbox sensitive to items' width. All I did was adapt the steps from the article to AutoHotkey with the help of this topic and that one (thanks to Sean, majkinetor and dncarac).

And this is what you get: a function that adds an horizontal scrollbar to your listbox, which will scroll only up to what you need, that is, up to the longest item (and also taking into consideration the font used in the listbox).

How to use/add to your code
All you need from the code below is the ListBoxAdjustHSB function and the GetListBoxItem function. I only added a GUI as an example. Everytime an item is added/removed from the listbox, call the ListBoxAdjustHSB function to adjust the scrollbar extent (or remove it if not needed). Make sure you have the +HScroll option when adding your listbox, otherwise it won't work.

Code:

Gui, Add, ListBox, h100 hwndhLB +HScroll, This is a short list box item.|This is a very very very very very very very very very very very very very very long list box item.
Gui, Show

;Add Horizontal Bar
ListBoxAdjustHSB(hLB)

Return

GuiClose:
ExitApp
Return

ListBoxAdjustHSB(hLB) {
   
   ;Declare variables (for clarity's sake)
   dwExtent := 0
   dwMaxExtent := 0
   hDCListBox := 0
   hFontOld := 0
   hFontNew := 0
   VarSetCapacity(lptm, 53)
   
   ;Use GetDC to retrieve handle to the display context for the list box and store it in hDCListBox
   hDCListBox := DllCall("GetDC", "Uint", hLB)

   ;Send the list box a WM_GETFONT message to retrieve the handle to the font that the list box is using, and store this handle in hFontNew
   SendMessage 49, 0, 0,, ahk_id %hLB%
   hFontNew := ErrorLevel

   ;Use SelectObject to select the font into the display context. Retain the return value from the SelectObject call in hFontOld
   hFontOld := DllCall("SelectObject", "Uint", hDCListBox, "Uint", hFontNew)

   ;Call GetTextMetrics to get additional information about the font being used (eg. to get tmAveCharWidth's value)
   DllCall("GetTextMetrics", "Uint", hDCListBox, "Uint", &lptm)
   tmAveCharWidth := NumGet(lptm, 20)

   ;Get item count using LB_GETCOUNT
   SendMessage 395, 0, 0,, ahk_id %hLB%

   ;Loop through the items
   Loop %ErrorLevel% {

      ;Get list box item text
      s := GetListBoxItem(hLB, A_Index - 1)

      ;For each string, the value of the extent to be used is calculated as follows:
      DllCall("GetTextExtentPoint32", "Uint", hDCListBox, "str", s, "int", StrLen(s), "int64P", nSize)
      dwExtent := (nSize & 0xFFFFFFFF) + tmAveCharWidth

      ;Keep if it's the highest to date
      If (dwExtent > dwMaxExtent)
         dwMaxExtent := dwExtent
      
   }
   
   ;After all the extents have been calculated, select the old font back into hDCListBox and then release it:
   DllCall("SelectObject", "Uint", hDCListBox, "Uint", hFontOld)
   DllCall("ReleaseDC", "Uint", hLB, "Uint", hDCListBox)
   
   ;Adjust the horizontal bar using LB_SETHORIZONTALEXTENT
   SendMessage 404, dwMaxExtent, 0,, ahk_id %hLB%

}

GetListBoxItem(hLB, i) {
      
   ;Get length of item. 394 = LB_GETTEXTLEN
   SendMessage 394, %i%, 0,, ahk_id %hLB%
   
   ;Check for error
   If (ErrorLevel = 0xFFFFFFFF)
      Return ""
   
   ;Prepare variable
   VarSetCapacity(sText, ErrorLevel, 0)
   
   ;Retrieve item. 393 = LB_GETTEXT
   SendMessage 393, %i%, &sText,, ahk_id %hLB%
   
   ;Check for error
   If (ErrorLevel = 0xFFFFFFFF)
      Return ""
   
   ;Done
   Return sText

}



Let me know if you find bugs or see places where I could improve.
Enjoy!
Back to top
View user's profile Send private message Visit poster's website
Joy2DWorld



Joined: 04 Dec 2006
Posts: 552
Location: Galil, Israel

PostPosted: Mon Dec 22, 2008 3:38 am    Post subject: Reply with quote

You've done an incredibly clear job of explaining & documenting your function. FANTASTIC!
_________________
Joyce Jamce
Back to top
View user's profile Send private message
jballi



Joined: 01 Oct 2005
Posts: 582
Location: Texas, USA

PostPosted: Mon Dec 22, 2008 8:47 am    Post subject: Reply with quote

This looks useful. I just need to remember that it's available the next time I create a ListBox that needs a horizontal scroll bar. Thanks for sharing. Smile
Back to top
View user's profile Send private message Send e-mail
TheGood



Joined: 30 Jul 2007
Posts: 516

PostPosted: Mon Dec 22, 2008 5:28 pm    Post subject: Reply with quote

I'm glad you guys like it Very Happy
I'll see if I can put it in Jon's stickied wiki. lol I wonder if "stickied" is even a word.
Back to top
View user's profile Send private message Visit poster's website
Display posts from previous:   
Reply to topic    AutoHotkey Community Forum Index -> Scripts & Functions All times are GMT
Page 1 of 1

 
Jump to:  
You can post new topics in this forum
You can reply to topics in this forum


Powered by phpBB © 2001, 2005 phpBB Group