Here is an idea from Fig who asked a way to edit every item in a ComboBox gadget.
Also, if any body asked the same idea earlier, no problem to add a link to such a message !
So, you can see this code which allows you to edit each item of a combo box.
What I imagine clever is the graphical compactness allowed by a combo on the basis. Adding this feature, the coder does not worry about another one that the region characteristics of the gadget which stays constant and so, forseeable.
I apologize for my language mistakes the best writers can put back here : I do not use translating bot.
So... Back to the main : user process.
1) He clicks on the box : naturally, a prestored list is automatically displayed, as the classical combo offers to the user.
2) He clicks on one of the item he chose : the item, ever naturally, is copied to the main combo scope.
3) The user edits it as usually...
4) And, now is the change : two ways are offered to the user.
a) Abort the editing by a simple click away from the combo which removes the focus : editing is cancelled and the old item text is remained and displayed on the main combo scope.
b) Validate the editing by the [Enter] key press : in this way, item is updated by the new text content. The modifying can be checked by the step #1 of this process, and some other items can be changed like this...
Easy !
Now, coder process...
=>> Just replaces ComboxBoxGadget keyword statement with ComboGadget.
=>> Does not worry about the flags argument : ComboGadget() procedure does not care.
=>> If a specific item should be initially set, the coder will use ComboItem() procedure after having added initial item, exactly as classical ComboBox gadget.
=>> The coder can use classical ComboBoxGadget() statement. In this way, he has not to forget #PB_ComboBox_Editable flag on the 6th argument (see reference, and will use ComboCreate() procedure.
=>> ComboCreate() procedure returning a handle, see the following syntax to use it :
Code: Select all
SetGadgetData(Gadget, ComboCreate(Window, Gadget) )
=>> To allow this technical break step, 2 internal values must be choosen by the coder : unique key internal code, and unique ghost menu internal code.
=>> Unique key internal code is easy to understand anymore : the program uses it to bypass combo charasteristics inefficience shortcut callback. This code is specific to identify [Enter] key data type event. Here, I chose then numeral 64-bits value 'GK13', but the coder can change it for its own needs.
=>> Unique ghost menu internal code is a little bit more difficult to understand : the program uses it to dicern each "high-level" combo gadget. It is a menu item identifier. I could set it a automatical identifier provider (in a domain between 0 and 64000). But, in this way, I prevented the coder from being free to choose its own menu item identifying values, and this could be source of conflict ! So, I let the coder to choose these. In the example below, in the queue of the following code, you can see I chose the 100 and 101 values. Free to the coder to set them !
=>> Whatever the coder uses ComboGadget() or ComboCreate(), he has to free internal buffer when he deletes the gadget or the host window. For that, there is ComboDelete() procedure. Do not forget !
This tip is on 32 or 64 bits modes : just adapt the first constant.
Hope this will be a new native feature...
Thank again to Fig.
If you see some technical or linguistic mistakes, please tell them.
Code: Select all
;*************************************************************************************************************************************************************************************************
; (An idea from Fig)
#ComboKeyEnter = 'GK13'
Structure COMBO
Window.I
Gadget.I
Item.I
kMenu.I
kMenuItem.I
ReturnKey.I
EndStructure
Declare ComboReturnKey()
Declare ComboCallBack()
Procedure ComboCreate(Window, Gadget, kMenuItemDefault = 64000)
Define *A.COMBO = AllocateMemory(SizeOf(COMBO) )
With *A
\Window = Window
\Gadget = Gadget
\kMenuItem = kMenuItemDefault
BindEvent(#PB_Event_Gadget, @ComboCallBack(), \Window, \Gadget)
\kMenu = CreateMenu(#PB_Any, WindowID(\Window) )
BindMenuEvent(\kMenu, \kMenuItem, @ComboReturnKey() )
EndWith
ProcedureReturn *A
EndProcedure
Procedure ComboDelete(Gadget)
Define *A.COMBO = GetGadgetData(Gadget)
With *A
UnbindEvent(#PB_Event_Gadget, @ComboCallBack(), \Window, Gadget)
UnbindMenuEvent(\kMenu, \kMenuItem, @ComboReturnKey() )
FreeMemory(*A)
EndWith
EndProcedure
Procedure ComboReturnKey()
PostEvent(#PB_Event_Gadget, GetActiveWindow(), GetActiveGadget(), #PB_EventType_FirstCustomValue, 'GK13')
EndProcedure
Procedure ComboCallBack()
Define Gadget = EventGadget()
Define *A.COMBO = GetGadgetData(Gadget)
Define gState = GetGadgetState(Gadget)
If *A
With *A
Select EventType()
Case #PB_EventType_Focus
AddKeyboardShortcut(\Window, #PB_Shortcut_Return, \kMenuItem)
Case #PB_EventType_LostFocus
RemoveKeyboardShortcut(\Window, #PB_Shortcut_Return)
SetGadgetText(Gadget, GetGadgetItemText(Gadget, \Item) )
Case #PB_EventType_Change
If gState <> -1
\Item = gState
EndIf
Case #PB_EventType_FirstCustomValue
If EventData() = 'GK13'
SetGadgetItemText(Gadget, \Item, GetGadgetText(Gadget) )
EndIf
EndSelect
EndWith
EndIf
EndProcedure
Procedure ComboGadget(Id, x, y, w, h, kMenuItemDefault = 64000)
Define Result
Define Gadget
Result = ComboBoxGadget(Id, x, y, w, h, #PB_ComboBox_Editable)
If Id = #PB_Any
Gadget = Result
Else
Gadget = Id
EndIf
SetGadgetData(Gadget, ComboCreate(GetActiveWindow(), Gadget, kMenuItemDefault) )
ProcedureReturn Result
EndProcedure
Procedure ComboItem(Gadget, Item)
Define *A.COMBO = GetGadgetData(Gadget)
If *A
With *A
SetGadgetState(Gadget, Item)
\Item = Item
EndWith
EndIf
EndProcedure
; Example
If OpenWindow(10, 0, 0, 270, 180, "Combo", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
ComboGadget(20, 10, 10, 250, 100)
AddGadgetItem(20, -1, "Option A")
AddGadgetItem(20, -1, "Option B")
AddGadgetItem(20, -1, "Option C")
ComboItem(20, 1)
ComboGadget(21, 10, 42, 250, 101)
AddGadgetItem(21, -1, "Week 1")
AddGadgetItem(21, -1, "Week 2")
AddGadgetItem(21, -1, "Week 3")
ComboItem(21, 2)
Repeat : Until WaitWindowEvent() = #PB_Event_CloseWindow
EndIf