I've been using this revision for my current personal project but I've only updated the combobox part and not the string/editor part. Let me know if there's anything wrong with it and I can update it fairly quickly for you.
Code: Select all
;- Coded by Xombie 12/19/2005, updated 8/18/2006, updated 12/11/2007
;- Structures
Structure s_ACStringStructure
FakeString.s[0]
EndStructure
Structure s_AutoComplete
;
Gadget.l
Handle.l
Parent.l
CallBack.l
; The old callback handle.
ArrayAddress.l
; Only valid for edit controls, this will be the address of the first element in an array of strings.
PopList.b
; Non-zero if displaying a small popup list of matching text. The value is the number of characters to match on. This
; completely changes the behavior of the autocompletion routines. Individual words are matched to a list of words.
ShowDrop.b
;
EndStructure
Structure _s_AutoComplete_Info
;
Gadget.l
;
IdentifierWindow.l
HandleWindow.l
;
IdentifierList.l
HandleList.l
;
CallBack.l
;
EndStructure
;-
EnableExplicit
;- Global Variables
Global NewList _ac_Main.s_AutoComplete()
Global __ac_Info._s_AutoComplete_Info
;-
Procedure _ac_QuickSortArray(Address.l, g.l, d.l)
; Modified from the PureBasic advanced examples.
Define.s v, tmp, t
;
Define.l i, j, ok
;
Define.s_ACStringStructure *Position
; This will be a pointer to the strings in the array.
*Position = Address
;
If g < d
v = *Position\FakeString[d]
i = g-1
j = d
;
Repeat
Repeat : i=i+1 : Until LCase(*Position\FakeString[i]) >= LCase(v)
ok = 0
Repeat
If j>0 : j=j-1 : Else : ok=1 : EndIf
If LCase(*Position\FakeString[j]) <= LCase(v) : ok=1 : EndIf
Until ok<>0
tmp = *Position\FakeString[i]
*Position\FakeString[i] = *Position\FakeString[j]
*Position\FakeString[j] = tmp
Until j <= i
;
t = *Position\FakeString[j]
*Position\FakeString[j] = *Position\FakeString[i]
*Position\FakeString[i] = *Position\FakeString[d]
*Position\FakeString[d] = t
;
_ac_QuickSortArray(Address, g, i-1)
_ac_QuickSortArray(Address, i+1, d)
;
EndIf
;
EndProcedure
Procedure _ac_KillList()
;
If __ac_Info\IdentifierWindow
;
FreeGadget(__ac_Info\IdentifierList)
;
CloseWindow(__ac_Info\IdentifierWindow)
;
__ac_Info\IdentifierWindow = 0
;
__ac_Info\HandleWindow = 0
;
__ac_Info\IdentifierList = 0
;
__ac_Info\HandleList = 0
;
EndIf
;
EndProcedure
Procedure.l _ac_HandleListEvents(HandleWindow.l, Message.l, wParam.l, lParam.l)
;
Define.l lResult
;
Define.l HoldLength
;
Define.s HoldString
;
Define.l *Position
;
Define.l Type
;
Define.CHARRANGE HoldRange
;
Type = GadgetType(_ac_Main()\Gadget)
;
If Message = #WM_LBUTTONDBLCLK
;
HoldString = GetGadgetText(_ac_Main()\Gadget)
; Store the current text.
HoldLength = Len(HoldString)
;
*Position = @HoldString + HoldLength - 1
;
While *Position > @HoldString
;
If PeekB(*Position) < 33 : Break : EndIf
;
*Position - 1
;
Wend
;
If Type = #PB_GadgetType_Editor : SendMessage_(_ac_Main()\Handle, #EM_HIDESELECTION, #True, #Null) : EndIf
;
If PeekB(*Position) < 33
;
If Type = #PB_GadgetType_String
SendMessage_(_ac_Main()\Handle, #EM_SETSEL, *Position - @HoldString + 1, HoldLength)
Else
HoldRange\cpMin = *Position - @HoldString + 1 : HoldRange\cpMax = HoldLength
SendMessage_(_ac_Main()\Handle, #EM_EXSETSEL, *Position - @HoldString + 1, HoldLength)
EndIf
;
Else
;
If Type = #PB_GadgetType_String
SendMessage_(_ac_Main()\Handle, #EM_SETSEL, *Position - @HoldString, HoldLength)
Else
HoldRange\cpMin = *Position - @HoldString : HoldRange\cpMax = HoldLength
SendMessage_(_ac_Main()\Handle, #EM_EXSETSEL, *Position - @HoldString, HoldLength)
EndIf
;
EndIf
;
HoldString = GetGadgetText(__ac_Info\IdentifierList) + " "
;
SendMessage_(_ac_Main()\Handle, #EM_REPLACESEL, #True, @HoldString)
;
If Type = #PB_GadgetType_Editor : SendMessage_(_ac_Main()\Handle, #EM_HIDESELECTION, #False, #Null) : EndIf
;
_ac_KillList()
;
SetActiveGadget(__ac_Info\Gadget)
;
ProcedureReturn 1
;
EndIf
;
lResult = CallWindowProc_(__ac_Info\CallBack, HandleWindow, Message, wParam, lParam)
;
ProcedureReturn lResult
;
EndProcedure
;- Popup Autocomplete
Procedure.l _ac_PopList(HoldComplete.s_AutoComplete(), ItemCount.l, Text.s)
;
Define.l iLoop, jLoop
;
Define.l lResult
;
Define.l Parent
;
Define.l lHold
;
Define.s HoldString, HoldText
;
Define.l HoldLength
;
Define.l HoldHeight
;
Define.l CharacterPosition
;
Define.l *Position
;
Define.l iCount
;
Define.b CaughtMatch
;
Define.POINT HoldPoint
;
Define.s_ACStringStructure *HoldArray
; This will be a pointer to the strings in the array.
HoldLength = Len(Text)
;
*Position = @Text + HoldLength - 1
;
If PeekB(*Position) = 32 : _ac_KillList() : EndIf
; Only autocompleting single words.
While *Position > @Text
;
If PeekB(*Position) < 33 : Break : EndIf
;
*Position - 1
;
Wend
;
If PeekB(*Position) < 33
;
If PeekS(*Position + 1) = ""
;
_ac_KillList()
;
ProcedureReturn
;
EndIf
;
CharacterPosition = *Position - @Text + 2
;
HoldText = LCase(PeekS(*Position + 1))
;
Else
;
If PeekS(*Position) = ""
;
_ac_KillList()
;
ProcedureReturn
;
EndIf
;
CharacterPosition = *Position - @Text
; Subtract one to make zero based.
HoldText = LCase(PeekS(*Position))
;
EndIf
;
HoldLength = Len(HoldText)
;
If HoldLength < HoldComplete()\PopList
;
_ac_KillList()
;
ProcedureReturn
;
EndIf
;
*HoldArray = HoldComplete()\ArrayAddress
;
While iLoop <= ItemCount
; Loop through the list of items.
HoldString = LCase(*HoldArray\FakeString[iLoop])
; Store the text at index iLoop. This little trick of getting the items in a array by addresses is thanks (again) to freak ( http://forums.purebasic.com/english/viewtopic.php?t=15366 )
If HoldText = Left(HoldString, HoldLength)
;
If HoldText = HoldString : CaughtMatch = #True : EndIf
;
HoldHeight + 1
;
If HoldHeight = 5 : Break : EndIf
;
EndIf
;
iLoop + 1
;
Wend
;
If HoldHeight = 0 Or (HoldHeight = 1 And CaughtMatch)
;
_ac_KillList()
;
ProcedureReturn
;
EndIf
;
__ac_Info\Gadget = HoldComplete()\Gadget
;
If __ac_Info\IdentifierWindow
; The popup window already exists.
ClearGadgetItemList(__ac_Info\IdentifierList)
; Remove all current items from the list.
iLoop = 0
;
While iLoop <= ItemCount
; Loop through the list of items.
If HoldText = LCase(Left(*HoldArray\FakeString[iLoop], HoldLength))
; This little trick of getting the items in a array by addresses is thanks (again) to freak ( http://forums.purebasic.com/english/viewtopic.php?t=15366 )
CaughtMatch = #False
;
iCount = CountGadgetItems(__ac_Info\IdentifierList)
For jLoop = 1 To iCount
;
If LCase(*HoldArray\FakeString[iLoop]) = LCase(GetGadgetItemText(__ac_Info\IdentifierList, jLoop - 1, 0)) : CaughtMatch = #True : Break : EndIf
;
Next jLoop
;
If CaughtMatch = #False : AddGadgetItem(__ac_Info\IdentifierList, -1, *HoldArray\FakeString[iLoop]) : EndIf
;
EndIf
;
iLoop + 1
;
Wend
;
ResizeWindow(__ac_Info\IdentifierWindow, #PB_Ignore, #PB_Ignore, #PB_Ignore, (HoldHeight * 14) + 4)
;
ResizeGadget(__ac_Info\IdentifierList, #PB_Ignore, #PB_Ignore, #PB_Ignore, (HoldHeight * 14) + 1)
;
Else
; The popup window does not exist.
lResult = SendMessage_(HoldComplete()\Handle, #EM_POSFROMCHAR, @HoldPoint, CharacterPosition)
;
lHold = GetParent_(HoldComplete()\Handle) : While lHold : Parent = lHold : lHold = GetParent_(lHold) : Wend
; Get the handle to the parent window of the edit control.
lResult = MapWindowPoints_(HoldComplete()\Handle, lHold, @HoldPoint, 1)
; Convert the coordinates to the main window.
__ac_Info\IdentifierWindow = OpenWindow(#PB_Any, 0, 0, 244, (HoldHeight * 14) + 4, "", #PB_Window_WindowCentered | #PB_Window_BorderLess, Parent)
;
If __ac_Info\IdentifierWindow
;
__ac_Info\HandleWindow = WindowID(__ac_Info\IdentifierWindow)
;
If CreateGadgetList(__ac_Info\HandleWindow)
;
__ac_Info\IdentifierList = ListViewGadget(#PB_Any, 2, 2, 240, (HoldHeight * 14) + 1)
;
__ac_Info\HandleList = GadgetID(__ac_Info\IdentifierList)
;
__ac_Info\CallBack = SetWindowLong_(__ac_Info\HandleList, #GWL_WNDPROC, @_ac_HandleListEvents())
;
iLoop = 0
;
While iLoop <= ItemCount
; Loop through the list of items.
If HoldText = LCase(Left(*HoldArray\FakeString[iLoop], HoldLength))
; This little trick of getting the items in a array by addresses is thanks (again) to freak ( http://forums.purebasic.com/english/viewtopic.php?t=15366 )
CaughtMatch = #False
;
iCount = CountGadgetItems(__ac_Info\IdentifierList)
For jLoop = 1 To iCount
;
If LCase(*HoldArray\FakeString[iLoop]) = LCase(GetGadgetItemText(__ac_Info\IdentifierList, jLoop - 1, 0)) : CaughtMatch = #True : Break : EndIf
;
Next jLoop
;
If CaughtMatch = #False : AddGadgetItem(__ac_Info\IdentifierList, -1, *HoldArray\FakeString[iLoop]) : EndIf
;
EndIf
;
iLoop + 1
;
Wend
;
Else
;
ProcedureReturn
;
EndIf
;
Else
;
ProcedureReturn
;
EndIf
;
ResizeWindow(__ac_Info\IdentifierWindow, HoldPoint\X, HoldPoint\Y + 14, #PB_Ignore, #PB_Ignore)
;
EndIf
;
SetGadgetState(__ac_Info\IdentifierList, 0)
;
SetActiveGadget(HoldComplete()\Gadget)
;
EndProcedure
;- Callback Functions
Procedure.l _ac_HandleEditEvents(HandleWindow.l, Message.l, wParam.l, lParam.l)
; Custom callback for edit controls.
Define.l lResult
;
Define.l iLoop
;
Define.l HoldTotal
;
Define.l HoldLength
;
Define.l HoldCombinedLength
;
Define.l HoldStart
;
Define.l HoldEnd
;
Define.CHARRANGE HoldRange
;
Define.s HoldString
;
Define.s CombinedText
;
Define.l *Position
;
Define.s_ACStringStructure *HoldArray
; This will be a pointer to the strings in the array.
Define.l Type
;
ResetList(_ac_Main())
While NextElement(_ac_Main())
;
If _ac_Main()\Handle = HandleWindow : Break : EndIf
;
Wend
;
If _ac_Main()\CallBack = -1 : ProcedureReturn : EndIf
; This should never happen as this callback is only set for autocomplete items.
Type = GadgetType(_ac_Main()\Gadget)
;
HoldTotal = PeekL(_ac_Main()\ArrayAddress - 8)
; Return the number of items in the array.
If HoldTotal = 0
; No need to complete if 0 items.
lResult = CallWindowProc_(_ac_Main()\CallBack, HandleWindow, Message, wParam, lParam)
;
Else
;
*HoldArray = _ac_Main()\ArrayAddress
; Point to the first element in the array.
If Message = #WM_DESTROY
;
SetWindowLong_(GadgetID(_ac_Main()\Gadget), #GWL_WNDPROC, _ac_Main()\CallBack)
;
DeleteElement(_ac_Main())
;
ElseIf Message = #WM_CHAR
;
HoldString = GetGadgetText(_ac_Main()\Gadget)
; Store the current text.
HoldLength = Len(HoldString)
;
If Type = #PB_GadgetType_String
SendMessage_(HandleWindow, #EM_GETSEL, @HoldStart, @HoldEnd)
Else
SendMessage_(HandleWindow, #EM_EXGETSEL, 0, @HoldRange)
HoldStart = HoldRange\cpMin : HoldEnd = HoldRange\cpMax
EndIf
;
If __ac_Info\HandleWindow
;
If wParam = #VK_TAB Or wParam = #VK_RETURN
;
HoldString = ReplaceString(HoldString, Chr(13)+Chr(10), Chr(13))
;
HoldLength = Len(HoldString)
;
*Position = @HoldString + HoldLength - 1
;
While *Position > @HoldString
;
If PeekB(*Position) < 33 : Break : Else : *Position - 1 : EndIf
;
Wend
;
If Type = #PB_GadgetType_Editor : SendMessage_(_ac_Main()\Handle, #EM_HIDESELECTION, #True, #Null) : EndIf
; Temporarily hide the selection of the text. This will prevent a flicker as the text is replaced.
If PeekB(*Position) < 33 : *Position + 1 : EndIf
;
If Type = #PB_GadgetType_String
SendMessage_(_ac_Main()\Handle, #EM_SETSEL, *Position - @HoldString, HoldLength)
Else
HoldRange\cpMin = *Position - @HoldString : HoldRange\cpMax = HoldLength
SendMessage_(_ac_Main()\Handle, #EM_EXSETSEL, 0, @HoldRange)
EndIf
;
HoldString = GetGadgetText(__ac_Info\IdentifierList) + " "
; Add a trailing space to the text.
SendMessage_(_ac_Main()\Handle, #EM_REPLACESEL, #True, @HoldString)
; Replace the text with the completed text.
If Type = #PB_GadgetType_Editor : SendMessage_(_ac_Main()\Handle, #EM_HIDESELECTION, #False, #Null) : EndIf
; Show the selection again.
_ac_KillList()
;
wParam = 0
;
ProcedureReturn 1
;
EndIf
;
EndIf
;
If wParam = #VK_BACK
;
If Type = #PB_GadgetType_Editor
CombinedText = LCase(Mid(HoldString, 1, HoldStart) + Mid(HoldString, HoldEnd + 1, HoldLength - HoldEnd + 1))
Else
CombinedText = LCase(Mid(HoldString, 1, HoldStart - 1) + Mid(HoldString, HoldEnd + 1, HoldLength - HoldEnd + 1))
EndIf
;
Else
;
CombinedText = LCase(Mid(HoldString, 1, HoldStart) + Mid(HoldString, HoldEnd + 1, HoldLength - HoldEnd + 1) + Chr(wParam))
;
EndIf
;
HoldCombinedLength = Len(CombinedText)
;
If HoldCombinedLength = 0
;
SetGadgetText(_ac_Main()\Gadget, "")
;
Else
;
If _ac_Main()\PopList
;
If HoldCombinedLength >= _ac_Main()\PopList
;
_ac_PopList(_ac_Main(), HoldTotal - 1, CombinedText)
;
Else
;
_ac_KillList()
;
EndIf
;
Else
;
For iLoop = 0 To HoldTotal - 1
; Loop through all items in the array.
If LCase(Left(*HoldArray\FakeString[iLoop], HoldCombinedLength)) = CombinedText
; Found a matching item in the combobox. This little trick of getting the items in a array by addresses is thanks (again) to freak ( http://forums.purebasic.com/english/viewtopic.php?t=15366 )
SetGadgetText(_ac_Main()\Gadget, *HoldArray\FakeString[iLoop])
;
If Type = #PB_GadgetType_String
SendMessage_(HandleWindow, #EM_SETSEL, HoldCombinedLength, -1)
Else
HoldRange\cpMin = HoldCombinedLength : HoldRange\cpMax = -1
SendMessage_(HandleWindow, #EM_SETSEL, 0, @HoldRange)
EndIf
;
wParam = 0
;
Break
; Exit the loop.
EndIf
;
Next iLoop
;
EndIf
;
EndIf
;
If wParam : lResult = CallWindowProc_(_ac_Main()\CallBack, HandleWindow, Message, wParam, lParam) : EndIf
;
ElseIf Message = #WM_KEYDOWN
;
If _ac_Main()\PopList And __ac_Info\HandleWindow
;
HoldString = GetGadgetText(_ac_Main()\Gadget)
; Store the current text.
If wParam = #VK_ESCAPE
;
_ac_KillList()
;
wParam = 0
;
ElseIf wParam = #VK_UP
;
HoldTotal = GetGadgetState(__ac_Info\IdentifierList)
;
If HoldTotal - 1 > 0 : HoldTotal - 1 : Else : HoldTotal = 0 : EndIf
;
SetGadgetState(__ac_Info\IdentifierList, HoldTotal)
;
wParam = 0
;
ElseIf wParam = #VK_RETURN
; The code for completion will be handled under the WM_CHAR message.
If __ac_Info\HandleWindow : wParam = 0 : EndIf
;
ElseIf wParam = #VK_RIGHT
;
wParam = 0
;
ElseIf wParam = #VK_DOWN
;
HoldTotal = GetGadgetState(__ac_Info\IdentifierList)
;
If HoldTotal + 1 > CountGadgetItems(__ac_Info\IdentifierList) : HoldTotal = CountGadgetItems(__ac_Info\IdentifierList) : Else : HoldTotal + 1 : EndIf
;
SetGadgetState(__ac_Info\IdentifierList, HoldTotal)
;
wParam = 0
;
ElseIf wParam = #VK_LEFT
;
wParam = 0
;
ElseIf wParam = #VK_HOME
;
SetGadgetState(__ac_Info\IdentifierList, 0)
;
wParam = 0
;
ElseIf wParam = #VK_PRIOR
;
HoldTotal = GetGadgetState(__ac_Info\IdentifierList)
;
If HoldTotal - 5 > 0 : HoldTotal - 5 : Else : HoldTotal = 0 : EndIf
;
SetGadgetState(__ac_Info\IdentifierList, HoldTotal)
;
wParam = 0
;
ElseIf wParam = #VK_NEXT
;
HoldTotal = GetGadgetState(__ac_Info\IdentifierList)
;
If HoldTotal + 5 > CountGadgetItems(__ac_Info\IdentifierList) - 1 : HoldTotal = CountGadgetItems(__ac_Info\IdentifierList) - 1 : Else : HoldTotal + 5 : EndIf
;
SetGadgetState(__ac_Info\IdentifierList, HoldTotal)
;
wParam = 0
;
ElseIf wParam = #VK_END
;
SetGadgetState(__ac_Info\IdentifierList, CountGadgetItems(__ac_Info\IdentifierList) - 1)
;
wParam = 0
;
EndIf
;
SetActiveGadget(_ac_Main()\Gadget)
;
EndIf
;
If wParam : lResult = CallWindowProc_(_ac_Main()\CallBack, HandleWindow, message, wParam, lParam) : EndIf
;
ElseIf message = #WM_KILLFOCUS
;
If wParam <> __ac_Info\HandleWindow
;
_ac_KillList()
;
SendMessage_(_ac_Main()\Handle, #EM_SETSEL, -1, 0)
;
EndIf
;
lResult = CallWindowProc_(_ac_Main()\CallBack, HandleWindow, message, wParam, lParam)
;
Else
;
lResult = CallWindowProc_(_ac_Main()\CallBack, HandleWindow, message, wParam, lParam)
;
EndIf
;
EndIf
;
ProcedureReturn lResult
;
EndProcedure
Procedure.l _ac_HandleComboEvents(HandleWindow.l, Message.l, wParam.l, lParam.l)
; Custom callback for combobox controls.
Define.l lResult
;
Define.l CallBack
;
Define.l Gadget
;
Define.l Parent
;
Define.l iLoop
;
Define.l HoldTotal
;
Define.l HoldLength
;
Define.l HoldCombinedLength
;
Define.l HoldStart
;
Define.l HoldEnd
;
Define.l HoldSelection
;
Define.s HoldString
;
Define.s PreText
;
Define.s PostText
;
Define.s CombinedText
;
Define.s MatchText
;
ResetList(_ac_Main())
While NextElement(_ac_Main())
;
If _ac_Main()\Handle = HandleWindow
;
Parent = _ac_Main()\Parent
;
Gadget = _ac_Main()\Gadget
;
CallBack = _ac_Main()\CallBack
;
Break
;
EndIf
;
Wend
; Retrieve the handle to the combobox and the gadget id.
If CallBack = -1 : ProcedureReturn : EndIf
; This should never happen as this callback is only set for autocomplete items.
If Message = #WM_DESTROY
;
lResult = CallWindowProc_(CallBack, HandleWindow, Message, wParam, lParam)
; Call the next callback handler.
SetWindowLong_(GadgetID(_ac_Main()\Gadget), #GWL_WNDPROC, _ac_Main()\CallBack)
;
DeleteElement(_ac_Main())
;
ElseIf Message = #WM_CHAR
;
HoldTotal = SendMessage_(Parent, #CB_GETCOUNT, 0, 0)
; Return the number of items in the combobox.
If HoldTotal
; Only need to check for autocompletion if items exist in the combobox.
If _ac_Main()\ShowDrop And SendMessage_(GadgetID(Gadget), #CB_GETDROPPEDSTATE, #Null, #Null) = #False : SendMessage_(GadgetID(Gadget), #CB_SHOWDROPDOWN, #True, #Null) : EndIf
;
HoldString = GetGadgetText(Gadget)
; Store the current combobox text.
HoldLength = Len(HoldString)
;
SendMessage_(Parent, #CB_GETEDITSEL, @HoldStart, @HoldEnd)
; Store the start and end selection values.
If wParam = #VK_BACK
;
CombinedText = LCase(Mid(HoldString, 1, HoldStart - 1))
;
Else
;
PreText = Mid(HoldString, 1, HoldStart)
; The text before the selection.
PostText = Mid(HoldString, HoldEnd + 1, HoldLength - HoldEnd)
; The text after the selection.
CombinedText = LCase(PreText + PostText + Chr(wParam))
;
EndIf
;
HoldCombinedLength = Len(CombinedText)
;
If HoldCombinedLength = 0
;
SetGadgetText(Gadget, "")
;
Else
;
For iLoop = 0 To HoldTotal - 1
; Loop through all items in the combo box.
MatchText = GetGadgetItemText(Gadget, iLoop, 0)
; Store the text at index iLoop.
If LCase(Left(MatchText, HoldCombinedLength)) = CombinedText
; Found a matching item in the combobox.
SetGadgetText(Gadget, MatchText)
;
HoldSelection = HoldCombinedLength | -1 << 16
; Convert the start and end selection into an lParam. The start position is the combined length of the pre
; and post text. The end is set to -1 to select the rest of the text.
SendMessage_(GadgetID(Gadget), #CB_SETCURSEL, iLoop, #Null)
;
SendMessage_(Parent, #CB_SETEDITSEL, 0, HoldSelection)
;
wParam = 0
;
; SetGadgetState(Gadget, iLoop)
Break
; Exit the loop.
EndIf
;
Next iLoop
;
EndIf
;
If wParam : lResult = CallWindowProc_(CallBack, HandleWindow, Message, wParam, lParam) : EndIf
;
Else
;
lResult = CallWindowProc_(CallBack, HandleWindow, Message, wParam, lParam)
;
EndIf
;
Else
;
lResult = CallWindowProc_(CallBack, HandleWindow, Message, wParam, lParam)
;
EndIf
;
If lResult : ProcedureReturn lResult : EndIf
;
EndProcedure
;- Main Functions
Procedure ac_SetAutocomplete(Gadget.l, ShowDrop.b = #False, EditGadgetArrayAddress.l = 0, PopList.b = #False)
; EditGadgetArrayAddress is exactly that. The address to the first element of a plain string array. This will be used
; for the autocompletion list. Feel free to modify this to handle linked lists or whatever. It will be ignored for
; combobox. See s_AutoComplete for information on PopList.
Define.l Handle
;
Define.s HoldString
;
Define.l Type
;
ResetList(_ac_Main())
While NextElement(_ac_Main())
If _ac_Main()\Gadget = Gadget : ProcedureReturn : EndIf
Wend
; Check if the gadget already exists in the autocomplete list.
Handle = GadgetID(Gadget)
;
If GadgetType(Gadget) = #PB_GadgetType_Editor Or GadgetType(Gadget) = #PB_GadgetType_String
; String type.
If EditGadgetArrayAddress
; An edit control must be associated with an array address.
AddElement(_ac_Main())
;
_ac_Main()\Gadget = Gadget
_ac_Main()\Handle = Handle
; The handle to the edit control.
_ac_Main()\Parent = 0
; An edit control is not like a combobox. Does not have a parent container.
_ac_Main()\CallBack = SetWindowLong_(Handle, #GWL_WNDPROC, @_ac_HandleEditEvents())
; The callback will be set for the edit control, not the combobox.
_ac_QuickSortArray(EditGadgetArrayAddress, 0, PeekL(EditGadgetArrayAddress - 8))
;
_ac_Main()\ArrayAddress = EditGadgetArrayAddress
;
_ac_Main()\PopList = PopList
;
_ac_Main()\ShowDrop = ShowDrop
;
EndIf
;
ElseIf GadgetType(Gadget) = #PB_GadgetType_ComboBox
; Combobox type
AddElement(_ac_Main())
;
_ac_Main()\Gadget = Gadget
_ac_Main()\Handle = GetWindow_(Handle, #GW_CHILD)
; This is the handle to the edit control within the combobox. I think I got this little tidbit from fr34k but don't quote me on that.
_ac_Main()\Parent = Handle
; This will be the handle to the combobox control.
_ac_Main()\CallBack = SetWindowLong_(_ac_Main()\Handle, #GWL_WNDPROC, @_ac_HandleComboEvents())
; The callback will be set for the edit control, not the combobox.
_ac_Main()\ShowDrop = ShowDrop
;
EndIf
;
EndProcedure
Procedure ac_UpdateArray(Gadget.l, ArrayAddress.l, PopList.b)
;
ResetList(_ac_Main())
While NextElement(_ac_Main())
;
If _ac_Main()\Gadget = Gadget
;
_ac_QuickSortArray(ArrayAddress, 0, PeekL(ArrayAddress - 8))
;
_ac_Main()\ArrayAddress = ArrayAddress
;
_ac_Main()\PopList = PopList
;
Break
;
EndIf
;
Wend
;
EndProcedure