Auto-Complete for combo-box

Share your advanced PureBasic knowledge/code with the community.
BackupUser
PureBasic Guru
PureBasic Guru
Posts: 16777133
Joined: Tue Apr 22, 2003 7:42 pm

Auto-Complete for combo-box

Post by BackupUser »

Code updated for 5.20+

Restored from previous forum. Originally posted by Fangbeast.

Danilo posted this great bit of code for me for using the comboboxgadget as a pseudo auto-complete mechanism and he also did one for string gadget (sometimes I need a kick to think properly) which I modified after this.

Code: Select all

Global hCombo, hComboEdit, hList, pt.POINT
Global oldComboEditProc, ListHidden
;
Procedure CheckContents(A$)
  If UCase(Left(A$,4)) = "FANG" ;And Len(A$) = 4
    HideGadget(2,0): ListHidden = 0
  Else
    HideGadget(2,1): ListHidden = 1
  EndIf
EndProcedure
;
Procedure ComboKey(Window,Message,wParam,lParam)
  If Message = #WM_KEYDOWN And wParam = #VK_DOWN And ListHidden = 0
    SetFocus_(hList): SetGadgetState(2,0)
  EndIf
  Result = CallWindowProc_(oldComboEditProc,Window,Message,wParam,lParam)
  ProcedureReturn Result
EndProcedure
;
Procedure WindowCallback(Window,Message,wParam,lParam)
  Result = #PB_ProcessPureBasicEvents
  Select Window
    Case WindowID(1)
      Select Message
        Case #WM_COMMAND
          If lParam = hCombo And (wParam >> 16) = #CBN_EDITCHANGE
            A$=Space(1000) : GetWindowText_(hCombo,A$,1000)
            CheckContents(A$)
          EndIf
      EndSelect
  EndSelect
  ProcedureReturn Result
EndProcedure

;- main
OpenWindow(1,200,200,400,200,"",#PB_Window_SystemMenu)

hCombo = ComboBoxGadget(1,10,10,300,22,#PB_ComboBox_Editable)
hList  = ListViewGadget(2,20,31,280,100)

HideGadget(2,1): ListHidden = 1

For a = 1 To 9: AddGadgetItem(2, -1,"FangBeast "+ Str(a)): Next a

AddKeyboardShortcut(1,#PB_Shortcut_Return,100)
AddKeyboardShortcut(1,#PB_Shortcut_Up    ,101)

;
SetWindowCallback(@WindowCallback())

pt\x = 5
pt\y = 5

hComboEdit = ChildWindowFromPoint_(hCombo,pt)
oldComboEditProc = SetWindowLong_(hComboEdit,#GWL_WNDPROC,@ComboKey())
;
Repeat
  Select WaitWindowEvent()
    Case #PB_Event_CloseWindow: End
    Case #PB_Event_Menu
      If EventMenu() = 100 And GetFocus_() = hList
        SetWindowText_(hCombo,GetGadgetItemText(2,GetGadgetState(2),0))
        HideGadget(2,1): ListHidden = 1
        SetFocus_(hComboEdit): SendMessage_(hComboEdit,#EM_SETSEL,$FFFFFFFF,$FFFFFFFF)
        SetGadgetState(2,0)
      ElseIf EventMenu() = 101 And GetFocus_() = hList
        If GetGadgetState(2) = 0
          SetGadgetState(2,-1)
          SetFocus_(hComboEdit): SendMessage_(hComboEdit,#EM_SETSEL,$FFFFFFFF,$FFFFFFFF)
        Else
          SetGadgetState(2,GetGadgetState(2)-1)
        EndIf
      EndIf
    Case #PB_Event_Gadget
  EndSelect
ForEver
Danilo's comments: "Just Type "Fang" in the ComboBox to see whats happening..."

The below routine is what he posted for stringgadget and I've modified it to allow me to press RETURN or ESCAPE in the stringgadget when I don't want any matches to occur. I also load an external list into a structure to generate the matches from (I was just testing the matching process)

Code: Select all

Structure _bla
  junk.s
EndStructure

NewList stuff._bla()

#stringy = 1
#listy = 2

#return = 100
#up = 101
#escape = 102

Declare StringKey(Window, Message, wParam, lParam)

Global hString,  hComboEdit,  hList
Global oldStringGadgetProc,  ListHidden
;--------------------------------------------------------------------------------------------------
Procedure StringKey(Window, Message, wParam, lParam)
  
  If Message = #WM_KEYDOWN And wParam = #VK_DOWN And ListHidden = 0
    SetFocus_(hList)
    SetGadgetState(#listy, 0)
  EndIf
  
  Result = CallWindowProc_(oldStringGadgetProc, Window, Message, wParam, lParam)
  
  ProcedureReturn Result
  
EndProcedure
;--------------------------------------------------------------------------------------------------
OpenWindow(1, 200, 200, 400, 200, "", #PB_Window_SystemMenu)

hString = StringGadget(#stringy, 10, 10, 300, 20, "")
hList   = ListViewGadget(#listy, 10, 31, 300, 100)
HideGadget(#listy, 1)
ListHidden = 1

AddKeyboardShortcut(1, #PB_Shortcut_Return, #return)
AddKeyboardShortcut(1, #PB_Shortcut_Up    , #up)
AddKeyboardShortcut(1, #PB_Shortcut_Escape, #escape)

If OpenFile(0, "C:\junk.txt") <> 0
  While Eof(0) = 0
    AddElement(stuff())
    stuff()\junk = ReadString(0)
  Wend
  CloseFile(0)
Else
  MessageRequester("File Open Error", "File missing?", #PB_MessageRequester_Ok)
EndIf



oldStringGadgetProc = SetWindowLong_(hString, #GWL_WNDPROC, @StringKey())

Repeat
  Select WaitWindowEvent()
    Case #PB_Event_CloseWindow
      End
    Case #PB_Event_Menu
      If EventMenu() = #return And GetFocus_() = hList
        SetGadgetText(#stringy, GetGadgetItemText(#listy, GetGadgetState(#listy), 0))
        HideGadget(#listy, 1)
        ListHidden = 1
        SetGadgetState(#listy, - 1)
        SetFocus_(hString)
        SendMessage_(hString, #WM_KEYDOWN, #VK_END, 0)
      ElseIf EventMenu() = #up And GetFocus_() = hList
        If GetGadgetState(#listy) = 0
          SetGadgetState(#listy, - 1)
          SetFocus_(hString)
          SendMessage_(hString, #EM_SETSEL, $FFFFFFFF, $FFFFFFFF)
        Else
          SetGadgetState(#listy, GetGadgetState(#listy) - 1)
        EndIf
      ElseIf EventMenu() = #escape And GetFocus_() = hString
        If GetGadgetState(#listy) = - 1
          RemoveGadgetItem(#listy, 0)
          HideGadget(#listy, 1)
          ListHidden = 1
        EndIf
      ElseIf EventMenu() = #return And GetFocus_() = hString
        If GetGadgetState(#listy) = - 1
          RemoveGadgetItem(#listy, 0)
          HideGadget(#listy, 1)
          ListHidden = 1
        EndIf
      EndIf
    Case #PB_Event_Gadget
      If EventGadget() = #stringy And EventType() = #PB_EventType_Change
        A$ = GetGadgetText(#stringy)
        ResetList(stuff())
        RemoveGadgetItem(#listy, 0)
        HideGadget(#listy, 0)
        ListHidden = 0
        alen = Len(A$)
        
        While NextElement(stuff())
          If UCase(Left(A$, alen)) = UCase(Left(stuff()\junk, alen))
            If stuff()\junk <> "" And A$ <> ""
              AddGadgetItem(#listy, - 1, stuff()\junk)
            EndIf
          EndIf
        Wend
        
      EndIf
  EndSelect
  
ForEver
Hope this helps someone, it certainly did help me. If I can streamline the process somehow, I will repost an example doing this for 20 gadgets on a data entry form.

Thanks Danilo!

Fangles woz ear orright den?
Last edited by fsw on Thu Aug 22, 2013 6:10 pm, edited 2 times in total.
Reason: Code updated for 5.20+