Purebasic 4.5 brings an upgrade to ComboBox gadgets in that, under windows, PB has replaced the older ComboBox control class with the newer ComboBoxEx control classes. This allows for easy use of image lists etc. (See the PB help manual for an example).
However, this does have one disadvantage, namely that you cannot (at least I have been unable to do so) use owner-drawn methods with these new controls. (For me, a consequence of this is that my EsGRID control has collapsed... albeit temporarily!

I have therefore created this small wrapper around the Windows ComboBox control class, mimicking, as far as is possible, the operation of PB's gadget library etc. Indeed, Freak kindly made his original C code available so that I could mimick PB's original wrapper right down to the last comment. The good thing being that we are guaranteed to have a control which is absolutely compatible with the original PB ComboboxGadget right down to the borders and styles etc. (Just what I need for EsGRID's salvation!)
My thanks to Freak/Fred for making this code available and allowing me to make this posting.
Main code...
Code: Select all
CompilerIf Defined(INCLUDE_APICOMBO, #PB_Constant)=0
#INCLUDE_APICOMBO=1
;/////////////////////////////////////////////////////////////////////////////////
;***API Combo controls*** - Version 1.1.
;=======================
; Thanks to Timo (Freak) for his permission to translate (from C) his original Windows wrapper around the ComboBox api.
;
; Created with Purebasic 4.5 for Windows.
;
; Platforms: Windows.
;/////////////////////////////////////////////////////////////////////////////////
;/////////////////////////////////////////////////////////////////////////////////
;With Purebasic 4.5 the ComboBox gadget has been upgraded to a Windows ComboBoxEx control which, whilst offering images etc.
;does not allow us to use ownerdrawn techniques etc.
;This api wrapper, therefore, offers easy access to standard ComboBox controls which can be ownerdrawn and so on. We follow the original
;Purebasic ComboBoxGadget (prior to PB 4.5) as close as possible and indeed this code is a direct translation of Freak/Fred's original
;C code.
;/////////////////////////////////////////////////////////////////////////////////
;/////////////////////////////////////////////////////////////////////////////////
;NOTES :
;
; i) Create a combo control with the APIComboGadget() function.
; Use the 'styles' parameter to set some styles (e.g. #CBS_OWNERDRAWFIXED) which will be in addition to those set internally.
;
; ii) The #GWL_USERDATA attribute is used internally. Do not use it!
;/////////////////////////////////////////////////////////////////////////////////
EnableExplicit
Procedure.i APIComboGadget(hWndParent, x, y, width, height, styles=0, blnEditable=#False)
Protected hWnd, hEdit, rc.RECT, bordersHeight
If hWndParent
styles | #WS_CHILD | #WS_VISIBLE | #WS_BORDER | #CBS_HASSTRINGS | #WS_GROUP | #WS_VSCROLL | #CBS_AUTOHSCROLL
If blnEditable
styles | #CBS_DROPDOWN
Else
styles | #CBS_DROPDOWNLIST|#WS_TABSTOP
EndIf
hWnd = CreateWindowEx_(#WS_EX_CLIENTEDGE, @"ComboBox", 0, styles, x, y, width, 350, hWndParent, -1, GetModuleHandle_(0), 0)
If hWnd
If blnEditable
;Add the tabstop to the edit control.
hEdit = GetWindow_(hWnd, #GW_CHILD)
SetWindowLongPtr_(hEdit, #GWL_STYLE, GetWindowLongPtr_(hEdit, #GWL_STYLE) | #WS_TABSTOP)
EndIf
;Set the real height by taking the selection item's border into account.
SendMessage_(hWnd, #WM_SETFONT, GetStockObject_(#DEFAULT_GUI_FONT), 0)
SendMessage_(hWnd, #CB_SETITEMHEIGHT, -1, 15)
GetWindowRect_(hWnd, rc)
bordersHeight = rc\bottom - rc\top - 15
SendMessage_(hWnd, #CB_SETITEMHEIGHT, -1, height-bordersHeight)
;Record the height.
SetWindowLongPtr_(hWnd, #GWL_USERDATA, bordersHeight)
EndIf
EndIf
ProcedureReturn hWnd
EndProcedure
Procedure APICombo_AddGadgetItem(hWndCombo, position, text$)
If position >= -1
SendMessage_(hWndCombo, #CB_INSERTSTRING, position, @text$)
EndIf
EndProcedure
Procedure APICombo_ClearGadgetItems(hWndCombo)
SendMessage_(hWndCombo, #CB_RESETCONTENT, 0, 0)
EndProcedure
Procedure.i APICombo_CountGadgetItems(hWndCombo)
ProcedureReturn SendMessage_(hWndCombo, #CB_GETCOUNT, 0, 0)
EndProcedure
Procedure APICombo_DisableGadget(hWndCombo, state)
If state
state = 0
Else
state = 1
EndIf
EnableWindow_(hWndCombo, state)
EndProcedure
Procedure APICombo_FreeGadget(hWndCombo)
DestroyWindow_(hWndCombo)
EndProcedure
Procedure.i APICombo_GadgetHeight(hWndCombo)
Protected result, wp.WINDOWPLACEMENT
wp\Length = SizeOf(WINDOWPLACEMENT)
If GetWindowPlacement_(hWndCombo, wp)
result = wp\rcNormalPosition\bottom - wp\rcNormalPosition\top
EndIf
ProcedureReturn result
EndProcedure
Procedure.i APICombo_GadgetWidth(hWndCombo)
Protected result, wp.WINDOWPLACEMENT
wp\Length = SizeOf(WINDOWPLACEMENT)
If GetWindowPlacement_(hWndCombo, wp)
result = wp\rcNormalPosition\right - wp\rcNormalPosition\left
EndIf
ProcedureReturn result
EndProcedure
Procedure.i APICombo_GadgetX(hWndCombo)
Protected result, wp.WINDOWPLACEMENT
wp\Length = SizeOf(WINDOWPLACEMENT)
If GetWindowPlacement_(hWndCombo, wp)
result = wp\rcNormalPosition\left
EndIf
ProcedureReturn result
EndProcedure
Procedure.i APICombo_GadgetY(hWndCombo)
Protected result, wp.WINDOWPLACEMENT
wp\Length = SizeOf(WINDOWPLACEMENT)
If GetWindowPlacement_(hWndCombo, wp)
result = wp\rcNormalPosition\top
EndIf
ProcedureReturn result
EndProcedure
Procedure.i APICombo_GetGadgetItemData(hWndCombo, item)
ProcedureReturn SendMessage_(hWndCombo, #CB_GETITEMDATA, item, 0)
EndProcedure
Procedure.s APICombo_GetGadgetItemText(hWndCombo, item)
Protected length, text$
length = SendMessage_(hWndCombo, #CB_GETLBTEXTLEN, item, 0)
If length > 0
text$ = Space(length)
SendMessage_(hWndCombo, #CB_GETLBTEXT, item, @text$)
EndIf
ProcedureReturn text$
EndProcedure
Procedure.i APICombo_GetGadgetState(hWndCombo)
ProcedureReturn SendMessage_(hWndCombo, #CB_GETCURSEL, 0, 0)
EndProcedure
Procedure.s APICombo_GetGadgetText(hWndCombo)
Protected length, text$
length = GetWindowTextLength_(hWndCombo)
If length > 0
text$ = space(length)
GetWindowText_(hWndCombo, @text$, 100)
EndIf
ProcedureReturn text$
EndProcedure
Procedure APICombo_HideGadget(hWndCombo, state)
If state
ShowWindow_(hWndCombo, #SW_HIDE)
Else
ShowWindow_(hWndCombo, #SW_SHOW)
EndIf
EndProcedure
Procedure APICombo_RemoveGadgetItem(hWndCombo, item)
SendMessage_(hWndCombo, #CB_DELETESTRING, item, 0)
EndProcedure
Procedure APICombo_ResizeGadget(hWndCombo, x, y, width, height)
Protected wp.WINDOWPLACEMENT, dropHeight, rc.RECT, borderHeight
;First the control itself including the drop down height.
wp\Length = SizeOf(WINDOWPLACEMENT)
If GetWindowPlacement_(hWndCombo, wp)
If x = #PB_Ignore
x = wp\rcNormalPosition\left
EndIf
If y = #PB_Ignore
y = wp\rcNormalPosition\top
EndIf
If width = #PB_Ignore
width = wp\rcNormalPosition\right - wp\rcNormalPosition\left
EndIf
SendMessage_(hWndCombo, #CB_GETDROPPEDCONTROLRECT, 0, rc)
dropHeight = rc\bottom - rc\top
MoveWindow_(hWndCombo, x, y, width, dropHeight, 1)
;Now the selection field.
If height <> #PB_Ignore
borderHeight = GetWindowLongPtr_(hWndCombo, #GWL_USERDATA)
SendMessage_(hWndCombo, #CB_SETITEMHEIGHT, -1, height-borderHeight)
EndIf
EndIf
EndProcedure
Procedure APICombo_SetGadgetItemData(hWndCombo, item, userData)
SendMessage_(hWndCombo, #CB_SETITEMDATA, item, userData)
EndProcedure
Procedure APICombo_SetGadgetItemText(hWndCombo, item, text$)
Protected userData
userData = SendMessage_(hWndCombo, #CB_GETITEMDATA, item, 0) ;Preserve the userdata!
If SendMessage_(hWndCombo, #CB_DELETESTRING, item, 0) <> -1
SendMessage_(hWndCombo, #CB_INSERTSTRING, item, text$)
SendMessage_(hWndCombo, #CB_SETITEMDATA, item, userData)
EndIf
EndProcedure
Procedure APICombo_SetGadgetState(hWndCombo, state)
SendMessage_(hWndCombo, #CB_SETCURSEL, state, 0)
EndProcedure
Procedure APICombo_SetGadgetText(hWndCombo, text$)
Protected item
If GetWindowLongPtr_(hWndCombo, #GWL_STYLE) & #CBS_SIMPLE ;Not editable.
If text$
item = SendMessage_(hWndCombo, #CB_FINDSTRINGEXACT, -1, @text$)
If item <> -1
SendMessage_(hWndCombo, #CB_SETCURSEL, item, 0)
EndIf
Else
SendMessage_(hWndCombo, #CB_SETCURSEL, -1, 0)
EndIf
Else ;Editable
SetWindowText_(hWndCombo, text$)
EndIf
EndProcedure
DisableExplicit
CompilerEndIf
Demo...
Code: Select all
XIncludeFile "apiCombo.pbi"
hWnd = OpenWindow(0, 0, 0, 270, 60, "API Combo Control", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
If hWnd
hWndCombo = APIComboGadget(hWnd, 10, 10, 250, 20)
If hWndCombo
For i = 0 To 9
APICombo_AddGadgetItem(hWndCombo, -1, "Item " + Str(i))
Next
APICombo_SetGadgetState(hWndCombo, 2)
EndIf
Repeat : Until WaitWindowEvent() = #PB_Event_CloseWindow
EndIf