Hello !
Sorry this is going to be a very long post - but wanted to put as many info as possible.
I found on the net a way to add an horizontal scroll bar to a VB Listbox (works also for comboboxes).
This is were I found it :It uses API calls which I am not familiar with at all.
I have several listboxes in my form - I updated the code (or tried to !) to work with all of them.
Basically, I've put all the functions and declaration (made public) in a module.
In my form I have only the :
mAddScrollBar List1
mListBoxAdjustHScroll List1
The problem is, the scroll bar appears only in one Listbox - not on the others ?
I looked - all the declarations are constants (no variables), the control object seems to pass through alright ... So really I do not know what's wrong ...
If this help here is an example :
On the Form
Form_Load
mAddScrollBar lst1
mAddScrollBar lst2
mAddScrollBar lst3
mAddScrollBar lst4
End
On_some_event
Populate Lst1
Populate Lst2
Populate Lst3
Populate Lst4
mListBoxAdjustHScroll Lst1
mListBoxAdjustHScroll Lst2
mListBoxAdjustHScroll Lst3
mListBoxAdjustHScroll Lst4
End
In the Module (declaration at the end)
Public Sub mListBoxAdjustHScroll(ctlControl As Control)
'Purpose: Adjust the horizontal scroll extent of a ListBox to fit the largest item in the
'list
Dim lItemLen As Integer
Dim lItemMaxLen As Integer
Dim sItemText As String
Dim lResult As Long
Dim lLength As Long
Dim i As Integer
Select Case TypeName(ctlControl)
Case "ListBox", "ComboBox"
Case Else
MsgBox "mListBoxAdjustHScroll: Invalid argument value for ctlControl."
GoTo Exit_
End Select
'Find the longest item in the ListBox (by number of characters)
'Note: To be 100% accurate, we should compare the GetTextExtentPoint32 values of each
'string rather than the Length. Would this be much slower? For now, take the simple
'way out.
lItemMaxLen = 0
sItemText = ""
For i = 0 To ctlControl.ListCount - 1
Select Case TypeName(ctlControl)
Case "ListBox"
lResult = SendMessage(ctlControl.hwnd, LB_GETTEXTLEN, i, ByVal 0)
End Select
If (lResult = CB_ERR) Then
gErrHandlerAPI "mListBoxAdjustHScroll"
GoTo NextItem
End If
'If the current item is longer than the longest found so far...
If (lResult > lItemMaxLen) Then
'remember the size and string value of the current item
lItemMaxLen = lResult
sItemText = ctlControl.List(i)
End If
NextItem:
Next
'Determine the width of the longest string found, in the context of the Combo font
lLength = mlStringLenInControl(ctlControl, sItemText)
If (lLength = 0) Then GoTo Exit_
'Fudge factor
lLength = lLength + 4
'Set the horizontal scrollbar extent
Select Case TypeName(ctlControl)
Case "ListBox"
lResult = SendMessage(ctlControl.hwnd, LB_SETHORIZONTALEXTENT, lLength, ByVal 0)
End Select
Exit_:
Exit Sub
err:
gErrHandlerAPI "mListBoxAdjustHScroll"
End Sub
Public Function mlStringLenInControl(ctlControl As Control, ByVal vsString As String) As Long
'Purpose: Determine the length in pixels of a string in the device context of ctlControl
Dim hDC As Long
Dim lFont As Long
Dim lFontOld As Long
Dim uSize As SIZE
Dim lHeight As Long
Dim lResult As Long
mlStringLenInControl = 0
With ctlControl
'Get a handle to the device context for the control
hDC = GetDC(.hwnd)
If (hDC = API_NULL) Then GoTo ErrAPI
lFont = SendMessage(.hwnd, WM_GETFONT, 0, ByVal 0)
If (lFont = API_NULL) Then GoTo ErrAPI
End With
'Select the font in to the device context, and retain prior font
lFontOld = SelectObject(hDC, lFont)
If (lFontOld = 0) Or (lFontOld = GDI_ERROR) Then GoTo ErrAPI
'Determine the width of the string
lResult = GetTextExtentPoint32(hDC, vsString, Len(vsString), uSize)
If (lResult = 0) Then GoTo ErrAPI
'Return the string length
mlStringLenInControl = uSize.cx
Exit_:
'Reset the device context font and delete the temporary font. Ignore any errors.
SelectObject hDC, lFontOld
'Release the device context handle. Ignore any errors.
ReleaseDC ctlControl.hwnd, hDC
Exit Function
err:
MsgBox "mlStringLenInControl: " & err.Number & " - " & err.Description
On Error Resume Next
Resume Exit_
ErrAPI:
gErrHandlerAPI "mlStringLenInControl"
GoTo Exit_
'Resume
End Function
Public Sub gErrHandlerAPI(ByVal vsRoutine As String, Optional ByVal vlMessageId As Variant)
Dim sBuffer As String
Dim lReturn As Long
If IsMissing(vlMessageId) Then
vlMessageId = GetLastError()
End If
sBuffer = Space(255)
lReturn = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, 0, vlMessageId, 0, sBuffer, 255, 0)
If (lReturn > 0) Then
sBuffer = Left(sBuffer, lReturn - 1)
MsgBox "WinAPI (" & vsRoutine & "): " & sBuffer
Else
MsgBox "WinAPI (" & vsRoutine & "): " & vlMessageId & " - No description exists for this error number."
End If
End Sub
Public Sub mAddScrollBar(oControl As Control)
Dim lWindowStyle As Long
lWindowStyle = GetWindowLong(oControl.hwnd, GWL_STYLE)
If (lWindowStyle = 0) Then
gErrHandlerAPI "mAddScrollBar"
Exit Sub
End If
lWindowStyle = lWindowStyle Or WS_HSCROLL
SetLastError 0
lWindowStyle = SetWindowLong(oControl.hwnd, GWL_STYLE, lWindowStyle)
End Sub
Declaration in the module
Private Declare Function SendMessage Lib "user32" Alias "SendMessageA" (ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, lParam As Long) As Long
Public Const CB_SETDROPPEDWIDTH = &H160
Public Declare Function GetWindowLong Lib "user32" Alias "GetWindowLongA" ( _
ByVal hwnd As Long, ByVal nIndex As Long) As Long
Public Declare Function SetWindowLong Lib "user32" Alias "SetWindowLongA" ( _
ByVal hwnd As Long, ByVal nIndex As Long, ByVal dwNewLong As Long) As Long
Public Declare Function GetTextExtentPoint32 Lib "gdi32" _
Alias "GetTextExtentPoint32A" _
(ByVal hDC As Long, _
ByVal lpsz As String, _
ByVal cbString As Long, _
lpSize As SIZE) As Long
Public Declare Function GetStockObject Lib "gdi32" (ByVal nIndex As Long) As Long
Public Declare Function SelectObject Lib "gdi32" _
(ByVal hDC As Long, ByVal hObject As Long) As Long
Public Declare Function DeleteObject Lib "gdi32" (ByVal hObject As Long) As Long
Public Declare Function GetDC Lib "user32" (ByVal hwnd As Long) As Long
Public Declare Function ReleaseDC Lib "user32" (ByVal hwnd As Long, ByVal hDC As Long) As Long
Public Declare Function GetDeviceCaps Lib "gdi32" (ByVal hDC As Long _
, ByVal nIndex As Long) As Long
Public Declare Sub SetLastError Lib "kernel32" (ByVal dwErrCode As Long)
Public Declare Function GetLastError Lib "kernel32" () As Long
Public Const FORMAT_MESSAGE_FROM_SYSTEM = &H1000
Public Declare Function FormatMessage Lib "kernel32" Alias "FormatMessageA" (ByVal dwFlags As Long, lpSource As Any, ByVal dwMessageId As Long, ByVal dwLanguageId As Long, ByVal lpBuffer As String, ByVal nSize As Long, Arguments As Long) As Long
Public Declare Function GetTickCount Lib "kernel32" () As Long
Public Const GWL_STYLE = (-16)
Public Const WS_HSCROLL = &H100000
Public Type SIZE
cx As Long
cy As Long
End Type
Public Const ANSI_FIXED_FONT = 11
Public Const ANSI_VAR_FONT = 12
Public Const SYSTEM_FONT = 13
Public Const DEFAULT_GUI_FONT = 17
Public Const GDI_ERROR = &HFFFF
Public Const FW_BOLD = 700
Public Const FW_NORMAL = 400
Public Const DEFAULT_CHARSET = 1
Public Const OUT_DEFAULT_PRECIS = 0
Public Const CLIP_DEFAULT_PRECIS = 0
Public Const DEFAULT_QUALITY = 0
Public Const DEFAULT_PITCH = 0
Public Const FF_DONTCARE = 0
Private Const API_NULL As Long = 0
Private Const WM_GETFONT = &H31
Private Const CB_GETLBTEXT = &H148
Private Const CB_GETLBTEXTLEN = &H149
'Private Const CB_SHOWDROPDOWN = &H14F
Private Const CB_SETHORIZONTALEXTENT = &H15E
Private Const LB_ERR = -1
Private Const LB_GETTEXT = &H189
Private Const LB_GETTEXTLEN = &H18A
Private Const LB_ITEMFROMPOINT = &H1A9
'Private Const LB_GETHORIZONTALEXTENT = &H193
Private Const LB_SETHORIZONTALEXTENT = &H194
Sorry this is going to be a very long post - but wanted to put as many info as possible.
I found on the net a way to add an horizontal scroll bar to a VB Listbox (works also for comboboxes).
This is were I found it :It uses API calls which I am not familiar with at all.
I have several listboxes in my form - I updated the code (or tried to !) to work with all of them.
Basically, I've put all the functions and declaration (made public) in a module.
In my form I have only the :
mAddScrollBar List1
mListBoxAdjustHScroll List1
The problem is, the scroll bar appears only in one Listbox - not on the others ?
I looked - all the declarations are constants (no variables), the control object seems to pass through alright ... So really I do not know what's wrong ...
If this help here is an example :
On the Form
Form_Load
mAddScrollBar lst1
mAddScrollBar lst2
mAddScrollBar lst3
mAddScrollBar lst4
End
On_some_event
Populate Lst1
Populate Lst2
Populate Lst3
Populate Lst4
mListBoxAdjustHScroll Lst1
mListBoxAdjustHScroll Lst2
mListBoxAdjustHScroll Lst3
mListBoxAdjustHScroll Lst4
End
In the Module (declaration at the end)
Public Sub mListBoxAdjustHScroll(ctlControl As Control)
'Purpose: Adjust the horizontal scroll extent of a ListBox to fit the largest item in the
'list
Dim lItemLen As Integer
Dim lItemMaxLen As Integer
Dim sItemText As String
Dim lResult As Long
Dim lLength As Long
Dim i As Integer
Select Case TypeName(ctlControl)
Case "ListBox", "ComboBox"
Case Else
MsgBox "mListBoxAdjustHScroll: Invalid argument value for ctlControl."
GoTo Exit_
End Select
'Find the longest item in the ListBox (by number of characters)
'Note: To be 100% accurate, we should compare the GetTextExtentPoint32 values of each
'string rather than the Length. Would this be much slower? For now, take the simple
'way out.
lItemMaxLen = 0
sItemText = ""
For i = 0 To ctlControl.ListCount - 1
Select Case TypeName(ctlControl)
Case "ListBox"
lResult = SendMessage(ctlControl.hwnd, LB_GETTEXTLEN, i, ByVal 0)
End Select
If (lResult = CB_ERR) Then
gErrHandlerAPI "mListBoxAdjustHScroll"
GoTo NextItem
End If
'If the current item is longer than the longest found so far...
If (lResult > lItemMaxLen) Then
'remember the size and string value of the current item
lItemMaxLen = lResult
sItemText = ctlControl.List(i)
End If
NextItem:
Next
'Determine the width of the longest string found, in the context of the Combo font
lLength = mlStringLenInControl(ctlControl, sItemText)
If (lLength = 0) Then GoTo Exit_
'Fudge factor
lLength = lLength + 4
'Set the horizontal scrollbar extent
Select Case TypeName(ctlControl)
Case "ListBox"
lResult = SendMessage(ctlControl.hwnd, LB_SETHORIZONTALEXTENT, lLength, ByVal 0)
End Select
Exit_:
Exit Sub
err:
gErrHandlerAPI "mListBoxAdjustHScroll"
End Sub
Public Function mlStringLenInControl(ctlControl As Control, ByVal vsString As String) As Long
'Purpose: Determine the length in pixels of a string in the device context of ctlControl
Dim hDC As Long
Dim lFont As Long
Dim lFontOld As Long
Dim uSize As SIZE
Dim lHeight As Long
Dim lResult As Long
mlStringLenInControl = 0
With ctlControl
'Get a handle to the device context for the control
hDC = GetDC(.hwnd)
If (hDC = API_NULL) Then GoTo ErrAPI
lFont = SendMessage(.hwnd, WM_GETFONT, 0, ByVal 0)
If (lFont = API_NULL) Then GoTo ErrAPI
End With
'Select the font in to the device context, and retain prior font
lFontOld = SelectObject(hDC, lFont)
If (lFontOld = 0) Or (lFontOld = GDI_ERROR) Then GoTo ErrAPI
'Determine the width of the string
lResult = GetTextExtentPoint32(hDC, vsString, Len(vsString), uSize)
If (lResult = 0) Then GoTo ErrAPI
'Return the string length
mlStringLenInControl = uSize.cx
Exit_:
'Reset the device context font and delete the temporary font. Ignore any errors.
SelectObject hDC, lFontOld
'Release the device context handle. Ignore any errors.
ReleaseDC ctlControl.hwnd, hDC
Exit Function
err:
MsgBox "mlStringLenInControl: " & err.Number & " - " & err.Description
On Error Resume Next
Resume Exit_
ErrAPI:
gErrHandlerAPI "mlStringLenInControl"
GoTo Exit_
'Resume
End Function
Public Sub gErrHandlerAPI(ByVal vsRoutine As String, Optional ByVal vlMessageId As Variant)
Dim sBuffer As String
Dim lReturn As Long
If IsMissing(vlMessageId) Then
vlMessageId = GetLastError()
End If
sBuffer = Space(255)
lReturn = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, 0, vlMessageId, 0, sBuffer, 255, 0)
If (lReturn > 0) Then
sBuffer = Left(sBuffer, lReturn - 1)
MsgBox "WinAPI (" & vsRoutine & "): " & sBuffer
Else
MsgBox "WinAPI (" & vsRoutine & "): " & vlMessageId & " - No description exists for this error number."
End If
End Sub
Public Sub mAddScrollBar(oControl As Control)
Dim lWindowStyle As Long
lWindowStyle = GetWindowLong(oControl.hwnd, GWL_STYLE)
If (lWindowStyle = 0) Then
gErrHandlerAPI "mAddScrollBar"
Exit Sub
End If
lWindowStyle = lWindowStyle Or WS_HSCROLL
SetLastError 0
lWindowStyle = SetWindowLong(oControl.hwnd, GWL_STYLE, lWindowStyle)
End Sub
Declaration in the module
Private Declare Function SendMessage Lib "user32" Alias "SendMessageA" (ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, lParam As Long) As Long
Public Const CB_SETDROPPEDWIDTH = &H160
Public Declare Function GetWindowLong Lib "user32" Alias "GetWindowLongA" ( _
ByVal hwnd As Long, ByVal nIndex As Long) As Long
Public Declare Function SetWindowLong Lib "user32" Alias "SetWindowLongA" ( _
ByVal hwnd As Long, ByVal nIndex As Long, ByVal dwNewLong As Long) As Long
Public Declare Function GetTextExtentPoint32 Lib "gdi32" _
Alias "GetTextExtentPoint32A" _
(ByVal hDC As Long, _
ByVal lpsz As String, _
ByVal cbString As Long, _
lpSize As SIZE) As Long
Public Declare Function GetStockObject Lib "gdi32" (ByVal nIndex As Long) As Long
Public Declare Function SelectObject Lib "gdi32" _
(ByVal hDC As Long, ByVal hObject As Long) As Long
Public Declare Function DeleteObject Lib "gdi32" (ByVal hObject As Long) As Long
Public Declare Function GetDC Lib "user32" (ByVal hwnd As Long) As Long
Public Declare Function ReleaseDC Lib "user32" (ByVal hwnd As Long, ByVal hDC As Long) As Long
Public Declare Function GetDeviceCaps Lib "gdi32" (ByVal hDC As Long _
, ByVal nIndex As Long) As Long
Public Declare Sub SetLastError Lib "kernel32" (ByVal dwErrCode As Long)
Public Declare Function GetLastError Lib "kernel32" () As Long
Public Const FORMAT_MESSAGE_FROM_SYSTEM = &H1000
Public Declare Function FormatMessage Lib "kernel32" Alias "FormatMessageA" (ByVal dwFlags As Long, lpSource As Any, ByVal dwMessageId As Long, ByVal dwLanguageId As Long, ByVal lpBuffer As String, ByVal nSize As Long, Arguments As Long) As Long
Public Declare Function GetTickCount Lib "kernel32" () As Long
Public Const GWL_STYLE = (-16)
Public Const WS_HSCROLL = &H100000
Public Type SIZE
cx As Long
cy As Long
End Type
Public Const ANSI_FIXED_FONT = 11
Public Const ANSI_VAR_FONT = 12
Public Const SYSTEM_FONT = 13
Public Const DEFAULT_GUI_FONT = 17
Public Const GDI_ERROR = &HFFFF
Public Const FW_BOLD = 700
Public Const FW_NORMAL = 400
Public Const DEFAULT_CHARSET = 1
Public Const OUT_DEFAULT_PRECIS = 0
Public Const CLIP_DEFAULT_PRECIS = 0
Public Const DEFAULT_QUALITY = 0
Public Const DEFAULT_PITCH = 0
Public Const FF_DONTCARE = 0
Private Const API_NULL As Long = 0
Private Const WM_GETFONT = &H31
Private Const CB_GETLBTEXT = &H148
Private Const CB_GETLBTEXTLEN = &H149
'Private Const CB_SHOWDROPDOWN = &H14F
Private Const CB_SETHORIZONTALEXTENT = &H15E
Private Const LB_ERR = -1
Private Const LB_GETTEXT = &H189
Private Const LB_GETTEXTLEN = &H18A
Private Const LB_ITEMFROMPOINT = &H1A9
'Private Const LB_GETHORIZONTALEXTENT = &H193
Private Const LB_SETHORIZONTALEXTENT = &H194