MSDN wrote: You can use CLSID_ACLMulti if you want AutoComplete to use multiple lists
Code: Select all
DataSection
CLSID_ACLMulti:
Data.l $00BB2765
Data.w $6A77, $11D0
Data.b $A5, $35, $00, $C0, $4F, $D7, $D0, $62
EndDataSection
MSDN wrote: You can use CLSID_ACLMulti if you want AutoComplete to use multiple lists
Code: Select all
DataSection
CLSID_ACLMulti:
Data.l $00BB2765
Data.w $6A77, $11D0
Data.b $A5, $35, $00, $C0, $4F, $D7, $D0, $62
EndDataSection
Code: Select all
;==================================================================
;
; Library: AutoComplete v. 0.3 alpha
; Author: Lloyd Gallant (netmaestro)
; Date: July 21, 2010
; Target OS: Microsoft Windows All
; Target Compiler: PureBasic 4.50 and later
; license: Free, unrestricted, no warranty whatsoever
; credit appreciated but not required
;
;==================================================================
UseSQLiteDatabase()
#DATABASE_OK = ""
Structure AutoCompleteObject
*vTable
database.i
subclass_oldproc.i
gadget.i
dynamic.b
EndStructure
Interface iAutoCompleteObject
Attach ( gadget, *strings, size )
AddString ( gadget, *string )
Release ()
EndInterface
Procedure AddString(*this.AutoCompleteObject, gadget, *string )
text$ = PeekS(*string)
sql$ = "SELECT promptstring FROM Autocomplete where (promptstring = '"+text$+"' and gadget = '" + Str(gadget) + "')"
DatabaseQuery(*this\database, sql$)
recordcount = 0
While NextDatabaseRow(*this\database)
recordcount+1
Wend
FinishDatabaseQuery(*this\database)
If recordcount = 0
sql$ = "insert into Autocomplete (gadget, promptstring) values(" + Str(gadget) + "," + "'"+ PeekS(*string) + "')"
DatabaseUpdate(*this\database, sql$)
EndIf
ProcedureReturn 1
EndProcedure
Procedure _nmAC_StringProc(hwnd, msg, wparam, lparam)
*this.AutoCompleteObject = GetProp_(hwnd, "acdata")
oldproc = *this\subclass_oldproc
gadget = *this\gadget
Select msg
Case #WM_NCDESTROY
RemoveProp_(hwnd, "oldproc")
Case #WM_KEYUP
If GetFocus_() = hwnd
ClearDebugOutput()
text$ = GetGadgetText(*this\gadget)
If text$ <> ""
sql$ = "SELECT promptstring FROM Autocomplete where (promptstring like '"+text$+"%' and gadget = '" + Str(gadget) + "')"
DatabaseQuery(*this\database, sql$)
While NextDatabaseRow(*this\database)
Debug GetDatabaseString(*this\database,0)
Wend
FinishDatabaseQuery(*this\database)
EndIf
EndIf
Case #WM_KILLFOCUS
If *this\dynamic
text$ = GetGadgetText(gadget)
Addstring(*this, gadget, @text$)
EndIf
Case #WM_SETFOCUS
SendMessage_(hwnd, #EM_SETSEL, 0, -1)
EndSelect
ProcedureReturn CallWindowProc_(oldproc, hwnd, msg, wparam, lparam)
EndProcedure
Procedure Attach(*this.AutoCompleteObject, gadget, *strings, size )
Protected fail_status = #False
*ptr = *strings
For i=1 To size
sql$ = "insert into Autocomplete (gadget, promptstring) values(" + Str(gadget) + "," + "'"+ PeekS(PeekL(*ptr)) + "')"
If DatabaseUpdate(*this\database, sql$)
*ptr+SizeOf(integer)
Else
fail_status = #True
Break
EndIf
Next
If IsGadget(gadget) And GadgetType(gadget) = #PB_GadgetType_String And fail_status = #False
*this\gadget = gadget
*this\subclass_oldproc = SetWindowLongPtr_(GadgetID(gadget), #GWL_WNDPROC, @_nmAC_StringProc())
SetProp_(GadgetID(gadget), "acdata", *this )
Else
fail_status = #True
EndIf
If fail_status = #False
ProcedureReturn #True
Else
ProcedureReturn 0
EndIf
EndProcedure
Procedure NewObject_Autocomplete(dynamic=0)
*newobject.AutoCompleteObject = AllocateMemory(SizeOf(AutoCompleteObject))
With *newobject
\vTable = ?AutoComplete_Methods
\dynamic = dynamic
EndWith
dbOpenResult = OpenDatabase(#PB_Any, ":memory:", "", "")
If dbOpenResult
DatabaseUpdate(dbOpenResult, "CREATE TABLE AutoComplete (gadget VARCHAR, promptstring VARCHAR(255));")
If DatabaseError() = #DATABASE_OK
*newobject\database = dbOpenResult
ProcedureReturn *newobject
Else
ProcedureReturn 0
EndIf
Else
ProcedureReturn 0
EndIf
EndProcedure
Procedure Release(*this.AutoCompleteObject)
If *this\subclass_oldproc
SetWindowLongPtr_(GadgetID(*this\gadget),#GWL_WNDPROC, *this\subclass_oldproc)
EndIf
If IsDatabase(*this\database)
CloseDatabase(*this\database)
EndIf
FreeMemory(*this)
EndProcedure
DataSection
AutoComplete_Methods:
Data.l @Attach(), @AddString(), @Release()
EndDataSection
;=================================================================
; END OF INCLUDE CODESECTION
;=================================================================
; Test prog
Dim Strings.s(17)
Strings(0) = "Else"
Strings(1) = "ElseIf"
Strings(2) = "EnableDebugger"
Strings(3) = "EnableExplicit"
Strings(4) = "End"
Strings(5) = "EndDataSection"
Strings(6) = "EndEnumeration"
Strings(7) = "EndIf"
Strings(8) = "EndImport"
Strings(9) = "EndInterface"
Strings(10) = "EndMacro"
Strings(11) = "EndProcedure"
Strings(12) = "EndSelect"
Strings(13) = "EndStructure"
Strings(14) = "EndStructureUnion"
Strings(15) = "EndWith"
Strings(16) = "Enumeration"
OpenWindow(0,0,0,320,240,"",#PB_Window_ScreenCentered|#PB_Window_SystemMenu)
StringGadget(6, 10,10, 300,20,"")
StringGadget(7, 10,50, 300,20,"")
SetActiveGadget(6)
prompts1.iAutoCompleteObject = NewObject_Autocomplete(1) ; Dynamic additions on
prompts1\Attach(6, @strings(), 17 )
prompts2.iAutoCompleteObject = NewObject_Autocomplete() ; Dynamic additions off - list doesn't change
prompts2\Attach(7, @strings(), 17 )
Repeat : Until WaitWindowEvent() = #PB_Event_CloseWindow
prompts1\Release()
prompts2\Release()
Code: Select all
;
; Generic Implementation of an IEnumString Interface.
; New_EnumString(StringArray(), ItemCount) will create a new IEnumString instance
; with a referencecount of 1. (this means you must call IEnumString\Release()
; to release this reference once you do not need it anymore.)
;
;
;
EnableExplicit
; To allow for the ::Clone() method without dublicating the buffer,
; the string buffer is kept separate, with its own reference count.
Structure EnumStringBuffer
RefCount.l
Strings.l[0]
; following is the literal string data
EndStructure
; IEnumString data
Structure EnumString
*Vtbl
RefCount.l
StringCount.l
Enumerator.l
*Buffer.EnumStringBuffer
EndStructure
Procedure IEnumString_QueryInterface(*THIS.EnumString, *IID.IID, *Object.Integer)
If *Object = 0
ProcedureReturn #E_INVALIDARG
ElseIf CompareMemory(*IID, ?IID_IUnknown, SizeOf(IID)) Or CompareMemory(*IID, ?IID_IEnumString, SizeOf(IID))
*Object\i = *THIS
*THIS\RefCount + 1
ProcedureReturn #S_OK
Else
*Object\i = 0
ProcedureReturn #E_NOINTERFACE
EndIf
EndProcedure
Procedure IEnumString_AddRef(*THIS.EnumString)
*THIS\RefCount + 1
ProcedureReturn *THIS\RefCount
EndProcedure
Procedure IEnumString_Release(*THIS.EnumString)
*THIS\RefCount - 1
If *THIS\RefCount = 0
*THIS\Buffer\RefCount - 1
If *THIS\Buffer\RefCount = 0
FreeMemory(*THIS\Buffer)
EndIf
FreeMemory(*THIS)
ProcedureReturn 0
Else
ProcedureReturn *THIS\RefCount
EndIf
EndProcedure
Procedure IEnumString_Next(*THIS.EnumString, celt, *rgelt.Integer, *pceltFetched.Integer)
Protected count.i, i.i
If *THIS\Enumerator + celt <= *THIS\StringCount
count = celt
Else
count = *THIS\StringCount - *THIS\Enumerator
EndIf
For i = 0 To count-1
*rgelt\i = *THIS\Buffer\Strings[*THIS\Enumerator + i]
*rgelt + 4
Next i
*THIS\Enumerator + count
If *pceltFetched
*pceltFetched\i = count
EndIf
If count = celt
ProcedureReturn #S_OK
Else
ProcedureReturn #S_FALSE
EndIf
EndProcedure
Procedure IEnumString_Skip(*THIS.EnumString, celt)
*THIS\Enumerator + celt
If *THIS\Enumerator <= *THIS\StringCount
ProcedureReturn #S_OK
Else
ProcedureReturn #S_FALSE
EndIf
EndProcedure
Procedure IEnumString_Reset(*THIS.EnumString)
*THIS\Enumerator = 0
ProcedureReturn #S_OK
EndProcedure
Procedure IEnumString_Clone(*THIS.EnumString, *ppenum.Integer)
Protected *Clone.EnumString
If *ppenum = 0
ProcedureReturn #E_INVALIDARG
Else
*Clone = AllocateMemory(SizeOf(EnumString))
If *Clone
CopyMemory(*THIS, *Clone, SizeOf(EnumString))
*Clone\RefCount = 1
*Clone\Buffer\RefCount + 1
*ppenum\i = *Clone
ProcedureReturn #S_OK
Else
*ppenum\i = 0
ProcedureReturn #E_OUTOFMEMORY
EndIf
EndIf
EndProcedure
Procedure New_EnumString(Array StringArray.s(1))
Protected *THIS.EnumString = 0, *StringBuffer.EnumStringBuffer
Protected StringCount.i, Size.i, i.i
Protected *Pointer
StringCount = ArraySize(StringArray())
Size = 4 + StringCount * 4
For i = 0 To StringCount - 1
Size + Len(StringArray(i)) * 2 + 2
Next i
*StringBuffer = AllocateMemory(Size)
If *StringBuffer
*StringBuffer\RefCount = 1
*Pointer = *StringBuffer + 4 + StringCount * 4
For i = 0 To StringCount - 1
*StringBuffer\Strings[i] = *Pointer
PokeS(*Pointer, StringArray(i), -1, #PB_Unicode)
*Pointer + Len(StringArray(i)) * 2 + 2
Next i
*THIS = AllocateMemory(SizeOf(EnumString))
If *THIS
*THIS\Vtbl = ?IEnumStringVtbl
*THIS\RefCount = 1
*THIS\StringCount = StringCount
*THIS\Enumerator = 0
*THIS\Buffer = *StringBuffer
Else
FreeMemory(*StringBuffer)
EndIf
EndIf
ProcedureReturn *THIS
EndProcedure
DataSection
IEnumStringVtbl:
Data.i @IEnumString_QueryInterface()
Data.i @IEnumString_AddRef()
Data.i @IEnumString_Release()
Data.i @IEnumString_Next()
Data.i @IEnumString_Skip()
Data.i @IEnumString_Reset()
Data.i @IEnumString_Clone()
IID_IUnknown: ; {00000000-0000-0000-C000-000000000046}
Data.l $00000000
Data.w $0000, $0000
Data.b $C0, $00, $00, $00, $00, $00, $00, $46
IID_IEnumString: ; {00000101-0000-0000-C000-000000000046}
Data.l $00000101
Data.w $0000, $0000
Data.b $C0, $00, $00, $00, $00, $00, $00, $46
CLSID_AutoComplete: ; {00BB2763-6A77-11D0-A535-00C04FD7D062}
Data.l $00BB2763
Data.w $6A77, $11D0
Data.b $A5, $35, $00, $C0, $4F, $D7, $D0, $62
IID_IAutoComplete: ; {00BB2762-6A77-11D0-A535-00C04FD7D062}
Data.l $00BB2762
Data.w $6A77, $11D0
Data.b $A5, $35, $00, $C0, $4F, $D7, $D0, $62
IID_IAutoComplete2: ; {EAC04BC0-3791-11D2-BB95-0060977B464C}
Data.l $EAC04BC0
Data.w $3791, $11D2
Data.b $BB, $95, $00, $60, $97, $7B, $46, $4C
EndDataSection
#CLSCTX_INPROC_SERVER = $1
#ACO_NONE = 0 ; No autocompletion.
#ACO_AUTOSUGGEST = $1 ; Enable the autosuggest drop-down list.
#ACO_AUTOAPPEND = $2 ; Enable autoappend.
#ACO_SEARCH = $4 ; Add a search item to the dropdown list of completed strings. If this is item is selected, you should launch a search engine to assist the user.
#ACO_FILTERPREFIXES = $8 ; Don't match common prefixes, such as "www.", "http://", and so on.
#ACO_USETAB = $10 ; Use the TAB key to select an item from the drop-down list. This flag is disabled by default.
#ACO_UPDOWNKEYDROPSLIST = $20 ; Use the UP ARROW and DOWN ARROW keys to display the autosuggest drop-down list.
#ACO_RTLREADING = $40 ; If ACO_RTLREADING is set, the text is read in the opposite direction from the text in the parent window.
Code: Select all
IncludeFile "AutoComplete.pbi"
; -----------------------------------------------
#Window_0 = 0
#String_0 = 0
Dim Strings.s(17)
Strings(0) = "Else"
Strings(1) = "ElseIf"
Strings(2) = "EnableDebugger"
Strings(3) = "EnableExplicit"
Strings(4) = "End"
Strings(5) = "EndDataSection"
Strings(6) = "EndEnumeration"
Strings(7) = "EndIf"
Strings(8) = "EndImport"
Strings(9) = "EndInterface"
Strings(10) = "EndMacro"
Strings(11) = "EndProcedure"
Strings(12) = "EndSelect"
Strings(13) = "EndStructure"
Strings(14) = "EndStructureUnion"
Strings(15) = "EndWith"
Strings(16) = "Enumeration"
; Initialize the COM environment
CoInitialize_(0)
Define *AutoComplete.IAutoComplete2, *Enum.IEnumString
If OpenWindow(#Window_0, 323, 219, 600, 300, "AutoComplete", #PB_Window_SystemMenu | #PB_Window_TitleBar | #PB_Window_ScreenCentered )
StringGadget(#String_0, 40, 40, 320, 20, "")
SetActiveGadget(#String_0)
; This creates the autocomplete object:
;
If CoCreateInstance_(?CLSID_AutoComplete, #Null, 1, ?IID_IAutoComplete2, @*AutoComplete) = #S_OK
; Lets change the options for autocomplete a bit:
; See the constant definitions above for the available options.
; There is a dropdown or in-place suggestion mode.
;
*AutoComplete\SetOptions(#ACO_AUTOSUGGEST|#ACO_USETAB)
; This creates the IEnumString interface from our string array:
;
*Enum = New_EnumString(Strings())
; This sets the autocomplet with our Enum object.
; If you want more info on the last 2 parameters, read here:
; http://msdn.microsoft.com/library/default.asp?url=/library/en-us/shellcc/platform/shell/reference/ifaces/iautocomplete/Init.asp
; Note that these must be unicode strings if present!
;
; This also works for Comboboxes, you just need to get the handle to the edit
; control that is contained inside with the GetComboBoxInfo_() function.
;
*AutoComplete\Init(GadgetID(#String_0), *Enum, 0, 0)
Repeat
Until WaitWindowEvent() = #PB_Event_CloseWindow
; Release our own references to the objects to avoid a memory leak
;
*Enum\Release()
*AutoComplete\Release()
EndIf
EndIf