Seite 1 von 1

Autocomplete bei Comboboxen als Callback

Verfasst: 28.03.2006 15:18
von Karl
Hallo,

ich habe mal eine Callback-Prozedur für Autocompletes bei Comboboxen gemalt:

Code: Alles auswählen

;PB 3.94 
;Der Karl
;updated 12.10.2006

#comboTest = 0


Procedure cmbAutoComplete(WindowID, Message, wParam, lParam)
  
  Protected comboWert.s, comboIndex.l, comboLang.l, comboStart.l, parameter.l
  Protected start.l, ende.l
  result = #PB_ProcessPureBasicEvents
  
  
  Select Message
    Case #WM_COMMAND
      Select lParam
        Case GadgetID(0)
          Select (wParam >> 16 & $FFFF)
            Case #CBN_EDITUPDATE
              If GetAsyncKeyState_(#vk_back) Or GetAsyncKeyState_(#vk_delete)
                ;tu nix
              Else
                comboWert = GetGadgetText(#comboTest)
                comboIndex = SendMessage_(lParam, #CB_FINDSTRING, -1, @comboWert)
                comboStart = Len(comboWert)
                ;Länge des eingegebenen Textes
                If comboIndex >= 0 
                  SendMessage_(lParam, #CB_SETCURSEL, comboIndex, 0) 
                  comboLang = Len(GetGadgetText(#comboTest))
                  ;Länge des gefundenen Textes
                  parameter = (comboLang << 16 & $FFFFFFFF) + comboStart
                  SendMessage_(lParam, #CB_SETEDITSEL, 0, parameter)
                EndIf
              EndIf
          EndSelect
      EndSelect
  EndSelect

  ProcedureReturn result
  
EndProcedure

Procedure InitWindow()
  
  ;Window zeichnen und ComboBox aus einer externen Datei füllen (jede Zeile = ein Eintrag)
  
  If OpenWindow(0, 0, 0, 400, 200, #PB_Window_SystemMenu, "Test")
    If CreateMenu(0, WindowID(0))
      MenuTitle("Datei")
      LoadImage(0, "folder_page.bmp")
      LoadImage(1, "printer.bmp")
        MenuItem(0, "Öffnen" + #TAB$ + "STRG+O")
        MenuItem(1, "Schließen")
        SetMenuItemBitmaps_(MenuID(), 0, #MF_BYPOSITION, UseImage(0), UseImage(1)) 
    EndIf
    If CreateGadgetList(WindowID(0))
      ComboBoxGadget(#comboTest, 10, 10, 180, 150, #PB_ComboBox_Editable)
    EndIf
    ReadFile(0, "cmb.txt")
    While ~Eof(0)
      AddGadgetItem(0, -1, ReadString())
    Wend
    CloseFile(0)
  EndIf

EndProcedure


InitWindow()
SetWindowCallback(@cmbAutoComplete())

Repeat
  
Until WaitWindowEvent() = #PB_Event_CloseWindow

End
Die Textdatei kann sich jeder selbst basteln. Viel Spass damit.

Gruß Karl

Re: Autocomplete bei Comboboxen als Callback

Verfasst: 28.03.2006 17:07
von AND51
Karl hat geschrieben:

Code: Alles auswählen

    While ~Eof(0)
ist doch sicher nur ein tippfehler, oder?

Und sry, hab da noch mal eine grundlegende frage zu Callbacks. ich beschäftige mich aufgrund deines Codes erstmalig damit. Sind Callbacks, Proceduren, die von PB imemr zu bestimmten Zwecken/Intervallen aufgerufen werden? ALso zum beispiel beim Packen mit den PB-Befehelen: Da kann man ja auch ein Callback irgendwie... "machen", Sodass man mit hilfe des callbacks also eine Statsuanzeige machen könnte, wie weit der Prozess chon ist.

Versteht mich einer und kann mir sagen, ob ich Callbacks richtig verstehe?

Verfasst: 28.03.2006 17:12
von NicTheQuick
Eine Window-Callback-Procedure wird immer dann aufgerufen, wenn die
Maus auf irgend ein Fenster klickt, sich darüber hinwegbewegt, man das
Fenster minimiert, es verschiebt, die Größe ändert, usw. Übergeben wird
dabei das Handle des Fensters (hwnd), eine Nachricht (uMsg) und zwei
zusätzliche Parameter, die je nach Nachricht ausgewertet werden können.

Für weitere Informationen schau dich mal in dem MSDN um und such z.B.
mal nach "WindowProc".

Verfasst: 28.03.2006 17:44
von Karl

Code: Alles auswählen

While ~Eof(0)
ist kein Schreibfehler, sondern ein NOT auf Bitebene. Ist vielleicht nicht ganz sauber, aber dafür schön kurz.

Der Code wurde auf einem 3.94er System erstellt. PB4 will ich mir erst als finale Version beschaffen.

Der Callback soll die Nachrichten, die von irgendwelchen Gadgets oder anderen Quellen stammen, abfangen und bearbeiten. In diesem Beispiel erzeugt der Eintrag in die Combobox eine WM_COMMAND-Nachricht. Davon kann es aber ein Haufen geben, gerade wenn es mehrere Gadgets gibt. Also fragst du im nächsten Schritt, welches Gadget die Nachricht rausgeschmissen hat (Hier im lParam, der die GadgetID der Combobox enthält). Nun interessiere ich mich aber nur für eine ganz bestimmte Nachricht der Combobox (#CB_EDITUPDATE). Die steht im HI-Word des lParams. Das muss ich erst um 16 Stellen nach rechts verschieben (entspricht teilen durch 2^16) und dann kann ich die Nachricht auswerten (das VerUNDen mit $FFFF dient nur zum sauberen Konvertieren).

Dann beginnt meine eigentliche Manipulation. Ich will den ersten Eintrag haben, der mit dem Eingabetext übereinstimmt. Dazu sende ich die Nachricht #CB_FINDSTRING an die Combobox. Wenn das Ergebnis >= 0 ist, dann gibt es tatsächlich solch einen Eintrag. Dieser soll erstmal in der Box angezeigt werden. Dat dumme ist jetzt, das der gesamte Eintrag markiert wird. Also Mist, wenn mehrere Einträge mit dem gleichen Buchstaben beginnen. Ich ändere die Auswahlmarkierung und lasse nur die Zeichen markieren, die er automatisch hinzugefügt hat (#CB_SETEDITSEL) und bin glücklich.

Wenn du für alle Comboboxen die Autocompletefunktion verwenden willst, dann ignorierst du einfach den lParam und gut ist.

Gruß Karl

Verfasst: 28.03.2006 17:48
von AND51
achso. Ich habe mich schon gewundert, weil doch ~ und e auf der tastatur meilenweit auseinanderliegen...

Verfasst: 28.03.2006 17:56
von Kaeru Gaman
tja... nich alles, was du nit glei raffst, isn tippfehler... :p

Verfasst: 10.09.2006 13:12
von Calloway
Ich habe diesen Code in 3.94 und in angepasster Form auch in 4.0 ausprobiert. Bei beiden Versionen kann ich, solange das Gadget erkannt hat, dass man einen Eintrag aus der Liste eingeben möchte und diesen Eintrag markiert in das gadget schreibt, die Delete- und Backspace-Taste nicht mehr verwenden. Das funktioniert erst wieder, wenn man etwas ins Gadget schreibt, das nicht in der Liste steht. Kann man das noch korrigieren?