October 31, 2025, 04:57:40 AM

News:

Own IWBasic 2.x ? -----> Get your free upgrade to 3.x now.........


ComboBox with horizontal scrollbar

Started by Ficko, December 18, 2009, 01:50:57 PM

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

Ficko

December 18, 2009, 01:50:57 PM Last Edit: December 18, 2009, 01:57:48 PM by Ficko
I am working on this beast but somehow can't get the scrolling proportions right.

I am very bad in math. ;D
May someone has an Idea? ::)


AUTODEFINE "OFF"
' ===============================================================================================
DECLARE IMPORT,SetWindowLongA(hWnd:INT,nIndex:INT,dwNewLong:INT),INT
DECLARE IMPORT,SetScrollInfo(HWND:INT,fnBar:INT,lpsi:_LPSCROLLINFO,fRedraw:INT),UINT
DECLARE IMPORT,GetComboBoxInfo(HWND:INT,PCOMBOBOXINFO:_COMBOBOXINFO),INT
DECLARE IMPORT,CallWindowProcA(lpPrevWndFunc:INT,hWnd:INT,Msg:INT,wParam:INT,lParam:INT),INT
' ===============================================================================================
TYPE _COMBOBOXINFO
 DEF cbSize:UINT
 DEF rcItem:WINRECT
 DEF rcButton:WINRECT
 DEF stateButton:UINT
 DEF hwndCombo:INT
 DEF hwndItem:INT
 DEF hwndList:INT
ENDTYPE
TYPE _SCROLLINFO
 DEF cbSize:UINT
 DEF fMask:UINT
 DEF nMin:INT
 DEF nMax:INT
 DEF nPage:INT
 DEF nPos:INT
 DEF nTrackPos:INT
ENDTYPE
' ===============================================================================================
CONST COMBO = 1
CONST CB_SHOWDROPDOWN   = 0x14F
CONST CB_SETHORIZONTALEXTENT = 0x15E
CONST SB_HORZ = 0
CONST SB_LINELEFT       = 0
CONST SB_LINERIGHT       = 1
CONST SB_PAGELEFT       = 2
CONST SB_PAGERIGHT       = 3
CONST SB_THUMBPOSITION   = 4
CONST SIF_RANGE     = 1
CONST SIF_PAGE       = 2
CONST SIF_POS       = 4
CONST GWL_WNDPROC = -4
CONST WM_HSCROLL = 0x114
CONST WM_LBUTTONDOWN     = 0x201
CONST CB_OX = 40
CONST CB_OY = 30
CONST CB_XW = 175
CONST CB_YW = 350
' ===============================================================================================
DEF MainD :DIALOG
DEF COMBOBOXINFO_LF :_COMBOBOXINFO
DEF SCROLLINFO :_SCROLLINFO
DEF OrigCBLB_LF,OrigComb_LF,ScrollPos,MaxPix :INT
' ===============================================================================================
CREATEDIALOG MainD,0,0,300,409,0x80C80080,0,"Caption",&MainD_handler
CONTROL MainD,@COMBOBOX,"",CB_OX,CB_OY,CB_OX + CB_XW,CB_OY + CB_YW,@CTCOMBODROPDOWN|@VSCROLL|@CTCOMBOAUTOHSCROLL|@CTCOMBOSORT,COMBO
DOMODAL MainD
END

' =================================== D I A L O G  P R O C ======================================
SUB MainD_handler
DEF A,MaxL,vWidth,vHeight :INT
DEF Item :STRING
' -----------------------------------------------------------------------------------------------
MaxL = 0
SELECT @MESSAGE
CASE @IDINITDIALOG
CENTERWINDOW MainD
FOR A = 0 TO 40 'Fill the combo
ADDSTRING(MainD,COMBO,USING("0#####",A) + " " + STRING$(RAND(150),"*") + "!")
NEXT A
FOR A = 0 TO 40 'Get the longest item
Item = GETSTRING(mainD,COMBO,A)
IF (LEN(Item) > MaxL) THEN
MaxL = LEN(Item)
GETTEXTSIZE(MainD,Item,vWidth,vHeight)
MaxPix = vWidth
ENDIF
NEXT A
SETHORIZEXTENT(MainD,COMBO,MaxPix) 'The listbox seems to be too width (why ?????)
COMBOBOXINFO_LF.cbSize = LEN(COMBOBOXINFO_LF)
SCROLLINFO.cbSize = LEN(SCROLLINFO)
SCROLLINFO.fMask = SIF_RANGE|SIF_PAGE
SCROLLINFO.nMax = MaxPix
SCROLLINFO.nPage = (MaxPix/100f)*10 '(Trying 10%)What is the exact relationship between nMax and nPage ????
IF (GetComboBoxInfo(GETCONTROLHANDLE(MainD,COMBO),COMBOBOXINFO_LF)) THEN
OrigCBLB_LF = SetWindowLongA(COMBOBOXINFO_LF.hwndList,GWL_WNDPROC,&CB_LF_LBHandler)
OrigComb_LF = SetWindowLongA(COMBOBOXINFO_LF.hwndCombo,GWL_WNDPROC,&CB_LF_Handler)
SetScrollInfo(COMBOBOXINFO_LF.hwndList,SB_HORZ,SCROLLINFO,FALSE)
ENDIF
CASE @IDCLOSEWINDOW
CLOSEDIALOG MainD
CASE @IDCONTROL
SELECT @CONTROLID
CASE COMBO
/* respond to control notifications here */
ENDSELECT
ENDSELECT
ENDSUB

' ================================== S U B R O U T I N E =========================================
SUB CB_LF_LBHandler(hwnd:int,uMsg:int,wParam:UINT,lParam:pointer),int
DEF LOWWORD :WORD
' ------------------------------------------------------------------------------------------------
LOWWORD = wParam
IF uMsg = WM_HSCROLL THEN
SELECT LOWWORD
CASE SB_PAGERIGHT
ScrollPos += (MaxPix/100f)*10 'Trying to move with page width dosn't seem right ???
CASE SB_PAGELEFT
ScrollPos -= (MaxPix/100f)*10
CASE SB_LINELEFT
ScrollPos -= 1 'Scrolling isn't proportional ??????
IF ScrollPos < 0 THEN ScrollPos = 0
CASE SB_LINERIGHT
ScrollPos += 1
IF (ScrollPos > MaxPix) THEN ScrollPos = MaxPix
CASE SB_THUMBPOSITION
ScrollPos = wParam >> 16
ENDSELECT
SCROLLINFO.fMask = SIF_POS
SCROLLINFO.nPos = ScrollPos
SetScrollInfo(COMBOBOXINFO_LF.hwndList,SB_HORZ,SCROLLINFO,TRUE)
ENDIF
RETURN CallWindowProcA(OrigCBLB_LF,hwnd,uMsg,wParam,lParam)
ENDSUB

' ================================== S U B R O U T I N E =========================================
SUB CB_LF_Handler(hwnd:int,uMsg:int,wParam:UINT,lParam:pointer),int
IF uMsg = WM_LBUTTONDOWN THEN
SENDMESSAGE MainD,CB_SHOWDROPDOWN,TRUE,0,COMBO
RETURN TRUE
ENDIF
RETURN CallWindowProcA(OrigComb_LF,hwnd,uMsg,wParam,lParam)
ENDSUB




fasecero

Hi, Ficko. Try with: 

       SCROLLINFO.nPage = 100 * ( SCROLLINFO.nMax / combo_width )


Ficko

Thanks for the reply. :D

Yes I know it can be "made" to look good but I am looking for the "magic" formel(s) to make a custom control class. ;D

If you push the little right arrow and hold it you can move way beyond the longest string shifting it totally out of view, which indicate to me that the width of the listbox is almost twice as should be.

So "SETHORIZEXTENT" needs a different size - I think - but what size?

I want the size of the longest item. So that the last "!" is touching the right border.
Than I need an explanation to the relation ship between "nPage" and "nMax" - or an other "magic" formel  :D - so my class can work with any size of combo with any size of item lenght.

I know that a lots to ask for but I am sure a lot of people can benefit from it if we can figure it out. ;D



fasecero

Hello again. Now I understand, you want that the longest item fill exactly the combo space.
Here's a possible solution changing two things:

* I dismiss to set SCROLLINFO.nPage, and I send SetScrollInfo only with SIF_RANGE, so I don't know if is the solution you want.
* the font of the combo may be different to the font of the window, so I use GetTextExtentPoint32 in a memory DC with the combo font instead of GETTEXTSIZE.


AUTODEFINE "OFF"
' ===============================================================================================
DECLARE IMPORT,SetWindowLongA(hWnd:INT,nIndex:INT,dwNewLong:INT),INT
DECLARE IMPORT,SetScrollInfo(HWND:INT,fnBar:INT,lpsi:_LPSCROLLINFO,fRedraw:INT),UINT
DECLARE IMPORT,GetComboBoxInfo(HWND:INT,PCOMBOBOXINFO:_COMBOBOXINFO),INT
DECLARE IMPORT,CallWindowProcA(lpPrevWndFunc:INT,hWnd:INT,Msg:INT,wParam:INT,lParam:INT),INT
DECLARE IMPORT, _CreateCompatibleDC ALIAS CreateCompatibleDC(hdc AS INT),INT
DECLARE IMPORT, _DeleteDC ALIAS DeleteDC(hdc AS INT),INT
DECLARE IMPORT, _SelectObject ALIAS SelectObject(hdc AS INT,hObject AS INT),INT
DECLARE IMPORT, _GetTextExtentPoint32 ALIAS GetTextExtentPoint32A(hdc AS INT,lpsz AS STRING,cbString AS INT,lpSize AS SIZE),INT
DECLARE IMPORT, _GetSystemMetrics ALIAS GetSystemMetrics(nIndex AS INT),INT
' ===============================================================================================
TYPE _COMBOBOXINFO
  DEF cbSize:UINT
  DEF rcItem:WINRECT
  DEF rcButton:WINRECT
  DEF stateButton:UINT
  DEF hwndCombo:INT
  DEF hwndItem:INT
  DEF hwndList:INT
ENDTYPE
TYPE _SCROLLINFO
  DEF cbSize:UINT
  DEF fMask:UINT
  DEF nMin:INT
  DEF nMax:INT
  DEF nPage:INT
  DEF nPos:INT
  DEF nTrackPos:INT
ENDTYPE
TYPE Size
DEF cx AS INT
DEF cy AS INT
ENDTYPE
' ===============================================================================================
CONST SM_CXEDGE = 45
CONST WM_GETFONT = 0x31
CONST COMBO = 1
CONST CB_SHOWDROPDOWN    = 0x14F
CONST CB_SETHORIZONTALEXTENT = 0x15E
CONST SB_HORZ = 0
CONST SB_LINELEFT        = 0
CONST SB_LINERIGHT      = 1
CONST SB_PAGELEFT        = 2
CONST SB_PAGERIGHT      = 3
CONST SB_THUMBPOSITION  = 4
CONST SIF_RANGE      = 1
CONST SIF_PAGE      = 2
CONST SIF_POS        = 4
CONST GWL_WNDPROC = -4
CONST WM_HSCROLL = 0x114
CONST WM_LBUTTONDOWN    = 0x201
CONST CB_OX = 40
CONST CB_OY = 30
CONST CB_XW = 200
CONST CB_YW = 350
' ===============================================================================================
DEF MainD :DIALOG
DEF COMBOBOXINFO_LF :_COMBOBOXINFO
DEF SCROLLINFO :_SCROLLINFO
DEF OrigCBLB_LF,OrigComb_LF,ScrollPos,MaxPix :INT
' ===============================================================================================
CREATEDIALOG MainD,0,0,300,409,0x80C80080,0,"Caption",&MainD_handler
CONTROL MainD,@COMBOBOX,"",CB_OX,CB_OY,CB_OX + CB_XW,CB_OY + CB_YW,@CTCOMBODROPDOWN|@VSCROLL|@CTCOMBOAUTOHSCROLL|@CTCOMBOSORT,COMBO
DOMODAL MainD
END

' =================================== D I A L O G  P R O C ======================================
SUB MainD_handler
DEF A,MaxL,vWidth,vHeight :INT
DEF Item :STRING
' -----------------------------------------------------------------------------------------------
MaxL = 0
SELECT @MESSAGE
CASE @IDINITDIALOG
CENTERWINDOW MainD
FOR A = 0 TO 40 'Fill the combo
ADDSTRING(MainD,COMBO,USING("0#####",A) + " " + STRING$(RAND(150),"*") + "!")
NEXT A

int hdc, hfontold

Measurement_Init(hdc, hfontold)

FOR A = 0 TO 40 'Get the longest item
Item = GETSTRING(mainD,COMBO,A)
IF (LEN(Item) > MaxL) THEN
MaxL = LEN(Item)

'GETTEXTSIZE(MainD,Item,vWidth,vHeight)
vWidth = MeasureStringX(hdc, Item)

MaxPix = vWidth
ENDIF
NEXT A

Measurement_Finish(hdc, hfontold)

SETHORIZEXTENT(MainD,COMBO,MaxPix) 'The listbox seems to be too width (why ?????)
COMBOBOXINFO_LF.cbSize = LEN(COMBOBOXINFO_LF)
SCROLLINFO.cbSize = LEN(SCROLLINFO)
SCROLLINFO.fMask = SIF_RANGE
SCROLLINFO.nMax = MaxPix

IF (GetComboBoxInfo(GETCONTROLHANDLE(MainD,COMBO),COMBOBOXINFO_LF)) THEN
OrigCBLB_LF = SetWindowLongA(COMBOBOXINFO_LF.hwndList,GWL_WNDPROC,&CB_LF_LBHandler)
OrigComb_LF = SetWindowLongA(COMBOBOXINFO_LF.hwndCombo,GWL_WNDPROC,&CB_LF_Handler)
SetScrollInfo(COMBOBOXINFO_LF.hwndList,SB_HORZ,SCROLLINFO,FALSE)
ENDIF
CASE @IDCLOSEWINDOW
CLOSEDIALOG MainD
CASE @IDCONTROL
SELECT @CONTROLID
CASE COMBO
/* respond to control notifications here */
ENDSELECT
ENDSELECT
ENDSUB

' ================================== S U B R O U T I N E =========================================
SUB CB_LF_LBHandler(hwnd:int,uMsg:int,wParam:UINT,lParam:pointer),int
DEF LOWWORD :WORD
' ------------------------------------------------------------------------------------------------
LOWWORD = wParam
IF uMsg = WM_HSCROLL THEN
SELECT LOWWORD
CASE SB_PAGERIGHT
ScrollPos += (MaxPix/100f)*10 'Trying to move with page width dosn't seem right ???
CASE SB_PAGELEFT
ScrollPos -= (MaxPix/100f)*10
CASE SB_LINELEFT
ScrollPos -= 1 'Scrolling isn't proportional ??????
IF ScrollPos < 0 THEN ScrollPos = 0
CASE SB_LINERIGHT
ScrollPos += 1
IF (ScrollPos > MaxPix) THEN ScrollPos = MaxPix
CASE SB_THUMBPOSITION
ScrollPos = wParam >> 16
ENDSELECT
SCROLLINFO.fMask = SIF_POS
SCROLLINFO.nPos = ScrollPos
SetScrollInfo(COMBOBOXINFO_LF.hwndList,SB_HORZ,SCROLLINFO,TRUE)
ENDIF
RETURN CallWindowProcA(OrigCBLB_LF,hwnd,uMsg,wParam,lParam)
ENDSUB

' ================================== S U B R O U T I N E =========================================
SUB CB_LF_Handler(hwnd:int,uMsg:int,wParam:UINT,lParam:pointer),int
IF uMsg = WM_LBUTTONDOWN THEN
SENDMESSAGE MainD,CB_SHOWDROPDOWN,TRUE,0,COMBO
RETURN TRUE
ENDIF
RETURN CallWindowProcA(OrigComb_LF,hwnd,uMsg,wParam,lParam)
ENDSUB


SUB Measurement_Init(int hdc BYREF, INT hfont BYREF)
hdc = _CreateCompatibleDC(0)
hfont = SENDMESSAGE( GETCONTROLHANDLE(MainD,COMBO), WM_GETFONT, 0, 0)
hfont = _SelectObject(hdc, hfont)
ENDSUB

SUB MeasureStringX(int hdc, STRING text), INT
SIZE sz

_GetTextExtentPoint32(hdc, text, LEN(text), sz)
RETURN sz.cx + 2*_GetSystemMetrics(SM_CXEDGE)
ENDSUB

SUB Measurement_Finish(int hdc, INT hfontold)
_SelectObject(hdc, hfontold)
_DeleteDC(hdc)
ENDSUB



I did a few tests changing the width of the combo and seems to work fine (at least in my system :) )


fasecero

December 19, 2009, 05:11:35 PM #4 Last Edit: December 19, 2009, 05:17:22 PM by fasecero
One last attempt, better than the last, using SCROLLINFO.nPage.
It appears that regardless of the value of SCROLLINFO.nMax, the SCROLLINFO.nPage value must equal the width of the combo (obtained with GETSIZE(...) ).


AUTODEFINE "OFF"
' ===============================================================================================
DECLARE IMPORT,SetWindowLongA(hWnd:INT,nIndex:INT,dwNewLong:INT),INT
DECLARE IMPORT,SetScrollInfo(HWND:INT,fnBar:INT,lpsi:_LPSCROLLINFO,fRedraw:INT),UINT
DECLARE IMPORT,GetScrollInfo(HWND:INT,fnBar:INT,lpsi:_LPSCROLLINFO),UINT
DECLARE IMPORT,GetComboBoxInfo(HWND:INT,PCOMBOBOXINFO:_COMBOBOXINFO),INT
DECLARE IMPORT,CallWindowProcA(lpPrevWndFunc:INT,hWnd:INT,Msg:INT,wParam:INT,lParam:INT),INT
DECLARE IMPORT, _CreateCompatibleDC ALIAS CreateCompatibleDC(hdc AS INT),INT
DECLARE IMPORT, _DeleteDC ALIAS DeleteDC(hdc AS INT),INT
DECLARE IMPORT, _SelectObject ALIAS SelectObject(hdc AS INT,hObject AS INT),INT
DECLARE IMPORT, _GetTextExtentPoint32 ALIAS GetTextExtentPoint32A(hdc AS INT,lpsz AS STRING,cbString AS INT,lpSize AS SIZE),INT
DECLARE IMPORT, _GetSystemMetrics ALIAS GetSystemMetrics(nIndex AS INT),INT
' ===============================================================================================
TYPE _COMBOBOXINFO
 DEF cbSize:UINT
 DEF rcItem:WINRECT
 DEF rcButton:WINRECT
 DEF stateButton:UINT
 DEF hwndCombo:INT
 DEF hwndItem:INT
 DEF hwndList:INT
ENDTYPE
TYPE _SCROLLINFO
 DEF cbSize:UINT
 DEF fMask:UINT
 DEF nMin:INT
 DEF nMax:INT
 DEF nPage:INT
 DEF nPos:INT
 DEF nTrackPos:INT
ENDTYPE
TYPE Size
DEF cx AS INT
DEF cy AS INT
ENDTYPE
' ===============================================================================================
CONST SM_CXVSCROLL = 2
CONST SM_CXEDGE = 45
CONST WM_GETFONT = 0x31
CONST COMBO = 1
CONST CB_SHOWDROPDOWN   = 0x14F
CONST CB_SETHORIZONTALEXTENT = 0x15E
CONST SB_HORZ = 0
CONST SB_LINELEFT       = 0
CONST SB_LINERIGHT       = 1
CONST SB_PAGELEFT       = 2
CONST SB_PAGERIGHT       = 3
CONST SB_THUMBPOSITION   = 4
CONST SIF_RANGE     = 1
CONST SIF_PAGE       = 2
CONST SIF_POS       = 4
CONST GWL_WNDPROC = -4
CONST WM_HSCROLL = 0x114
CONST WM_LBUTTONDOWN     = 0x201
CONST CB_OX = 40
CONST CB_OY = 30
CONST CB_XW = 175
CONST CB_YW = 350
' ===============================================================================================
DEF MainD :DIALOG
DEF COMBOBOXINFO_LF :_COMBOBOXINFO
DEF SCROLLINFO :_SCROLLINFO
DEF OrigCBLB_LF,OrigComb_LF,ScrollPos,MaxPix :INT
' ===============================================================================================
CREATEDIALOG MainD,0,0,300,409,0x80C80080,0,"Caption",&MainD_handler
CONTROL MainD,@COMBOBOX,"",CB_OX,CB_OY,CB_OX + CB_XW,CB_OY + CB_YW,@CTCOMBODROPDOWN|@VSCROLL|@CTCOMBOAUTOHSCROLL|@CTCOMBOSORT,COMBO
DOMODAL MainD
END

' =================================== D I A L O G  P R O C ======================================
SUB MainD_handler
DEF A,MaxL,vWidth,vHeight :INT
DEF Item :STRING
' -----------------------------------------------------------------------------------------------
MaxL = 0
SELECT @MESSAGE
CASE @IDINITDIALOG
CENTERWINDOW MainD
FOR A = 0 TO 40 'Fill the combo
ADDSTRING(MainD,COMBO,USING("0#####",A) + " " + STRING$(RAND(150),"*") + "!")
NEXT A

' used variables...
int hdc, hfontold
DEF l,t,w,h  as INT

Measurement_Init(hdc, hfontold)

FOR A = 0 TO 40 'Get the longest item
Item = GETSTRING(mainD,COMBO,A)
IF (LEN(Item) > MaxL) THEN
MaxL = LEN(Item)

'GETTEXTSIZE(MainD,Item,vWidth,vHeight)
vWidth = MeasureStringX(hdc, Item)

MaxPix = vWidth
ENDIF
NEXT A

Measurement_Finish(hdc, hfontold)

SETHORIZEXTENT(MainD,COMBO,MaxPix) 'The listbox seems to be too width (why ?????)
COMBOBOXINFO_LF.cbSize = LEN(COMBOBOXINFO_LF)
SCROLLINFO.cbSize = LEN(SCROLLINFO)
SCROLLINFO.fMask = SIF_RANGE|SIF_PAGE
SCROLLINFO.nMax = MaxPix

GETSIZE MainD, l, t, w, h, COMBO

' --------------------
SCROLLINFO.nPage = w
' --------------------

IF (GetComboBoxInfo(GETCONTROLHANDLE(MainD,COMBO),COMBOBOXINFO_LF)) THEN
OrigCBLB_LF = SetWindowLongA(COMBOBOXINFO_LF.hwndList,GWL_WNDPROC,&CB_LF_LBHandler)
OrigComb_LF = SetWindowLongA(COMBOBOXINFO_LF.hwndCombo,GWL_WNDPROC,&CB_LF_Handler)
SetScrollInfo(COMBOBOXINFO_LF.hwndList,SB_HORZ,SCROLLINFO,FALSE)
ENDIF
CASE @IDCLOSEWINDOW
CLOSEDIALOG MainD
CASE @IDCONTROL
SELECT @CONTROLID
CASE COMBO
/* respond to control notifications here */
ENDSELECT
ENDSELECT
ENDSUB

' ================================== S U B R O U T I N E =========================================
SUB CB_LF_LBHandler(hwnd:int,uMsg:int,wParam:UINT,lParam:pointer),int
DEF LOWWORD :WORD
' ------------------------------------------------------------------------------------------------
LOWWORD = wParam
SCROLLINFO.cbSize = LEN(SCROLLINFO)
GetScrollInfo( GETCONTROLHANDLE(MainD,COMBO), SB_HORZ, SCROLLINFO)
                ScrollPos = SCROLLINFO.nPos
IF uMsg = WM_HSCROLL THEN
SELECT LOWWORD
CASE SB_PAGERIGHT
ScrollPos += SCROLLINFO.nPage 'Trying to move with page width dosn't seem right ???
CASE SB_PAGELEFT
ScrollPos -= SCROLLINFO.nPage
CASE SB_LINELEFT
ScrollPos -= 1 'Scrolling isn't proportional ??????
IF ScrollPos < 0 THEN ScrollPos = 0
CASE SB_LINERIGHT
ScrollPos += 1
IF (ScrollPos > MaxPix) THEN ScrollPos = MaxPix
CASE SB_THUMBPOSITION
ScrollPos = wParam >> 16
ENDSELECT
SCROLLINFO.fMask = SIF_POS
SCROLLINFO.nPos = ScrollPos
SetScrollInfo(COMBOBOXINFO_LF.hwndList,SB_HORZ,SCROLLINFO,TRUE)
ENDIF
RETURN CallWindowProcA(OrigCBLB_LF,hwnd,uMsg,wParam,lParam)
ENDSUB

' ================================== S U B R O U T I N E =========================================
SUB CB_LF_Handler(hwnd:int,uMsg:int,wParam:UINT,lParam:pointer),int
IF uMsg = WM_LBUTTONDOWN THEN
SENDMESSAGE MainD,CB_SHOWDROPDOWN,TRUE,0,COMBO
RETURN TRUE
ENDIF
RETURN CallWindowProcA(OrigComb_LF,hwnd,uMsg,wParam,lParam)
ENDSUB


SUB Measurement_Init(int hdc BYREF, INT hfont BYREF)
hdc = _CreateCompatibleDC(0)
hfont = SENDMESSAGE( GETCONTROLHANDLE(MainD,COMBO), WM_GETFONT, 0, 0)
hfont = _SelectObject(hdc, hfont)
ENDSUB

SUB MeasureStringX(int hdc, STRING text), INT
SIZE sz

_GetTextExtentPoint32(hdc, text, LEN(text), sz)
RETURN sz.cx + 2*_GetSystemMetrics(SM_CXEDGE)+_GetSystemMetrics(SM_CXVSCROLL)
ENDSUB

SUB Measurement_Finish(int hdc, INT hfontold)
_SelectObject(hdc, hfontold)
_DeleteDC(hdc)
ENDSUB




Ficko

Thanx Fasecero! :)

You have been giving me good directions. :D

I think I found Formel #1 seems to work for any size combo.
- The last character of the longest item is touching the right border if moving the scroll box -thumb- it smoothly bouncing left and right -  ;D

Now, let see Formel #2. ;)

It is for "SB_LINELEFT" & "SB_LINERIGHT".
+/- 1 is no way right.
The thumb is barelly making 1/4 of the scrollbar at the list box end. :o


AUTODEFINE "OFF"
' ===============================================================================================
DECLARE IMPORT,SetWindowLongA(hWnd:INT,nIndex:INT,dwNewLong:INT),INT
DECLARE IMPORT,SetScrollInfo(HWND:INT,fnBar:INT,lpsi:_LPSCROLLINFO,fRedraw:INT),UINT
DECLARE IMPORT,GetScrollInfo(HWND:INT,fnBar:INT,lpsi:_LPSCROLLINFO),UINT
DECLARE IMPORT,GetComboBoxInfo(HWND:INT,PCOMBOBOXINFO:_COMBOBOXINFO),INT
DECLARE IMPORT,CallWindowProcA(lpPrevWndFunc:INT,hWnd:INT,Msg:INT,wParam:INT,lParam:INT),INT
DECLARE IMPORT, _CreateCompatibleDC ALIAS CreateCompatibleDC(hdc:INT),INT
DECLARE IMPORT, _ReleaseDC ALIAS ReleaseDC(hdc:INT),INT
DECLARE IMPORT, _SelectObject ALIAS SelectObject(hdc:INT,hObject:INT),INT
DECLARE IMPORT, _GetTextExtentPoint32 ALIAS GetTextExtentPoint32A(hdc:INT,lpsz:STRING,cbString:INT,lpSize:SIZE),INT
DECLARE IMPORT, _GetSystemMetrics ALIAS GetSystemMetrics(nIndex:INT),INT
' ===============================================================================================
TYPE _COMBOBOXINFO
  DEF cbSize:UINT
  DEF rcItem:WINRECT
  DEF rcButton:WINRECT
  DEF stateButton:UINT
  DEF hwndCombo:INT
  DEF hwndItem:INT
  DEF hwndList:INT
ENDTYPE
TYPE _SCROLLINFO
  DEF cbSize:UINT
  DEF fMask:UINT
  DEF nMin:INT
  DEF nMax:INT
  DEF nPage:INT
  DEF nPos:INT
  DEF nTrackPos:INT
ENDTYPE
TYPE Size
DEF cx AS INT
DEF cy AS INT
ENDTYPE
' ===============================================================================================
CONST COMBO = 1
CONST CB_SHOWDROPDOWN    = 0x14F
CONST CB_SETHORIZONTALEXTENT = 0x15E
CONST CB_GETHORIZONTALEXTENT    = 0x15D
CONST SB_HORZ = 0
CONST SB_LINELEFT        = 0
CONST SB_LINERIGHT      = 1
CONST SB_PAGELEFT        = 2
CONST SB_PAGERIGHT      = 3
CONST SB_THUMBPOSITION  = 4
CONST SIF_RANGE      = 1
CONST SIF_PAGE      = 2
CONST SIF_POS        = 4
CONST GWL_WNDPROC = -4
CONST WM_HSCROLL = 0x114
CONST WM_LBUTTONDOWN    = 0x201
CONST WM_GETFONT = 0x31
CONST CB_OX = 10
CONST CB_OY = 10
CONST CB_XW = 200 'Combo width
CONST CB_YW = 350
CONST SM_CXVSCROLL              = 2
CONST SM_CXHSCROLL              = 21
CONST SM_CXHTHUMB = 10
' ===============================================================================================
DEF MainD :DIALOG
DEF COMBOBOXINFO_LF :_COMBOBOXINFO
DEF SCROLLINFO :_SCROLLINFO
DEF OrigCBLB,OrigComb,MaxPix,Thumb :INT
' ===============================================================================================
OPENCONSOLE
CREATEDIALOG MainD,0,0,800,409,0x80C80080,0,"Caption",&MainD_handler
CONTROL MainD,@COMBOBOX,"",CB_OX,CB_OY,CB_XW,CB_YW,@CTCOMBODROPDOWN|@CTCOMBOAUTOHSCROLL|@VSCROLL|@CTCOMBOSORT,COMBO
DOMODAL MainD
END

' =================================== D I A L O G  P R O C ======================================
SUB MainD_handler
DEF MaxL,HFont,Hdc,HOldFont :INT
' -----------------------------------------------------------------------------------------------
MaxL = 0
SELECT @MESSAGE
CASE @IDINITDIALOG
CENTERWINDOW MainD
COMBOBOXINFO_LF.cbSize = LEN(COMBOBOXINFO_LF)
IF (GetComboBoxInfo(GETCONTROLHANDLE(MainD,COMBO),COMBOBOXINFO_LF)) THEN
FillCombo()
Hdc = _CreateCompatibleDC(0)
HFont = SENDMESSAGE(COMBOBOXINFO_LF.hwndList,WM_GETFONT,0,0)
HOldFont = _SelectObject(Hdc,HFont)
GetMaxItem(Hdc)
_SelectObject(Hdc,HOldFont):_ReleaseDC(Hdc)
SETHORIZEXTENT(MainD,COMBO,MaxPix)
SCROLLINFO.cbSize = LEN(SCROLLINFO)
SCROLLINFO.fMask = SIF_RANGE|SIF_PAGE
SCROLLINFO.nMax = MaxPix
SCROLLINFO.nPage = CB_XW - _GetSystemMetrics(SM_CXHSCROLL) - 1
OrigCBLB = SetWindowLongA(COMBOBOXINFO_LF.hwndList,GWL_WNDPROC,&CB_LBHandler)
OrigComb = SetWindowLongA(COMBOBOXINFO_LF.hwndCombo,GWL_WNDPROC,&CB_Handler)
SetScrollInfo(COMBOBOXINFO_LF.hwndList,SB_HORZ,SCROLLINFO,FALSE)
ENDIF
CASE @IDCLOSEWINDOW
CLOSEDIALOG MainD
CASE @IDCONTROL
SELECT @CONTROLID
CASE COMBO
/* respond to control notifications here */
ENDSELECT
ENDSELECT
ENDSUB

' ==================================== S U B C L A S S ===========================================
SUB CB_LBHandler(hwnd:INT,uMsg:INT,wParam:UINT,lParam:POINTER),INT
DEF LOWWORD :WORD
DEF ScrollPos :INT
' ------------------------------------------------------------------------------------------------
LOWWORD = wParam
IF uMsg = WM_HSCROLL THEN
SCROLLINFO.fMask = SIF_POS
GetScrollInfo(GETCONTROLHANDLE(MainD,COMBO),SB_HORZ,SCROLLINFO)
ScrollPos = SCROLLINFO.nPos
SELECT LOWWORD
CASE SB_PAGERIGHT
ScrollPos += CB_XW
CASE SB_PAGELEFT
ScrollPos -= CB_XW
CASE SB_LINELEFT
ScrollPos -= 1
IF ScrollPos < 0 THEN ScrollPos = 0
CASE SB_LINERIGHT
ScrollPos += 1
IF (ScrollPos > MaxPix) THEN ScrollPos = MaxPix
CASE SB_THUMBPOSITION
ScrollPos = wParam >> 16
ENDSELECT
SCROLLINFO.nPos = ScrollPos
SetScrollInfo(COMBOBOXINFO_LF.hwndList,SB_HORZ,SCROLLINFO,TRUE)
ENDIF
RETURN CallWindowProcA(OrigCBLB,hwnd,uMsg,wParam,lParam)
ENDSUB

' ==================================== S U B C L A S S ===========================================
SUB CB_Handler(hwnd:INT,uMsg:INT,wParam:UINT,lParam:POINTER),INT
IF uMsg = WM_LBUTTONDOWN THEN
SENDMESSAGE MainD,CB_SHOWDROPDOWN,TRUE,0,COMBO
RETURN TRUE
ENDIF
RETURN CallWindowProcA(OrigComb,hwnd,uMsg,wParam,lParam)
ENDSUB

' ================================== S U B R O U T I N E =========================================
SUB FillCombo
DEF A :INT
' ------------------------------------------------------------------------------------------------
FOR A = 0 TO 30
ADDSTRING(MainD,COMBO,USING("0#####",A) + " " + STRING$(100 + A*2,"*") + "X")
NEXT A
ENDSUB

' ================================== S U B R O U T I N E =========================================
SUB GetMaxItem(HDC:INT)
DEF A,TempX :INT
' ------------------------------------------------------------------------------------------------
FOR A = 0 TO 40 'Get the longest item
TempX = MeasureStringX(HDC,GETSTRING(MainD,COMBO,A))
IF (TempX > MaxPix) THEN
MaxPix = TempX
ENDIF
NEXT A
ENDSUB

' ================================== S U B R O U T I N E =========================================
SUB MeasureStringX(HDC:INT,Text:STRING),INT
DEF sz :SIZE
' ------------------------------------------------------------------------------------------------
_GetTextExtentPoint32(HDC,Text,LEN(Text),sz)
RETURN sz.cx + 2
ENDSUB