Seite 1 von 1

Comboboxgadget mit Gedächtnis

Verfasst: 04.02.2015 10:24
von hjbremer

Code: Alles auswählen

;by HJBremer - Februar 2015 - 2.11, Purebasic 5.31 Windows Vista X86 

DeclareModule ComboBox
   Declare.i ComboBox(pbnr, x, y, w, h, flags = 0)
   Declare.i ComboBox_AddItem(pbnr, text$)
   Declare.i Combobox_LoadItem(pbnr, typ$)
   Declare.i Combobox_SaveItem(pbnr, typ$)   
EndDeclareModule

Module ComboBox     
   EnableExplicit
   
   Structure Comboboxinfo  ;für x86, für x64 ???
      cbSize.i       
      rcItem.RECT
      rcButton.RECT
      stateButton.i
      hwndCombo.i
      hwndEdit.i
      hwndList.i
   EndStructure
   
   Structure Combobox      ;interne Struktur
      pbnr.i
      pbid.i
      group.s
      oldedit.i
      oldlist.i
      oldcombo.i
   EndStructure
      
   Global comboboxfile$ = "Combobox.txt"  ;Filename für Load/Save   
   Global NewList combolist()             ;Liste verwaltet Gadgetdaten
   
   Procedure.i Combobox_SetGroup(pbnr, grp$) 
      Protected *cb.Combobox
      ForEach combolist()
         *cb = combolist()
         If pbnr = *cb\pbnr Or pbnr = #PB_All 
            *cb\group = grp$            
         EndIf  
      Next 
   EndProcedure
      
   Procedure.i ComboBox_AddItem(pbnr, text$)
      Protected pos, id = GadgetID(pbnr)      
      If text$ ;wenn Text, suchen in Liste, wenn nicht gefunden dann Add
         pos = SendMessage_(id, #CB_FINDSTRINGEXACT, -1, @text$)
         If pos = #CB_ERR: SendMessage_(id, #CB_ADDSTRING, 0, @text$): EndIf
      EndIf
   EndProcedure  
   
   Procedure.i Combobox_SaveItem(pbnr, grp$)
      Protected anz, nr
      Protected ok = OpenPreferences(comboboxfile$)      
      If ok = 0: ok = CreatePreferences(comboboxfile$): EndIf      
      If ok
         If grp$       
            RemovePreferenceGroup(grp$)
            PreferenceGroup(grp$)         
            WritePreferenceString(Str(nr), GetGadgetText(pbnr))   ;Nr.0 aus Editfeld
            anz = CountGadgetItems(pbnr)                          ;Anzahl in Liste
            For nr = 1 To anz                                     ;Liste speichern 1-anz
               WritePreferenceString(Str(nr), GetGadgetItemText(pbnr, nr-1))            
            Next          
         EndIf
         ClosePreferences()
      EndIf      
   EndProcedure
   
   Procedure.i Combobox_LoadItem(pbnr, grp$)      
      Protected nr, lg, text$
      Protected ok = OpenPreferences(comboboxfile$)       
      If ok = 0: ok = CreatePreferences(comboboxfile$): EndIf      
      If ok
         PreferenceGroup(grp$)
         text$ = ReadPreferenceString(Str(nr), "")    ;Nr.0 ins Editfeld
         SetGadgetText(pbnr, text$)
         Repeat
            nr + 1
            text$ = ReadPreferenceString(Str(nr), "") ;ab Nr.1 ins Listfeld
            ComboBox_AddItem(pbnr, text$)
         Until text$ = ""
         ClosePreferences()
      EndIf 
      ;wenn Editfeld leer, dann 1.Eintrag aus Liste
      If GetGadgetText(pbnr) = "": SetGadgetState(pbnr, 0): EndIf
      ;wenn immer noch leer, Groupnamen als Banner
      If GetGadgetText(pbnr) = ""  
         lg = StringByteLength(grp$, #PB_Unicode)
         text$ = Space(lg) 
         PokeS(@text$, grp$, Len(text$), #PB_Unicode)
         SendMessage_(GadgetID(pbnr), #CB_SETCUEBANNER, 0, @text$)      
      EndIf 
      ;Groupnamen dem Memblock mitteilen für SaveItem
      Combobox_SetGroup(pbnr, grp$)
   EndProcedure

   Procedure.i ComboBox_CBEdit(hwnd, msg, wParam, lParam)   
      Protected *cb.Combobox = GetWindowLongPtr_(hwnd, #GWL_USERDATA)
      Protected oldwndproc = *cb\oldedit
      
      Select msg      
         Case #WM_KILLFOCUS            
            ;wenn hier, könnte VK_Return entfallen, ich finde es gut.
            ComboBox_AddItem(*cb\pbnr, GetGadgetText(*cb\pbnr))
                                 
         Case #WM_KEYDOWN            
            Select wparam               
               Case #VK_RETURN
                  ComboBox_AddItem(*cb\pbnr, GetGadgetText(*cb\pbnr))
                  SendMessage_(hwnd, #EM_SETSEL, 0, -1)
                  
               Case #WM_CHAR:; Debug "edit #WM_CHAR" + wparam
               ;hier könnte eine Eingabekontrolle sein
               ;z.B. if wparam = 46: wparam = 44: endif                  
            EndSelect     
      EndSelect
      
      ProcedureReturn CallWindowProc_(oldwndproc, hwnd, msg, wParam, lParam)
   EndProcedure 
   
   Procedure.i ComboBox_CBList(hwnd, msg, wParam, lParam) 
      Protected *cb.Combobox = GetWindowLongPtr_(hwnd, #GWL_USERDATA)
      Protected item, oldwndproc = *cb\oldlist      
      Select msg            
         Case #WM_RBUTTONDOWN
            ;entfernt ein Item aus der ComboboxGadget-Listbox 
            item = SendMessage_(hwnd, #LB_GETCURSEL, 0, 0) 
            SendMessage_(hwnd, #LB_DELETESTRING, item, 0) 
            SendMessage_(hwnd, #LB_SETCURSEL, item-1, 0)
      EndSelect
      
      ProcedureReturn CallWindowProc_(oldwndproc, hwnd, msg, wParam, lParam)
   EndProcedure 
   
   Procedure.i ComboBox_CBCombo(hwnd, msg, wParam, lParam) 
      Protected *cb.Combobox = GetWindowLongPtr_(hwnd, #GWL_USERDATA)
      Protected oldwndproc = *cb\oldcombo
      
      Select msg 
         Case #WM_DESTROY                        
            ForEach combolist()
               If *cb = combolist()
                  Combobox_SaveItem(*cb\pbnr, *cb\group)
                  DeleteElement(combolist()): FreeMemory(*cb)
               EndIf
            Next
 
         Case #WM_CTLCOLOREDIT, #WM_CTLCOLORLISTBOX
            SetBkMode_(wParam, #TRANSPARENT)       ;wParam ist das DC
            SetTextColor_(wparam, #Blue)
            ProcedureReturn GetStockObject_(#WHITE_BRUSH)
      EndSelect 
      
      ProcedureReturn CallWindowProc_(oldwndproc, hwnd, msg, wParam, lParam)
   EndProcedure 

   Procedure.i ComboBox(pbnr, x, y, w, h, flags = 0)
      Protected nr, id, cbi.comboboxinfo 
      Protected *cb.Combobox = AllocateMemory(SizeOf(Combobox))
      
      flags | #CBS_SORT      
      If pbnr = #PB_Any
         nr = ComboBoxGadget(#PB_Any, x, y, w, h, flags): id = GadgetID(nr)
      Else
         nr = pbnr: id = ComboBoxGadget(pbnr, x, y, w, h, flags)
      EndIf
      
      cbi\cbSize = SizeOf(comboboxinfo)
      GetComboBoxInfo_(id, cbi)      
      *cb\pbnr = nr
      *cb\pbid = id            
      *cb\oldedit  = SetWindowLongPtr_(cbi\hwndEdit,  #GWL_WNDPROC, @ComboBox_CBEdit())
      *cb\oldlist  = SetWindowLongPtr_(cbi\hwndList,  #GWL_WNDPROC, @ComboBox_CBList())
      *cb\oldcombo = SetWindowLongPtr_(cbi\hwndCombo, #GWL_WNDPROC, @ComboBox_CBCombo())      
      SetWindowLongPtr_(cbi\hwndEdit,  #GWL_USERDATA, *cb)     ;in Userdata speichern
      SetWindowLongPtr_(cbi\hwndList,  #GWL_USERDATA, *cb)     ;in Userdata speichern
      SetWindowLongPtr_(cbi\hwndCombo, #GWL_USERDATA, *cb)     ;in Userdata speichern            
      AddElement(combolist()): combolist() = *cb  
            
      If pbnr = #PB_Any
         ProcedureReturn  nr
      Else
         ProcedureReturn  id
      EndIf      
   EndProcedure
   
EndModule

UseModule ComboBox


 OpenWindow(0, 0, 0, 270, 180, "ComboBox", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
      
   ComboBox(0, 10, 10, 250, 21, #PB_ComboBox_Editable)
   ComboBox(1, 10, 50, 250, 21)
   ComboBox(2, 10, 90, 250, 21, #PB_ComboBox_Editable)
   
   ComboBox_AddItem(1, "keine Ahnung")
   ComboBox_AddItem(1, "uups")
   ComboBox_AddItem(1, "blah")
   
   Combobox_LoadItem(0, "Zahlen")      ;ohne LoadItem, kein Save
   Combobox_LoadItem(1, "Diverses")
   Combobox_LoadItem(2, "Stadtnamen")
   
   
   Repeat
      event = WaitWindowEvent() 
      Select event
         Case #PB_Event_Gadget      
            Select EventGadget()
               Case 0
            EndSelect
      EndSelect
      
   Until event = #PB_Event_CloseWindow

Re: Comboboxgadget mit Gedächtnis

Verfasst: 04.02.2015 10:27
von RSBasic
:allright:

Re: Comboboxgadget mit Gedächtnis

Verfasst: 04.02.2015 11:16
von Josh
Structure Comboboxinfo ;für x86, für x64 ???
Sollte in diesem Fall für x64 ok sein. Verwende einfach "Align #PB_Structure_AlignC", dann bist auf der sicheren Seite.

Re: Comboboxgadget mit Gedächtnis

Verfasst: 04.02.2015 11:26
von ts-soft
:allright:

Die Structure Comboboxinfo sollte so aussehen:

Code: Alles auswählen

   Structure Comboboxinfo  ;für x86, für x64 ???
      cbSize.l       
      rcItem.RECT
      rcButton.RECT
      stateButton.l
      hwndCombo.i
      hwndEdit.i
      hwndList.i
   EndStructure
also cbSize ist ein Long (DWORD), genauso wie stateButton!
Comboboxinfo

PS: #PB_Structure_AlignC hat keinerlei Einfluß auf diese Struktur!

Gruß
Thomas

Re: Comboboxgadget mit Gedächtnis

Verfasst: 04.02.2015 11:27
von Tommy
Cooler Code funktioniert sehr gut danke :allright:
Aber drücke bitte STRG + I und Define event auch nicht vergessen ;)

Re: Comboboxgadget mit Gedächtnis

Verfasst: 04.02.2015 12:26
von Josh
ts-soft hat geschrieben:PS: #PB_Structure_AlignC hat keinerlei Einfluß auf diese Struktur!
#PB_Structure_AlignC hat bei x64 sehr wohl einen Einfluss auf die Struktur. Es hat anscheindend nur keinen Einfluss auf dieses Programm. Die Strukturen mit #PB_Structure_AlignC korrekt auszurichten tut nicht weh und kann böse Fehlersuchen vermeiden.

Re: Comboboxgadget mit Gedächtnis

Verfasst: 04.02.2015 12:38
von ts-soft
@Josh:

Code: Alles auswählen

Structure Comboboxinfo1  ;für x86, für x64 ???
  cbSize.l       
  rcItem.RECT
  rcButton.RECT
  stateButton.l
  hwndCombo.i
  hwndEdit.i
  hwndList.i
EndStructure

Structure Comboboxinfo2 Align #PB_Structure_AlignC
  cbSize.l       
  rcItem.RECT
  rcButton.RECT
  stateButton.l
  hwndCombo.i
  hwndEdit.i
  hwndList.i
EndStructure


Debug OffsetOf(Comboboxinfo1\cbSize)
Debug OffsetOf(Comboboxinfo2\cbSize)

Debug OffsetOf(Comboboxinfo1\hwndList)
Debug OffsetOf(Comboboxinfo2\hwndList)
Ich kann den Einfluß nicht entdecken!

Re: Comboboxgadget mit Gedächtnis

Verfasst: 04.02.2015 13:16
von Josh
Stimmt, mein Versuch war noch mit der Struktur, wo du in deinem Beitrag cbSize bereits auf l geändert hattest und stateButton noch auf i hattest.

Für mich gibt es aber trotzdem keinen Grund, #PB_Structure_AlignC weg zu lassen.