Page 1 of 1
Simplified ComboBox Autocomplete
Posted: Mon Aug 18, 2003 8:49 pm
by ebs
Code in this post updated to 5.20+
I needed an autocompleting ComboBox and found a tip posted by Saboteur. I simplified his code by using "GetGadgetItemText()". I also made the routine accept the gadget number of the ComboBox to be completed, so it can be used for any number of ComboBoxes.
Code: Select all
;- autocomplete specified combobox
Procedure AutocompleteComboBox(ComboBox.l)
; get text entered by user
TextTyped.s = UCase(GetGadgetText(ComboBox))
LenTextTyped.l = Len(TextTyped)
; done if no text entered
If LenTextTyped
; search combo contents for item that starts with text entered
MaxItem.l = CountGadgetItems(ComboBox) - 1
For Item.l = 0 To MaxItem
If TextTyped = UCase(Left(GetGadgetItemText(ComboBox, Item, 0), LenTextTyped))
; found matching item
; set combo state
SetGadgetState(ComboBox, Item)
; select added text only
MyPoint.POINT
hComboEdit.l = ChildWindowFromPoint_(GadgetID(ComboBox), MyPoint);5, 5)
SendMessage_(hComboEdit, #EM_SETSEL, LenTextTyped, -1)
; exit For loop
Item = MaxItem
EndIf
Next
EndIf
EndProcedure
If OpenWindow(0, 0, 0, 300, 300, "Autocompletion", #PB_Window_SystemMenu|#PB_Window_TitleBar)
; If CreateGadgetList(WindowID(0))
ComboBoxGadget(0, 10, 10, 200, 100, #PB_ComboBox_Editable)
AddGadgetItem(0, -1, "Autocomplete")
AddGadgetItem(0, -1, "Bernard")
AddGadgetItem(0, -1, "Car")
AddGadgetItem(0, -1, "Explorer")
AddGadgetItem(0, -1, "Fantastic")
AddGadgetItem(0, -1, "General protection error")
AddGadgetItem(0, -1, "Purebasic")
AddGadgetItem(0, -1, "Purepower")
AddGadgetItem(0, -1, "Purevisual")
AddGadgetItem(0, -1, "Question")
AddGadgetItem(0, -1, "Zas")
; EndIf
EndIf
Repeat
Event = WaitWindowEvent()
Select Event
Case #PB_Event_Gadget
If EventGadget() = 0
AutocompleteComboBox(0)
EndIf
EndSelect
Until Event = #PB_Event_CloseWindow
End
If you need this capability, please try it and let me know how it works for you.
Eric
Posted: Mon Aug 18, 2003 10:20 pm
by Saboteur
Good update, ebs

Posted: Wed Aug 20, 2003 2:29 am
by aszid
i tested this out and found a little problem, once it has "autocompleted" the line, i can no longer use backspace... that was actually almost the first thing i did when i tried the code.
anyhow, running win2k here, 128mb ram.
Posted: Wed Aug 20, 2003 3:13 pm
by ebs
aszid,
I'm aware of that, and I'm not sure how to handle it the best way.
After autocompletion, backspace
does actually work, but the text is autocompleted again immediately, so you don't see it. I'm trying to figure out a straightforward way to delay autocompleting until another character is typed after a backspace, but so far, it's kind of messy. If I come up with something good, I'll post it here.
On another note, sometimes you may not want to autocomplete until a certain number of characters have been entered - I often use 3 characters. You can get this behavior easily by changing the line
to
Autocomplete Works With Backspace
Posted: Sat Aug 23, 2003 10:05 pm
by ebs
Here's a new version of the autocomplete code which works properly when Backspace is pressed:
Code: Select all
#NONE = -1
;- autocomplete specified combobox
Procedure AutocompleteComboBox(ComboBox.l)
Shared LenTextSave.l
Shared GadgetSave.l
; get text entered by user
TextTyped.s = UCase(GetGadgetText(ComboBox))
LenTextTyped.l = Len(TextTyped)
; skip if same gadget and same length or shorter text (backspace?)
If ComboBox = GadgetSave And LenTextTyped <= LenTextSave
LenTextSave = LenTextTyped
ElseIf LenTextTyped
GadgetSave = #NONE
; search combo contents for item that starts with text entered
MaxItem.l = CountGadgetItems(ComboBox) - 1
For Item.l = 0 To MaxItem
If TextTyped = UCase(Left(GetGadgetItemText(ComboBox, Item, 0), LenTextTyped))
; found matching item
; set combo state
SetGadgetState(ComboBox, Item)
; select added text only
hComboEdit.l = ChildWindowFromPoint_(GadgetID(ComboBox), 5, 5)
SendMessage_(hComboEdit, #EM_SETSEL, LenTextTyped, -1)
; save gadget number and text length for next pass
LenTextSave = LenTextTyped
GadgetSave = ComboBox
; exit For loop
Item = MaxItem
EndIf
Next
EndIf
EndProcedure
If OpenWindow(0, 0, 0, 300, 300, #PB_Window_SystemMenu|#PB_Window_TitleBar, "Autocompletion")
If CreateGadgetList(WindowID())
ComboBoxGadget(0, 10, 10, 200, 100, #PB_ComboBox_Editable)
AddGadgetItem(0, -1, "Autocomplete")
AddGadgetItem(0, -1, "Bernard")
AddGadgetItem(0, -1, "Car")
AddGadgetItem(0, -1, "Explorer")
AddGadgetItem(0, -1, "Fantastic")
AddGadgetItem(0, -1, "General protection error")
AddGadgetItem(0, -1, "Purebasic")
AddGadgetItem(0, -1, "Purepower")
AddGadgetItem(0, -1, "Purevisual")
AddGadgetItem(0, -1, "Question")
AddGadgetItem(0, -1, "Zas")
EndIf
EndIf
Repeat
Event = WaitWindowEvent()
Select Event
Case #PB_Event_Gadget
If EventGadgetID() = 0
AutocompleteComboBox(0)
EndIf
EndSelect
Until Event = #PB_Event_CloseWindow
End
Let me know if it works for you!
Posted: Wed Dec 03, 2003 3:00 am
by Karbon
It works for me when I run it in your example but I'm getting some pretty strange stuff when I included it in my own project.
I copied the function exactly, then changed the
Code: Select all
hComboEdit.l = ChildWindowFromPoint_(GadgetID(ComboBox), 5, 5)
to
Code: Select all
hComboEdit.l = ChildWindowFromPoint_(GadgetID(ComboBox), 117, 100)
Which should compensate for my gadget being in a different position.. Now, what I see happening in my project is very much what I expected to happen because you're calling the function every time any event occurs on the gadget, which means it gets called every time a key is pressed.. So if that happens then the TextTyped variable is set to what ever the current text in the gadget is. Now that's all fine and dandy until you get a match on the first character of what you type, then that item is selected which writes the full text of what ever the first match was into the TextTyped variable (because you set the state to that match every time), causing the entire thing to be selected and thus making my life hell!
What I can't figure out for the life of me (and this might be because this is hour 16 today) is - how the hell the example works like it does! I've taken my exact combo box that's dysfunctional in my project, put those items in the one in the example and it works like a charm! I'm using the *exact* function as in the example, less the change I outlined above, and it just doesn't work in my project!
Help!?

Posted: Wed Dec 03, 2003 4:01 pm
by Karbon
All fixed up - just me being a cluebie..
Posted: Wed Dec 03, 2003 4:21 pm
by ebs
Mitch,
I didn't even get a chance to reply before you figured it out!
You went back to using
Code: Select all
...ChildWindowFromPoint_(GadgetID(ComboBox), 5, 5)
Right?
Eric
Posted: Wed Dec 03, 2003 4:33 pm
by Karbon
Actually, no, if I do that then none of the text at all gets selected.. Aren't those the x/y coors of the combo?
Code: Select all
ComboBoxGadget(#Gadget_invoice_cmb_customer,65,75,234,100,#PB_ComboBox_Editable)
... that's my combo box..
All the text is being selected on the first match.. I'm scratching my head a bit on this one

Posted: Wed Dec 03, 2003 4:49 pm
by Karbon
Grrrrrrrrrr.. I changed it back to 5,5 (after reading the docs!).. Still getting nothing at all selected in the combo though.. Still bug hunting!
Posted: Wed Dec 03, 2003 5:11 pm
by ebs
Mitch,
If you like, post your code and I'll see if I can figure it out.
Eric
Posted: Wed Dec 03, 2003 6:11 pm
by Karbon
The thing is - I'm using the exact code from the example and callling the procedure in the exact way the example does. My only guess is that something in the callback is messing with that combobox as the only place that gadget is mentioned is in the event handler (when the gadget id gets passed to the autocomplete procedure) and when the gadget is created and populated.
Crazy!
Posted: Wed Dec 03, 2003 7:35 pm
by Karbon
So what was happening was that SetGadgetState() was actually triggering the event on the combo. I'm still totally confused as to why it happens in my project and not in the example but it happens just the same.. I commented out the callback to make sure it wasn't something in there fussing with the combobox and got the same broken result..
If I do this in my event handling loop it works like a charm.. :
Code: Select all
Case #PB_Event_Gadget
Select EventGadgetID()
Case #Gadget_invoice_cmb_customer
If EventType() = 5
AutocompleteComboBox(#Gadget_invoice_cmb_customer)
EndIf
The EventType() that appears to come from SetGadgetState() is type 6, but I'm unable to find anything that might tell me what that means
