Gadgets verschieben bzw. positionieren

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

Gadgets verschieben bzw. positionieren

Beitrag von hjbremer »

vor langer Zeit habe ich mal einen ähnlichen Code geschrieben mit Namen gotoxy. Dieser war gut aber mit Flags überladen und deswegen unübersichtlich.

mein letzter Code WriteText basierte darauf.

Hier nun eine überarbeitete Version genannt goxy. Dieser kommt wieder mit nur 5 flags aus und beschränkt sich auf das Nötigste.

wer die Beispiele nicht mehr braucht kann sie ja löschen

Vorschläge sind erwünscht

Code: Alles auswählen

;- Gadgets verschieben by HJBremer V.1.10 Nov 2022 - Windows 10 - PB ab 5.70 all

; goxy(pbnr, parent, position=#goBottom, align=#goLeft, gap=10, moveX=0, moveY=0)

;  pbnr     = pbnr des Gadgets welches verschoben wird
;  parent   = pbnr des Gadgets welches der Bezugspunkt ist
;  position = flag bestimmt wo das Gadget hin soll, flags gelten auch für align, siehe DeclareModule 
;  align    = flag bestimmt Ausrichtung 
;  gap      = Abstand zum Parentgadget, Vorgabe ist 10 Pixel Abstand zum Gadget 
;  move     = zusätzliche Möglichkeit ein Gadget zu verschieben, plus minus erlaubt

;  Standarvorgabe ist #goBottom, #goLeft, Abstand 10 Pixel zum Gadget

;Beispiele
;  goxy(pbnr, parent)                            ;unter dem Gadget links, Abstand Vorgabe 10
;  goxy(pbnr, parent, #goTop)                    ;über dem Gadget links
;  goxy(pbnr, parent, #goLeft)                   ;links vom Gadget oben
;  goxy(pbnr, parent, #goRight)                  ;rechts vom Gadget oben
;  goxy(pbnr, parent, #goRight, #goBottom, 3)    ;rechts vom Gadget unten Abstand 3 
;  goxy(pbnr, parent, #goBottom, #goCenter, 3)   ;unter dem Gadget mittig Abstand 3
;
;  goxy(202, #window, #goTop, #goRight)                  ;im Window oben rechts, braucht kein #goInside
;  goxy(200, #container, #goInside+#goBottom, #goRight)  ;im Container unten rechts, #goInside wenn innerhalb

;  Hinweis für #goInside: wenn ein Window die gleiche Nummer wie ein Gadget hat funktioniert es nicht !      
;  Hinweis für #goInside: ein Gadget muß in der entsprechenden Gadgetlist definiert sein z.B. beim Container !      

;  Hinweis: Konstanten benutzen, dient der Übersicht. Windows und Gadgets dürfen nicht die gleichen Werte haben.

DeclareModule goxy
   
   #goTop = 16 
   #goLeft = 1
   #goRight = 2
   #goBottom = 128   
   #goCenter = $100000
   #goInside = $80000   ;nur für Position wenn Parent Window oder Container etc
   
   Declare.i goxy(pbnr, parent, position=#goBottom, align=#goLeft, gap=10, moveX=0, moveY=0)
   
   Declare.i goxySetGap(gap)
   
EndDeclareModule
;-
Module goxy   
   EnableExplicit  
   
   Global newgap = #PB_Default
      
   Procedure.i goxySetGap(gap)
      newgap = gap
   EndProcedure
   
   Procedure.i goxy(child, parent, position=#goBottom, align=#goLeft, gap=10, moveX=0, moveY=0)
      
      Protected info$ = "Child: " + Str(child) + " Parent: " + Str(parent) + " "
      
      If newgap <> #PB_Default And gap = 10 : gap = newgap : EndIf         
      
      If IsGadget(child) = 0
         Debug info$ + "Child ist kein Gadget"
         ProcedureReturn
      EndIf      
      
      Protected inside, parenttyp = 0
      
      Protected x, y                   ;Child Gadget Werte
      Protected w = GadgetWidth(child)
      Protected h = GadgetHeight(child)
      Protected px, py, pw, ph         ;Parent Werte
      
      If Bool(position & #goInside)
         inside = #True: position = position - #goInside ;goinside entfernen         
      EndIf      
      
      If IsGadget(parent) = 0 ;wenn kein Gadget
         If IsWindow(parent)  ;wenn Window 
            parenttyp = 1 : inside = #True   ;im Window immer inside
         Else            
            Debug info$ + "Parent ist kein Gadget/Window" 
            ProcedureReturn           
         EndIf
      Else     ;ist ein Gadget
         Select GadgetType(parent)
            Case #PB_GadgetType_Container, #PB_GadgetType_Panel, #PB_GadgetType_ScrollArea 
               If inside: parenttyp = 2: EndIf            
         EndSelect
      EndIf  
      
      If parenttyp = 1             
         pw = WindowWidth(parent): ph = WindowHeight(parent)   ;Window Parent Werte        
      Else
         px = GadgetX(parent): py = GadgetY(parent)            ;Gadget Parent Werte        
         pw = GadgetWidth(parent): ph = GadgetHeight(parent) 
      EndIf
         
      If parenttyp = 0  ;Parent ist ein Gadget
         
         Select position                        ;wohin soll das ChildGadget ?
            Case #goTop: y = py - h - gap       ;y über dem Parent         
            Case #goLeft: x = px - w - gap      ;x links vom Parent         
            Case #goRight: x = px + pw + gap    ;x rechts vom Parent         
            Case #goBottom: y = py + ph + gap   ;y unter dem Parent         
            Default: Debug info$ + "Flag nicht vorgesehen" 
         EndSelect 
         
         Select align            ;Ausrichtung
            Case #goTop             
               Select position 
                  Case #goLeft, #goRight: y = py 
                  Default: Debug info$ + "Flag nicht vorgesehen" 
               EndSelect
               
            Case #goLeft 
               Select position 
                  Case #goTop, #goBottom: x = px 
                  Default: Debug info$ + "Flag nicht vorgesehen" 
               EndSelect
               
            Case #goRight 
               Select position
                  Case #goTop, #goBottom: x = px + pw - w
                  Default: Debug info$ + "Flag nicht vorgesehen" 
               EndSelect
               
            Case #goBottom:
               Select position
                  Case #goLeft, #goRight: y = py + ph - h
                  Default: Debug info$ + "Flag nicht vorgesehen" 
               EndSelect
               
            Case #goCenter: 
               Select position
                  Case #goTop, #goBottom: x = px + ((pw - w)/2) 
                  Case #goLeft, #goRight: y = py + ((ph - h)/2)
                  Case #goCenter: Debug info$ + "Flag nicht vorgesehen" 
               EndSelect
               
            Default: Debug info$ + "Flag nicht vorgesehen/unbekannt" 
         EndSelect
         
      Else  ;Parent ist window oder container

         Select position         ;wohin soll das ChildGadget ?
            Case #goTop: y = gap 
            Case #goBottom: y = ph - h - gap 
            Default: Debug info$ + "Flag für posi im window/container nicht vorgesehen" 
         EndSelect 
     
         Select align
            Case #goLeft : x = gap
            Case #goRight : x = pw - gap - w
            Case #goCenter : x = (pw - w) / 2
            Default: Debug info$ + "Flag für align im window/container nicht vorgesehen" 
         EndSelect
         
      EndIf
      
      ResizeGadget(child, x + moveX, y + moveY, #PB_Ignore, #PB_Ignore)
   EndProcedure
   
EndModule

UseModule goxy

;===================

CompilerIf #PB_Compiler_IsMainFile
   
   #window = 50
   #parent = 0
   #container = 100
   #container2 = 110
   
   OpenWindow(#window, 0, 0, 850, 500, "TextGadget", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
   
   ButtonGadget(#parent, 100, 100, 200, 50, "Gadget Parent")

   For j = 1 To 12
      ButtonGadget(j, 0, 0, 60, 22, "Button " + Str(j))
   Next
   
   goxy(1, #parent)                       ;position=#goBottom + align=#goLeft sind Vorgabe   
   goxy(2, #parent, #goRight, #goTop) 
   goxy(3, #parent, #goLeft, #goTop)
   
   goxy(4, #parent, #goBottom, #goRight, 10, -8)   ;x wird um -8 verschoben
   goxy(5, #parent, #goRight, #goBottom)   
   goxy(6, #parent, #goTop, #goCenter, 5)          ;Abstand ist hier 5
   
   goxySetGap(20)
   
   goxy(7, 1)
   goxy(8, 7)
   goxy(9, 8, #goBottom, #goLeft)
   goxy(10, 9, #goRight, #goTop)   
   goxy(11, 9)
   
   goxySetGap(#PB_Default)
   
   goxy(12, #parent, #goTop)  
   
   ContainerGadget(#container, 500, 110, 200, 222, 1)
      ButtonGadget(190, 0, 0, 90, 25, "Button 190")
      ButtonGadget(191, 0, 0, 90, 25, "Button 191")
      goxy(190, #container, #goInside+#goTop, #goLeft)     ; + oder |
      goxy(191, #container, #goInside|#goBottom, #goRight) ; erlaubt
      
   CloseGadgetList()   
   
   ButtonGadget(201, 0, 0, 80, 25, "Button 201")
   ButtonGadget(202, 0, 0, 80, 25, "Button 202")
   ButtonGadget(203, 0, 0, 80, 25, "Button 203")
   
   goxy(201, #window, #goBottom)  
   goxy(202, #window, #goTop, #goRight)  
   goxy(203, #window, #goTop, #goCenter)  
     
   Repeat : Until WaitWindowEvent() = #PB_Event_CloseWindow
   
CompilerEndIf
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
SMaag
Beiträge: 150
Registriert: 08.05.2022 12:58

Re: Gadgets verschieben bzw. positionieren

Beitrag von SMaag »

gute Sache!

Anregung:
Das müsste man noch so hinbekommen, dass man das bei einem Resize auch verwenden kann.

Ich stelle mir das so vor:

Die Anordnung der Gadgets mit goxy packt man in eine Procedure. Z.B. Procedure ArrangeGadgets()
Bei einem Resize ändert man die Fenstergröße und ruft ArrangeGadgets() erneut auf.
Nun werden die Größen und Positionen der Gadgets neu angepasst.

Dazu müsste man aber die Breite und die Höhe der Gadgetes bei goxy mit aufnehmen.
die align Eigenschaft müsste dann aber für alle Seiten festlegbar sein.

PseudoCode
goxy\AlignTop = GadgetID von Gadget darüber
goxy\AlignRight = GadgetID von Gadget rechts
goxy\AlignBottom = GadgetID von Gadget darunter
goxy\AlignLeft = GadgetID von Gadget links

Mit den entsprechenden gaps würde das Gadget dann automatisch in Breite und Höhe gezogen.

Leider ist das aber weit aufwendiger und komplizierter.
Da Gadgets in PB keine User-defined-Tags haben, wo man die Ausrichtung anhängen kann, müsste man eine List() generieren, die
alle Gadgets und die Ausrichtungseigenschaften enthält. Ob das dann komfortabler ist,
als händisch eine entsprechende Resize-Procedure zu erstellen, müsste sich erst noch herausstellen.
Antworten