Comboboxgadget mit Gedächtnis

Hier könnt Ihr gute, von Euch geschriebene Codes posten. Sie müssen auf jeden Fall funktionieren und sollten möglichst effizient, elegant und beispielhaft oder einfach nur cool sein.
Benutzeravatar
hjbremer
Beiträge: 822
Registriert: 27.02.2006 22:30
Computerausstattung: von gestern
Wohnort: Neumünster

Comboboxgadget mit Gedächtnis

Beitrag 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
Purebasic 5.70 x86 5.72 X 64 - Windows 10

Der Computer hat dem menschlichen Gehirn gegenüber nur einen Vorteil: Er wird benutzt
grüße hjbremer
Benutzeravatar
RSBasic
Admin
Beiträge: 8047
Registriert: 05.10.2006 18:55
Wohnort: Gernsbach
Kontaktdaten:

Re: Comboboxgadget mit Gedächtnis

Beitrag von RSBasic »

:allright:
Aus privaten Gründen habe ich leider nicht mehr so viel Zeit wie früher. Bitte habt Verständnis dafür.
Bild
Bild
Benutzeravatar
Josh
Beiträge: 1028
Registriert: 04.08.2009 17:24

Re: Comboboxgadget mit Gedächtnis

Beitrag 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.
Benutzeravatar
ts-soft
Beiträge: 22292
Registriert: 08.09.2004 00:57
Computerausstattung: Mainboard: MSI 970A-G43
CPU: AMD FX-6300 Six-Core Processor
GraKa: GeForce GTX 750 Ti, 2 GB
Memory: 16 GB DDR3-1600 - Dual Channel
Wohnort: Berlin

Re: Comboboxgadget mit Gedächtnis

Beitrag 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
Zuletzt geändert von ts-soft am 04.02.2015 11:47, insgesamt 3-mal geändert.
PureBasic 5.73 LTS | SpiderBasic 2.30 | Windows 10 Pro (x64) | Linux Mint 20.1 (x64)
Nutella hat nur sehr wenig Vitamine. Deswegen muss man davon relativ viel essen.
Bild
Benutzeravatar
Tommy
Spassvogel
Beiträge: 319
Registriert: 17.10.2013 14:36

Re: Comboboxgadget mit Gedächtnis

Beitrag von Tommy »

Cooler Code funktioniert sehr gut danke :allright:
Aber drücke bitte STRG + I und Define event auch nicht vergessen ;)
PB 5.41 x64
Benutzeravatar
Josh
Beiträge: 1028
Registriert: 04.08.2009 17:24

Re: Comboboxgadget mit Gedächtnis

Beitrag 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.
Benutzeravatar
ts-soft
Beiträge: 22292
Registriert: 08.09.2004 00:57
Computerausstattung: Mainboard: MSI 970A-G43
CPU: AMD FX-6300 Six-Core Processor
GraKa: GeForce GTX 750 Ti, 2 GB
Memory: 16 GB DDR3-1600 - Dual Channel
Wohnort: Berlin

Re: Comboboxgadget mit Gedächtnis

Beitrag 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!
PureBasic 5.73 LTS | SpiderBasic 2.30 | Windows 10 Pro (x64) | Linux Mint 20.1 (x64)
Nutella hat nur sehr wenig Vitamine. Deswegen muss man davon relativ viel essen.
Bild
Benutzeravatar
Josh
Beiträge: 1028
Registriert: 04.08.2009 17:24

Re: Comboboxgadget mit Gedächtnis

Beitrag 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.
Antworten