Fehler bei erweiterten Gadgets...

Anfängerfragen zum Programmieren mit PureBasic.
Benutzeravatar
Ghosty1967
Beiträge: 205
Registriert: 29.08.2005 13:56
Computerausstattung: Intel i7, 128GB Ram, Win10 Ultimate, PB6.00 Alpha 3
Wohnort: Köln

Fehler bei erweiterten Gadgets...

Beitrag von Ghosty1967 »

Hallo zusammen,
wenn ich für meine Projekte eigene GUIs erstelle, hat es mich immer genervt, für jedes Gadget (falls benötigt) die Text- und Hintergrundfarbe,
sowie den Zeichensatz usw... einzeln zu setzen.
Also habe ich mir meine eigenen "Erweiterungen" der bekannten Gadgets gebastelt wie z.B. unten im Beispielcode zu sehen. Das funktioniert
eigentlich immer ganz gut, habe aber jetzt feststellen müssen, das es vereinzelt Probleme gibt, wenn ich für die ID keinen festen Wert sondern
#PB_Any übergebe (siehe Beispielcode).
Woran liegt das eigentlich und kann man den Teil innerhalb der Prozeduren wo das Gadget erstellt wir...

Code: Alles auswählen

If Gadget = #PB_Any
  Gadget = CheckBoxGadget(#PB_Any, x, y, width, height, Text$, Flags)
Else
  CheckBoxGadget(Gadget, x, y, width, height, Text$, Flags)
EndIf
besser bzw. anders gestalten?


Hier ein kleiner Beispielcode um den "Fehler" aufzuzeigen :shock:

Code: Alles auswählen

Enumeration
  #WIN_INTERFACE
  #TXT_TEXTGADGET
  #CHK_CHECKBOX
  #FNT_TAHOMA
EndEnumeration

Procedure CheckGadgetEx_(Gadget.l, x.l, y.l, width.l, height.l, Text$, Font=#PB_Ignore, Status.l=#False, Flags=0)
  ;Font       = Zu verwendender Zeichensatz kann angegeben werden, sonst Systemfont
  ;Status     = Check/Uncheck kann gesetzt werden 
  If Gadget = #PB_Any
    Gadget = CheckBoxGadget(#PB_Any, x, y, width, height, Text$, Flags)
  Else
    CheckBoxGadget(Gadget, x, y, width, height, Text$, Flags)
  EndIf
  If IsGadget(Gadget)
    If Font <> #PB_Ignore And IsFont(Font): SetGadgetFont(Gadget, FontID(Font))    : EndIf
    SetGadgetState(Gadget, Status)
    ProcedureReturn Gadget
  EndIf
EndProcedure

Procedure TextGadgetEx_(Gadget, x, y, width, height, Text$="", TextColor=#PB_Ignore, BackColor=#PB_Ignore, Font=#PB_Ignore, Flags=0)
  ;TextColor  = Zu verwendende Textfarbe innerhalb des Gadgets
  ;BackColor  = Zu verwendende Hintergrundfarbe innerhalb des Gadgets
  ;Font       = Zu verwendender Zeichensatz kann angegeben werden, sonst Systemfont
  ;Status     = Check/Uncheck kann gesetzt werden 
  If Gadget = #PB_Any
    Gadget = TextGadget(#PB_Any, x, y, width, height, Text$, Flags)
  Else  
    TextGadget(Gadget, x, y, width, height, Text$, Flags)
  EndIf
  If IsGadget(Gadget)
    If TextColor <> #PB_Ignore: SetGadgetColor(Gadget, #PB_Gadget_FrontColor, TextColor): EndIf
    If BackColor <> #PB_Ignore: SetGadgetColor(Gadget, #PB_Gadget_BackColor , BackColor): EndIf
    If Font      <> #PB_Ignore And IsFont(Font): SetGadgetFont(Gadget, FontID(Font))    : EndIf
    ProcedureReturn Gadget
  EndIf
EndProcedure

If OpenWindow(#WIN_INTERFACE,   0,   0, 240, 100, "WindowTitle", #PB_Window_SystemMenu|#PB_Window_ScreenCentered)
  LoadFont(#FNT_TAHOMA, "Tahoma", 12)
  TextGadgetEx_ (#TXT_TEXTGADGET,  10,  10, 100,  18, "TextGadget", $000000FF, $FFFFFFFF, #FNT_TAHOMA, #PB_Text_Center)
  TextGadgetEx_ (#PB_Any        ,  10,  30, 100,  18, "TextGadget", $000000FF, $FFFFFFFF, #FNT_TAHOMA, #PB_Text_Center)
  CheckGadgetEx_(#CHK_CHECKBOX  , 120,  10, 100,  18, "Checkbox"  , #FNT_TAHOMA, #True)
  CheckGadgetEx_(#PB_Any        , 120,  30, 100,  18, "Checkbox"  , #FNT_TAHOMA, #True)
  Repeat: Until WaitWindowEvent() = #PB_Event_CloseWindow 
EndIf
berie
Beiträge: 75
Registriert: 17.01.2018 08:52
Computerausstattung: Windows 11 64 bit, i7, 16GB RAM
Wohnort: Wesertal in Nordhessen

Re: Fehler bei erweiterten Gadgets...

Beitrag von berie »

Habe mal folgendes probiert:

Code: Alles auswählen

For x=1 To 10
  Debug #PB_Any
Next
#PB_Any ist jedesmal -1.
Könnte es sein, daß das Probleme macht ?
formerly known as bizzl
Nino
Beiträge: 1300
Registriert: 13.05.2010 09:26
Wohnort: Berlin

Re: Fehler bei erweiterten Gadgets...

Beitrag von Nino »

Ghosty1967 hat geschrieben:

Code: Alles auswählen

If Gadget = #PB_Any
  Gadget = CheckBoxGadget(#PB_Any, x, y, width, height, Text$, Flags)
Else
  CheckBoxGadget(Gadget, x, y, width, height, Text$, Flags)
EndIf
Das ist OK, und ich wüsste nicht wie man das verbessern könnte.

Mir ist aber an dem eigentlichen Code, den du gepostet hast, spontan einiges aufgefallen:

Code: Alles auswählen

Procedure CheckGadgetEx_(Gadget.l, x.l, y.l, width.l, height.l, Text$, Font=#PB_Ignore, Status.l=#False, Flags=0)
Als Datentyp für ganze Zahlen sollte man immer .i verwenden, außer man hat in einem speziellen Fall einen guten Grund, das nicht zu tun.
Rückgabewerte (sowohl von eingebauten PB-Funktionen als auch von eigenen Prozeduren) sollten im Code immer geprüft werden.
Deine Prozedur CheckGadgetEx() gibt bei einem Fehler (also falls IsGadget() = 0 ist) 0 zurück. 0 kann aber auch eine gültige Gadget-Nummer sein.

Weiter habe ich jetzt nicht gekuckt, aber die o.g. Dinge solltest du auf jeden Fall ändern. Es könnten solche „Kleinigkeiten“ oder eine Kombination davon sein, die die Probleme verursacht.
Benutzeravatar
H.Brill
Beiträge: 496
Registriert: 15.10.2004 17:42
Wohnort: 66557 Neunkirchen

Re: Fehler bei erweiterten Gadgets...

Beitrag von H.Brill »

#PB_Any ist ja eine Konstante. Die hat einen bestimmten festen Wert und sagt als Parameter der Funktion
zum Erstellen des Gadgets, daß diese eine Gadget(Windows)-ID zurückliefern soll, die dann auch
für das Gadget alleine gültig ist. Diese von Windows generierte ID ist dann im ganzen laufenden Programm
nur für diese eine Gadget gültig.
Bei deiner Konstruktion mag das in den allermeisten Fällen funktionieren, muß es aber nicht. Besonders dann,
wenn von dir festgelegte IDs mit #PB_Any kollidieren. Ich vermute, daß hinter #PB_Any nur eine 1 für wahr
oder -1 dahinter steckt. Und das kann je nach Enumeration im einstelligen Bereich schiefgehen. Ich gehe mal
davon aus, daß Konstanten während des Programmlaufs unveränderbar sind.

Logischer und richtiger wäre folgendes :

Code: Alles auswählen

Gadget = CheckBoxGadget(#PB_Any, x, y, width, height, Text$, Flags)
If Gadget > 0
  Gadget = CheckGadgetEx_(....)
EndIf
Ich persönlich finde PB_Any bei der Erstellung von Gadgets nicht so gut. Da hätte Fred besser
generell eine von Windows generierte ID zurückgeben sollen. Das machen andere Sprachen
generell so.

So ist mal mein Gedankengang dazu.
Vielleicht irre ich mich aber auch.
PB 6.10
Benutzeravatar
Ghosty1967
Beiträge: 205
Registriert: 29.08.2005 13:56
Computerausstattung: Intel i7, 128GB Ram, Win10 Ultimate, PB6.00 Alpha 3
Wohnort: Köln

Re: Fehler bei erweiterten Gadgets...

Beitrag von Ghosty1967 »

Danke Euch, hat mir schonmal weitergeholfen :lol:
@Nino: Tatsächlich funktioniert der Aufruf mit #PB_Any, wenn ich die Übergabewerte von vornherein als Integer deklariere (mir ist nur nicht richtig klar warum :D )
@H.Brill auch deinen Vorschlag hab ich mal eingebunden...funktioniert soweit

Danke erst einmal :allright:
Benutzeravatar
Macros
Beiträge: 1361
Registriert: 23.12.2005 15:00
Wohnort: Olching(bei FFB)
Kontaktdaten:

Re: Fehler bei erweiterten Gadgets...

Beitrag von Macros »

Wie Berie schon richtig geantwortet hat ist #PB_Any eine Konstante mit Wert -1.
Wird sie eingesetzt teilt sie lediglich PB mit, dass es eine zufällige ID generieren soll, die dann der Rückgabewert ist.
(Die ID liegt bei bei mir bei aktuellem PureBasic zwischen 20 und 40 Millionen, ist aber nicht dokumentiert, also nicht darauf basierend Code schrieben)
Selbst festgelegte IDs kollidieren nicht mit #PB_Any, wenn man vermeidet IDs im Bereich über 10 Millionen zu vergeben.
Warum man das tun sollte ist mir nicht bekannt und der Compiler warnt auch in dem Fall.

@H.Brill: Wenn du das von dir gewünschte Verhalten willst, dann kannst du einfach immer #PB_Any verwenden.

Insofern sehe ich auch im Code von Ghosty1967 keinen verursachenden Fehler. So wie er das if mit #PB_Any gesetzt hat ist es korrekt.
Die Tips von Nino sind richtig und wichtig. Am .l Typ liegt es allerdings auch nicht. Zahlen unter 30 Millionen, das kann eine long noch fassen.
Edit wegen Ghosty1967s zwischenzeitlicher Antwort: Bei ihm liegen die generierten Werte von #PB_ANY wohl doch höher.

Bei mir funktioniert das Beispiel auch mit .l in 100% der Fälle unter Windows und Linux. Wobei man es so eben nicht machen sollte.

Wie man den Check ob das Gadget erstellt wurde einbauen könnte:

Code: Alles auswählen

If Gadget = #PB_Any
    returnvalue = CheckBoxGadget(#PB_Any, x, y, width, height, Text$, Flags)
    gadget = returnvalue
  Else
    returnvalue = CheckBoxGadget(Gadget, x, y, width, height, Text$, Flags)
  EndIf
  If returnvalue = 0
    ProcedureReturn -1
  EndIf
-1 ist keine gültige Gadgetnummer und würde somit eindeutig auf einen Fehler Hinweisen.
Achtung: Beim Prüfen muss man dann auch gegen -1 prüfen, ein einfaches if CheckGadgetEx_ meldet Erfolg weil alle Werte <>0 als Erfolg gemeldet werden.

Ich würde mir dafür eine Konstante definieren:

Code: Alles auswählen

#GadgetEx_Error = -1 
; Konstante dann am besten auch in der Funktionsdefinition für den Rückgabewert im Fehlerfall nutzen
If CheckGadgetEx_(#PB_Any, 120,  30, 100,  18, "Checkbox", #FNT_TAHOMA, #True, 3728173928) = #GadgetEx_Error
  Debug "Fehler, Gadget nicht erstellt!"
EndIf

@Ghosty1967 : Da bei dir die PB_ANY generierten Werte höher zu liegen scheinen, magst du mal folgenden Code ausführen und mir die Ergebnisse verraten?

Code: Alles auswählen

OpenWindow(1,0,0,800,600,"")
min=10000000000
max=0
For a=1 To 10000
  gadget=TextGadget(#PB_Any,Random(100),Random(100),Random(100),Random(100),"abc")
  If gadget<min
    min=gadget
  ElseIf gadget>max
    max=gadget
  EndIf
  FreeGadget(gadget)
Next
Debug min
Debug max
Bild
Benutzeravatar
Ghosty1967
Beiträge: 205
Registriert: 29.08.2005 13:56
Computerausstattung: Intel i7, 128GB Ram, Win10 Ultimate, PB6.00 Alpha 3
Wohnort: Köln

Re: Fehler bei erweiterten Gadgets...

Beitrag von Ghosty1967 »

@Macros: Danke für die Erklärungen...hier die von dir gewünschten Werte
max = 1947221576096
Benutzeravatar
Bisonte
Beiträge: 2465
Registriert: 01.04.2007 20:18

Re: Fehler bei erweiterten Gadgets...

Beitrag von Bisonte »

Ghosty1967 hat geschrieben: 20.09.2023 09:07 @Nino: Tatsächlich funktioniert der Aufruf mit #PB_Any, wenn ich die Übergabewerte von vornherein als Integer deklariere (mir ist nur nicht richtig klar warum :D )
Das warum ?

.l ist Long... das heisst maximal 2147483647 Bytes adressierbar.

Nun nehmen wir mal an, dass jemand der mehr als 2 GB Ram besitzt,
das Programm startet und das Programm bekommt von dem Betriebssystem
einen Speicherbereich Jenseits dieser 2 GB Grenze zugewiesen
(oder bekommt virtuellen Speicher bei kein freiem Ram)....

Und schon siehst du warum man Integer nehmen "muss"....
PureBasic 6.21 (Windows x86/x64) | Windows11 Pro x64 | AsRock B850 Steel Legend Wifi | R7 9800x3D | 64GB RAM | GeForce RTX 5080 | ThermaltakeView 270 TG ARGB | build by vannicom​​
Benutzeravatar
RSBasic
Admin
Beiträge: 8047
Registriert: 05.10.2006 18:55
Wohnort: Gernsbach
Kontaktdaten:

Re: Fehler bei erweiterten Gadgets...

Beitrag von RSBasic »

Ghosty1967 hat geschrieben: 20.09.2023 06:45 Hallo zusammen,
wenn ich für meine Projekte eigene GUIs erstelle, hat es mich immer genervt, für jedes Gadget (falls benötigt) die Text- und Hintergrundfarbe,
sowie den Zeichensatz usw... einzeln zu setzen.
Ja kenne ich. Ich bin auch kein Freund von manuellen Sachen, sondern ich automatisiere gerne.
Ich hab auf einem meiner Monitore mein eigenes Dashboard-Programm und da habe ich auch viele Gadgets, die ich normalerweise einzeln umfärben müsste, weil ich gerne DarkMode für mein Dashboard haben wollte.
Für mein Dashboard nutzte ich EnumChildWindows_(), um alle Gadgets in meinem Fenster zu ermitteln. Es ist egal, wie viele Gadgets es sind und ob #PB_Any oder nicht. Ich kann damit alle Gadgets ermitteln und umfärben.
In der Callback-Funktion habe ich den Typ des Gadgets ermittelt, um je nach Gadgettyp die Vorder- und Hintergrundfarbe mit Hilfe einer Farbkonstante zu setzen:

Code: Alles auswählen

Procedure SetGadgetDarkMode(hwnd, Param)
  Protected CurrentClassName$
  Protected CurrentGadgetNumber
  
  CurrentClassName$ = Space(1024)
  GetClassName_(hwnd, @CurrentClassName$, Len(CurrentClassName$))
  CurrentGadgetNumber = GetProp_(hwnd, "PB_ID")
  
  Select CurrentClassName$
    Case "Static", "RICHEDIT50W", "SysListView32"
      SetGadgetColor(CurrentGadgetNumber, #PB_Gadget_BackColor, #DarkModeColor_Background)
      SetGadgetColor(CurrentGadgetNumber, #PB_Gadget_FrontColor, #DarkModeColor_Text)
    Case "msctls_progress32"
      SetGadgetColor(CurrentGadgetNumber, #PB_Gadget_BackColor, #DarkModeColor_Background2)
      SetGadgetColor(CurrentGadgetNumber, #PB_Gadget_FrontColor, #DarkModeColor_Text2)
      
  EndSelect
  
  ProcedureReturn #True
EndProcedure

EnumChildWindows_(WindowID(Window_Main), @SetGadgetDarkMode(), 0)
Mein Dashboard sieht dann im DarkMode so aus:
Bild
Aus privaten Gründen habe ich leider nicht mehr so viel Zeit wie früher. Bitte habt Verständnis dafür.
Bild
Bild
Benutzeravatar
Macros
Beiträge: 1361
Registriert: 23.12.2005 15:00
Wohnort: Olching(bei FFB)
Kontaktdaten:

Re: Fehler bei erweiterten Gadgets...

Beitrag von Macros »

Ghosty1967 hat geschrieben: 20.09.2023 09:34 max = 1947221576096
Danke, also ca 2 * 10^12.

Nun sieht man auch gleich das Problem. Wenn du in der Hilfe den Typ long ansiehst (Kapitel Variablen, Typen und Operatoren)
Long | .l | 4 Byte | -2147483648 bis +2147483647
merkst du, da passt diese Nummer bei weitem nicht rein.
Das Maximum sind ja nur ca 2 * 10^9.

In den Bereich eines Integer auf einem 64 Bit System aber locker.
(-9223372036854775808 bis +9223372036854775807, ca 9 * 10^18)

Erstaunlich, dass #PB_Any bei deinem System so viel höhere Nummern generiert als auf meinem.
Bild
Antworten