Seite 1 von 1

CheckedListBox

Verfasst: 18.11.2025 20:38
von techniker
Hallo,

Ich benötige für die Mehrfachauswahl eine Kombination von ComboBox und CheckedList aufgrund Platzmangel im GUI.
Wie kann ich dies unter Windows am "einfachsten" bewerkstelligen? Gerne auch mit WinAPI.

Hat jemand einen kurzen Beispielcode für mich, den ich als Denkanstoß nutzen kann? :mrgreen:

PS: Hier ein Beispielbild, von dem was ich bräuchte: https://cdn.mescius.io/assets/developer ... istbox.png

Re: CheckedListBox

Verfasst: 19.11.2025 11:54
von Axolotl
Dem Bild am nächsten käme wohl ein ListIconGadget ohne ColumnHeader.
Das ganze in ein Window mit Borderless|Invisilbe packen.
Habe (leider) gerade keinen Code zur Hand und das Forum ist sehr*4 langsam.

Alternative wäre natürlich auch ein PopUpMenu.
Allerdings würde bei jedem (Un)Check das Menu schließen.....
Und sieht nicht so schön aus, Je nach Anforderung.

Re: CheckedListBox

Verfasst: 19.11.2025 12:10
von Axolotl
Okay, jetzt habe ich in meinem Archive noch was gefunden und angepasst.....
Als Start ganz gut geeignet ....
Aber sieh selbst.

Code: Alles auswählen

; Written by Axolotl 
;
EnableExplicit 

Procedure WndFly_PerformCallbackProc(hWnd, uMsg, wParam, lParam) 
  Select uMsg 
    Case #WM_NCDESTROY 
Debug "WM_NCDESTROY  " 
      RemoveProp_(hWnd, "Gadget") 

    Case #WM_ACTIVATE 
      ; user clicked outside the window / listbox 
      ; 
      If wParam = #WA_INACTIVE                        : Debug "WM_ACTIVATE, WA_INACTIVE, hide the fly window now " 
        ShowWindow_(hWnd, #SW_HIDE)   ; use handle instead 
        ;; HideWindow(#WND_FlyOver, 1) 
      EndIf 

    Case #WM_CHAR                 : Debug "WM_CHAR  '" + wParam + "'" 
    Case #WM_KEYDOWN            ; : Debug "WM_KEYDOWN " 
      Select wParam 
        Case #VK_ESCAPE         : Debug "WM_KEYDOWN  ESCAPE " 
        Case #VK_RETURN         : Debug "WM_KEYDOWN  RETUEN " 
      EndSelect 

    Case #WM_COMMAND 
      Select ((wParam >> 16) & $FFFF) 
        Case #EN_CHANGE  
          ; ?? editor changed 
        Case #LBN_SELCANCEL         : Debug "WM_COMMAND, LBN_SELCANCEL, " 
          ; ?? listbox selection ?? 
          Debug "  State == " + GetGadgetState(GetProp_(hwnd, "Gadget")) 
          SendMessage_(hwnd, #WM_CLOSE, 0, 0) 
      EndSelect 

;     If ((wParam >> 16) & $FFFF) = #LBN_SELCANCEL 
; Debug "WM_COMMAND, LBN_SELCANCEL, ?? " 
;     EndIf 

;   Default  
;Debug "Default  -> uMsg = " + uMsg 
  EndSelect 

  ProcedureReturn #PB_ProcessPureBasicEvents 
EndProcedure 

; --- 

Procedure WndFly_Create(Window, Width=200, Height=200) 
  Protected oldGadgetList 
  Protected ii, wnd, gdt 

  wnd = OpenWindow(Window, 0, 0, Width, Height, "", #PB_Window_Invisible | #PB_Window_BorderLess) 
  If wnd 
    If Window = #PB_Any 
      Window = wnd              ; now Window is a correct number 
      wnd = WindowID(Window)    ; and wnd is the handle 
    EndIf 

    StickyWindow(Window, 1)   ; because main window is also sticky 
    oldGadgetList = UseGadgetList(wnd)  ; Create GadgetList and store old GadgetList

    gdt = ListIconGadget(#PB_Any, 0, 0, Width, Height, "", Width-24, #PB_ListIcon_CheckBoxes|#LVS_NOCOLUMNHEADER) 
    If gdt ; valid gadget number 

      For ii = 1 To 4 
        AddGadgetItem(gdt, -1, "Item "+Str(ii)) 
      Next ii 

      SetProp_(wnd, "Gadget", gdt) 
      SetWindowCallback(@WndFly_PerformCallbackProc(), Window) 
      UseGadgetList(oldGadgetList)             ; return to previous GadgetList 
      ProcedureReturn #True 
    Else 
      ; strange error ..... 
      CloseWindow(Window) 
    EndIf 
  EndIf 
  ProcedureReturn #False 
EndProcedure 

; ---

Procedure WndFly_ShowForGadget(Window, TargetGadget) 
  Protected gdt, x, y, w 
  
  If IsWindow(Window) 
    gdt = GetProp_(WindowID(Window), "Gadget") 

    ; get pos and width of TargetGadget to place the window below ..... 
    x = GadgetX(TargetGadget, #PB_Gadget_ScreenCoordinate)
    y = GadgetY(TargetGadget, #PB_Gadget_ScreenCoordinate) + GadgetHeight(TargetGadget) 
    w = GadgetWidth(TargetGadget) 

    ; adjust the window size ??? 
    ResizeWindow(Window, x, y, w, #PB_Ignore)                 ; pos and width of the window 
    ResizeGadget(gdt, #PB_Ignore, #PB_Ignore, w, #PB_Ignore)  ; adjust the gadget width to the window width 
    SetGadgetItemAttribute(gdt, #PB_Ignore, #PB_ListIcon_ColumnWidth, w-24, 0)  ; adjust the gadget width to the window width 

    HideWindow(Window, 0)  ; show now 
    SetActiveGadget(gdt) 
    ProcedureReturn #True 
  EndIf 
  ProcedureReturn #False 
EndProcedure 

; --- 

If OpenWindow(0, 0, 0, 300, 80, "Test ", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
  ButtonGadget(0, 0, 20, 200, 20, "Click")
  TextGadget(1, 0, 0, 200, 20, "Click here on the Button below .... ")

  WndFly_Create(1, 400, 200) 
 
; WndFly_Fill(0, Items$()) 
  Repeat
    Select WaitWindowEvent() 
      Case #PB_Event_CloseWindow 
        Break 

      Case #PB_Event_Gadget 
        Select EventGadget() 
          Case 0 
            WndFly_ShowForGadget(1, 0) 
        EndSelect 
    EndSelect 
  ForEver 
EndIf

Re: CheckedListBox

Verfasst: 19.11.2025 12:36
von Axolotl
So, und das ganze ohne API....
Dafür mit ein paar Coding-Style-Elementen, die ich bevorzuge.....

Code: Alles auswählen

; written by Axolotl -- no API 
;
EnableExplicit 

Enumeration EWindow 1
  #WND_Main 
  #WND_Selection  
EndEnumeration 

Enumeration EGadget 1
  ; WND_Main Gadgets 
  #GDT_txtInfo 
  #GDT_btnClick 

  ; WND_Selection Gadgets  
  #GDT_Selection_lstItems 

  ; WND_<Next Window> Gadgets  

EndEnumeration 

; --- 

Procedure WndFly_Create(Width=200, Height=200) 
  Protected ii, oldGadgetList 

  If OpenWindow(#WND_Selection, 0, 0, Width, Height, "", #PB_Window_Invisible | #PB_Window_BorderLess) 
    StickyWindow(#WND_Selection, 1)   ; because on top of main window 
    oldGadgetList = UseGadgetList(WindowID(#WND_Selection))  ; Create GadgetList and store old GadgetList

    ListIconGadget(#GDT_Selection_lstItems, 0, 0, Width, Height, "", Width-24, #PB_ListIcon_CheckBoxes|#PB_ListIcon_NoHeaders) 
    ; in older PBs 
    ; replace #PB_ListIcon_NoHeaders => #LVS_NOCOLUMNHEADER 

    For ii = 1 To 4 
      AddGadgetItem(#GDT_Selection_lstItems, -1, "Item "+Str(ii)) 
    Next ii 
    UseGadgetList(oldGadgetList)             ; return to previous GadgetList 
    ProcedureReturn #True 
  EndIf 
  ProcedureReturn #False 
EndProcedure 

; ---

Procedure WndFly_ShowForGadget(TargetGadget) 
  Protected gdt, x, y, w 
  
  If IsWindow(#WND_Selection) 
    ; get pos and width of TargetGadget to place the window below ..... 
    x = GadgetX(TargetGadget, #PB_Gadget_ScreenCoordinate)
    y = GadgetY(TargetGadget, #PB_Gadget_ScreenCoordinate) + GadgetHeight(TargetGadget) 
    w = GadgetWidth(TargetGadget) 

    ; adjust the window size ??? 
    ResizeWindow(#WND_Selection, x, y, w, #PB_Ignore) 
    ResizeGadget(#GDT_Selection_lstItems, #PB_Ignore, #PB_Ignore, w, #PB_Ignore) 
    SetGadgetItemAttribute(#GDT_Selection_lstItems, #PB_Ignore, #PB_ListIcon_ColumnWidth, w-24, 0) 

    HideWindow(#WND_Selection, 0)  ; show now 
    SetActiveGadget(#GDT_Selection_lstItems) 
    ProcedureReturn #True 
  EndIf 
  ProcedureReturn #False 
EndProcedure 

; --- 

If OpenWindow(#WND_Main, 0, 0, 300, 80, "Test ", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
  TextGadget(#GDT_txtInfo, 0, 0, 200, 20, "Click here on the Button below .... ")
  ButtonGadget(#GDT_btnClick, 0, 20, 200, 20, "Click")

  WndFly_Create(400, 200) 
 
  Repeat
    Select WaitWindowEvent() 
      Case #PB_Event_CloseWindow 
        Break 

      Case #PB_Event_DeactivateWindow 
        Select EventWindow()  ; <= important ... huge difference betwwen EventWindow() and WindowEvent() !!! 
          Case #WND_Selection 
            HideWindow(#WND_Selection, 1) 
            SetActiveWindow(#WND_Main) 
        EndSelect

      Case #PB_Event_Gadget 
        Select EventGadget() 
          Case #GDT_btnClick 
            WndFly_ShowForGadget(#GDT_btnClick) 
        EndSelect 
    EndSelect 
  ForEver 
EndIf

Re: CheckedListBox

Verfasst: 19.11.2025 16:31
von jogo
hab aus Neugier das Beispiel ohne API getestet. Funktioniert gut.
Mein Compiler meckert über Zeile 31: Konstante #PB_ListIcon_NoHeaders ist nicht vorhanden.
Nachdem ich die Option mit #PB_ListIcon_NoHeaders entfernt hatte, lief alles - ist natürlich jetzt eine leere Kopfzeile vorhanden, die (aus meiner Sicht) nicht stört.
In der Hilfe habe ich diese Konstante allerdings auch nicht gefunden, weil ich anfangs vermutete, dass dies an Linux liegen könnte.

Ich habe mal so was ähnliches gebaut - also viele Checkboxen in einen kleinen Fenster. Gelöst habe ich dies mit ScrollAreaGadget(). Das klappt natürlich nicht so schön auf & zu. Hab das seitlich als scrollbare Leiste platziert.

Warum ist das Forum so langsam?

Re: CheckedListBox

Verfasst: 19.11.2025 16:43
von techniker
Danke Axolotl für den Denkanstoß! :-)
Die API-Variante gefällt mir sehr gut und kann diese perfekt integrieren..

Re: CheckedListBox

Verfasst: 19.11.2025 17:30
von Axolotl
jogo hat geschrieben: 19.11.2025 16:31 ...
Mein Compiler meckert über Zeile 31: Konstante #PB_ListIcon_NoHeaders ist nicht vorhanden.
....
ich hatte ja extra einen Kommentar eingefügt.
Die Konstante kommt mit 6.30 (u.höher) -> Einfach durch die ApI Konstante ersetzen.
Oder folgenden Code am Anfang des Beispiels ergänzen..

Code: Alles auswählen

CompilerIf Not Defined(PB_ListIcon_NoHeaders, #PB_Constant) And #PB_Compiler_OS = #PB_OS_Windows 
  #PB_ListIcon_NoHeaders = #LVS_NOCOLUMNHEADER  
CompilerEndIf 
jogo hat geschrieben: 19.11.2025 16:31 ....
Warum ist das Forum so langsam?
Warscheinlich müssen die AI Bots wieder was lernen?

Info: Ich habe eine noch bessere Variante gebaut, für meine eigenen Zwecke.
CheckboxList Window [Win Only]