Gadget Dock Include

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
milan1612
Beiträge: 810
Registriert: 15.04.2007 17:58

Gadget Dock Include

Beitrag von milan1612 »

Hallo zusammen,

Da es in PureBasic leider an nativen Fensterlayout-Hilfen fehlt hab ich mich heute
mal hingesetzt und versucht das meiner Meinung nach sehr angenehm zu verwendende
Dock Verhalten des .Net Framework nachzuprogrammieren. Herausgekommen ist das hier:

Code: Alles auswählen

;PureBasic Gadget Docking Include
;March 2008
;Copyright 2008 by Milan Schömig (milan1612)
;milan1612@gmx.de
;Developed and tested with PB 4.10 Final

;Do whatever you want to do with this, but I ask you
;to release any improvements you make so others
;may benefit from them as well

EnableExplicit

#DockLeft = 2
#DockRight = 4
#DockTop = 8
#DockBottom = 16
#DockFill = 32

Declare DockGadget(Gadget.l, DockState.l, MarginLeft.l = 0, MarginRight.l = 0, MarginTop.l = 0, MarginBottom.l = 0)
Declare UnDockGadget(Gadget.l)

Declare GadgetAlreadyInList(GadgetID.l)
Declare SubclassParent(GadgetID.l)
Declare DockWindowCallback(WindowID.l, Message.l, wParam.l, lParam.l)
Declare CalculateWindowClientRect(WindowID.l, *Rect.RECT)
Declare FindPossibleToolStatusbar(WindowID.l)
Declare WindowEnumCallback(hWnd.l, ID.l)
Declare DockLeft(GadgetID.l, *Rect.RECT, MLeft.l, MRight.l, MTop.l, MBottom.l)
Declare DockRight(GadgetID.l, *Rect.RECT, MLeft.l, MRight.l, MTop.l, MBottom.l)
Declare DockTop(GadgetID.l, *Rect.RECT, MLeft.l, MRight.l, MTop.l, MBottom.l)
Declare DockBottom(GadgetID.l, *Rect.RECT, MLeft.l, MRight.l, MTop.l, MBottom.l)
Declare DockFill(GadgetID.l, *Rect.RECT, MLeft.l, MRight.l, MTop.l, MBottom.l)

Structure Gadget
  GadgetID.l
  DockState.l
  MarginLeft.l
  MarginRight.l
  MarginTop.l
  MarginBottom.l
EndStructure

Global NewList DockGadgets.Gadget()
Global ToolBarHandle.l
Global StatusBarHandle.l

ProcedureDLL DockGadget(Gadget.l, DockState.l, MarginLeft.l = 0, MarginRight.l = 0, MarginTop.l = 0, MarginBottom.l = 0)
  If Not IsGadget(Gadget) : ProcedureReturn 0 : EndIf
  If GadgetAlreadyInList(GadgetID(Gadget)) : UnDockGadget(Gadget) : EndIf  
  If MarginLeft < 0 : MarginLeft = 0 : EndIf
  If MarginRight < 0 : MarginRight = 0 : EndIf
  If MarginTop < 0 : MarginTop = 0 : EndIf
  If MarginBottom < 0 : MarginBottom = 0 : EndIf
  AddElement(DockGadgets())
  DockGadgets()\GadgetID = GadgetID(Gadget)
  DockGadgets()\DockState = DockState
  DockGadgets()\MarginLeft = MarginLeft
  DockGadgets()\MarginRight = MarginRight
  DockGadgets()\MarginTop = MarginTop
  DockGadgets()\MarginBottom = MarginBottom
  SubclassParent(GadgetID(Gadget))
  If Not GetWindowLong_(GetParent_(GadgetID(Gadget)), #GWL_STYLE) & #WS_CLIPCHILDREN
    SetWindowLong_(GetParent_(GadgetID(Gadget)), #GWL_STYLE, GetWindowLong_(GetParent_(GadgetID(Gadget)), #GWL_STYLE) | #WS_CLIPCHILDREN)
  EndIf
  SendMessage_(GetParent_(GadgetID(Gadget)), #WM_SIZE, 0, 0)
  InvalidateRect_(GetParent_(GadgetID(Gadget)), 0, 1)
EndProcedure

ProcedureDLL UnDockGadget(Gadget.l)
  Protected ReturnVal
  ForEach DockGadgets()
    If DockGadgets()\GadgetID = GadgetID(Gadget)
      DeleteElement(DockGadgets())
      ReturnVal = 1
    EndIf
  Next
  ProcedureReturn ReturnVal
EndProcedure

Procedure GadgetAlreadyInList(GadgetID.l)
  Protected isInList
  Protected Count
  ForEach DockGadgets()
    Count + 1
    If DockGadgets()\GadgetID = GadgetID
      isInList = 1
      Break
    EndIf
  Next
  If Not isInList
    Count = 0
  EndIf
  ProcedureReturn Count
EndProcedure

Procedure SubclassParent(GadgetID.l)
  Protected ParentHandle.l = GetParent_(GadgetID)
  Protected OldProc = GetProp_(ParentHandle, @"PBDock_OldProcAddress")
  If Not OldProc
    OldProc = SetWindowLong_(ParentHandle, #GWL_WNDPROC, @DockWindowCallback())
    SetProp_(ParentHandle, @"PBDock_OldProcAddress", OldProc) 
  EndIf
EndProcedure

Procedure DockWindowCallback(WindowID.l, Message.l, wParam.l, lParam.l)
  Protected Rect.RECT

  Select Message
    Case #WM_SIZE
      LockWindowUpdate_(WindowID)
      CalculateWindowClientRect(WindowID, @Rect)
      ForEach DockGadgets()
        SendMessage_(DockGadgets()\GadgetID, #WM_SETREDRAW, 0, 0)
        If GetParent_(DockGadgets()\GadgetID) = WindowID
          Select DockGadgets()\DockState
            Case #DockLeft
              DockLeft(DockGadgets()\GadgetID, @Rect, DockGadgets()\MarginLeft, DockGadgets()\MarginRight, DockGadgets()\MarginTop, DockGadgets()\MarginBottom)
            Case #DockRight
              DockRight(DockGadgets()\GadgetID, @Rect, DockGadgets()\MarginLeft, DockGadgets()\MarginRight, DockGadgets()\MarginTop, DockGadgets()\MarginBottom)
            Case #DockTop
              DockTop(DockGadgets()\GadgetID, @Rect, DockGadgets()\MarginLeft, DockGadgets()\MarginRight, DockGadgets()\MarginTop, DockGadgets()\MarginBottom)
            Case #DockBottom
              DockBottom(DockGadgets()\GadgetID, @Rect, DockGadgets()\MarginLeft, DockGadgets()\MarginRight, DockGadgets()\MarginTop, DockGadgets()\MarginBottom)
            Case #DockFill
              DockFill(DockGadgets()\GadgetID, @Rect, DockGadgets()\MarginLeft, DockGadgets()\MarginRight, DockGadgets()\MarginTop, DockGadgets()\MarginBottom)
          EndSelect
        EndIf
        SendMessage_(DockGadgets()\GadgetID, #WM_SETREDRAW, 1, 0)
        InvalidateRect_(DockGadgets()\GadgetID, 0, 0)
      Next
      LockWindowUpdate_(0)
      UpdateWindow_(WindowID)
  EndSelect
  ProcedureReturn CallWindowProc_(GetProp_(WindowID, @"PBDock_OldProcAddress"), WindowID, Message, wParam, lParam)
EndProcedure

Procedure CalculateWindowClientRect(WindowID.l, *Rect.RECT)
  Protected TempRect.RECT
  GetClientRect_(WindowID, *Rect)
  FindPossibleToolStatusbar(WindowID)
  If ToolBarHandle
    GetClientRect_(ToolBarHandle, @TempRect)
    *Rect\top + (TempRect\bottom - TempRect\top) + 2
  EndIf
  If StatusBarHandle
    GetClientRect_(StatusBarHandle, @TempRect)
    *Rect\bottom - (TempRect\bottom - TempRect\top)
  EndIf
EndProcedure

Procedure FindPossibleToolStatusbar(WindowID.l)
  ToolBarHandle = 0
  StatusBarHandle = 0
  EnumChildWindows_(WindowID, @WindowEnumCallback(), 0)
EndProcedure

Procedure WindowEnumCallback(hWnd.l, ID.l)
  Protected Buffer.s = Space(100)
  If GetClassName_(hWnd, @Buffer, 99)
    If Buffer = "ToolbarWindow32"
      ToolBarHandle = hWnd
    ElseIf Buffer = "msctls_statusbar32"
      StatusBarHandle = hWnd
    EndIf
  EndIf
  ProcedureReturn 1
EndProcedure

Procedure DockLeft(GadgetID.l, *Rect.RECT, MLeft.l, MRight.l, MTop.l, MBottom.l)
  Protected GadRect.RECT
  GetWindowRect_(GadgetID, @GadRect)
  Protected X = *Rect\left + MLeft
  Protected Y = *Rect\top + MTop
  Protected W = GadRect\right - GadRect\left
  Protected H = *Rect\bottom - *Rect\top - MTop - MBottom
  MoveWindow_(GadgetID, X, Y, W, H, 0)
  *Rect\left + (GadRect\right - GadRect\left) + MLeft + MRight
EndProcedure

Procedure DockRight(GadgetID.l, *Rect.RECT, MLeft.l, MRight.l, MTop.l, MBottom.l)
  Protected GadRect.RECT
  GetWindowRect_(GadgetID, @GadRect)
  Protected X = *Rect\right - GadRect\right + GadRect\left - MRight
  Protected Y = *Rect\top + MTop
  Protected W = GadRect\right - GadRect\left
  Protected H = *Rect\bottom - *Rect\top - MTop - MBottom
  MoveWindow_(GadgetID, X, Y, W, H, 0)
  *Rect\right - ((GadRect\right - GadRect\left) + MLeft + MRight)
EndProcedure

Procedure DockTop(GadgetID.l, *Rect.RECT, MLeft.l, MRight.l, MTop.l, MBottom.l)
  Protected GadRect.RECT
  GetWindowRect_(GadgetID, @GadRect)
  Protected X = *Rect\left + MLeft
  Protected Y = *Rect\top + MTop
  Protected W = *Rect\right - MRight - *Rect\left + MLeft - MLeft - MRight
  Protected H = MTop + GadRect\bottom - GadRect\top
  MoveWindow_(GadgetID, X, Y, W, H, 0)
  *Rect\top + MTop + (GadRect\bottom - GadRect\top) + MBottom
EndProcedure

Procedure DockBottom(GadgetID.l, *Rect.RECT, MLeft.l, MRight.l, MTop.l, MBottom.l)
  Protected GadRect.RECT
  GetWindowRect_(GadgetID, @GadRect)
  Protected X = *Rect\left + MLeft
  Protected Y = *Rect\bottom - MBottom - GadRect\bottom + GadRect\top - MTop
  Protected W = *Rect\right - MRight - *Rect\left + MLeft - MLeft - MRight
  Protected H = GadRect\bottom - GadRect\top
  MoveWindow_(GadgetID, X, Y, W, H, 0)
  *Rect\bottom - (MTop + MBottom) - (GadRect\bottom - GadRect\top)
EndProcedure

Procedure DockFill(GadgetID.l, *Rect.RECT, MLeft.l, MRight.l, MTop.l, MBottom.l)
  Protected X = *Rect\left + MLeft
  Protected Y = *Rect\top + MTop
  Protected W = *Rect\right - *Rect\left - MLeft - MRight
  Protected H = *Rect\bottom - *Rect\top - MTop - MBottom
  MoveWindow_(GadgetID, X, Y, W, H, 0)
EndProcedure

DisableExplicit
Hier ein kleines Anwendungsbeispiel:

Code: Alles auswählen

IncludeFile "Dock.pbi"

#Flags = #PB_Window_MaximizeGadget|#PB_Window_MinimizeGadget|#PB_Window_ScreenCentered|#PB_Window_SizeGadget|#PB_Window_SystemMenu
OpenWindow(0, 0, 0, 630, 480, "Dock Example", #Flags)
CreateGadgetList(WindowID(0))
  SmartWindowRefresh(0, 1)

  CreateMenu(1, WindowID(0))
  MenuTitle("File")
    MenuItem(0, "Exit")
  
  CreateToolBar(2, WindowID(0))
    ToolBarStandardButton(0, #PB_ToolBarIcon_New)
    ToolBarStandardButton(1, #PB_ToolBarIcon_Open)
  
  CreateStatusBar(3, WindowID(0))
    StatusBarText(3, 0, "Welcome to the docking test ;-)")
  
  ButtonGadget(1, 0, 0, 80, 40, "Left")
  ButtonGadget(2, 0, 0, 80, 40, "Right")
  ButtonGadget(3, 0, 0, 80, 50, "Top")
  ButtonGadget(4, 0, 0, 80, 50, "Bottom")
  ButtonGadget(5, 0, 0, 80, 40, "Fill")
  
  DockGadget(1, #DockLeft, 2, 0, 0, 0)
  DockGadget(2, #DockRight, 0, 2, 0, 0)
  DockGadget(3, #DockTop, 2, 2, 0, 0)
  DockGadget(4, #DockBottom, 2, 2, 0, 0)
  DockGadget(5, #DockFill, 2, 2, 2, 2)

Repeat : Until WaitWindowEvent() = #PB_Event_CloseWindow
Grundsätzlich sind nur 2 Funktionen wichtig:

Code: Alles auswählen

DockGadget(Gadget, DockState, MarginLeft, MarginRight, MarginTop, MargineBottom)
und

Code: Alles auswählen

UnDockGadget(Gadget)
"Gadget" sollte selbsterklärend sein, der DockState wird durch 5 Konstanten, die
in der Include definiert sind, beschrieben und MarginLeft, -Right, -Bottom
und -Top geben den Rand an, der bei der Berechnung der Positionen der
Gadgets berücksichtigt werden soll.
Am besten ihr schaut euch einfach das Beispiel dazu an.

Noch was, ich hab das heute innerhalb von 2 Stunden geschrieben und nur wenig
getestet. Bitte seid nicht zu streng mit mir und meldet eventuelle Fehler.

EDIT1: OK, dank Kiffi sollte der erste Bug behoben sein, Code upgedated...
EDIT2: Code aufgeräumt
EDIT3: So, das Flickern sollte jetzt ein Ende haben, falls doch noch was zu sehen
ist, einfach mal SmartWindowRefresh() ausprobieren
Zuletzt geändert von milan1612 am 29.03.2008 17:58, insgesamt 4-mal geändert.
Bin nur noch sehr selten hier, bitte nur noch per PN kontaktieren
Benutzeravatar
Kiffi
Beiträge: 10714
Registriert: 08.09.2004 08:21
Wohnort: Amphibios 9

Re: Gadget Dock Include

Beitrag von Kiffi »

Hallo Milan,

Super Idee, danke für's Teilen! :allright:

aber... so irgendwie ist das noch nicht ganz sauber(?)

Code: Alles auswählen

TreeGadget    (1, 0, 0, 100,  40)
ListViewGadget(2, 0, 0,  80, 100)
EditorGadget  (3, 0, 0,  80,  50)
 
DockGadget(1, #DockLeft, 0, 0, 0, 0)
DockGadget(2, #DockTop,  0, 0, 0, 0)
DockGadget(3, #DockFill, 0, 0, 0, 0)
Grüße ... Kiffi
a²+b²=mc²
Benutzeravatar
milan1612
Beiträge: 810
Registriert: 15.04.2007 17:58

Beitrag von milan1612 »

Danke fürs Testen, ich bin grad bei meiner Freundin am Laptop und hab kein PB zur Hand.
Ich werds gleich morgen anschauen, wie gesagt, ich habs noch nicht ausgiebig getestet.

Grüße, Milan
Bin nur noch sehr selten hier, bitte nur noch per PN kontaktieren
Benutzeravatar
milan1612
Beiträge: 810
Registriert: 15.04.2007 17:58

Beitrag von milan1612 »

Sorry für Doppelpost :|
Kiffi, könntest du dein Beispiel jetzt noch mal versuchen?
Es gab ein kleines Redrawproblem, sollte gefixt sein...
Bin nur noch sehr selten hier, bitte nur noch per PN kontaktieren
Benutzeravatar
Kiffi
Beiträge: 10714
Registriert: 08.09.2004 08:21
Wohnort: Amphibios 9

Beitrag von Kiffi »

milan1612 hat geschrieben:Kiffi, könntest du dein Beispiel jetzt noch mal versuchen?
so sieht's besser aus! :allright:

Nochmals Danke & Grüße ... Kiffi
a²+b²=mc²
Benutzeravatar
NicTheQuick
Ein Admin
Beiträge: 8809
Registriert: 29.08.2004 20:20
Computerausstattung: Ryzen 7 5800X, 64 GB DDR4-3200
Ubuntu 24.04.2 LTS
GeForce RTX 3080 Ti
Wohnort: Saarbrücken

Beitrag von NicTheQuick »

Was ich mir wünschen würde:
Fenster-Erstellung so dynamisch wie HTML-Designerei. Also z.B. à la
XML-Struktur. Hab sowas schonmal angefangen, aber wieder abgebrochen,
weil es mir zu kompliziert wurde. Hab von Anfang an den Code falsch
strukturiert.

Mein System hätte so ausgesehen:

Code: Alles auswählen

WinID = form("window centered sysmenu size=400,300 title='\'test window\''")
  form("menu id=0", WinID)
    form("menu item parent", "Datei")
      form("menu item", "Öffnen")
      form("menu bar")
      form("menu item", "Beenden")
    form("menu item close")
    form("menu item", "Über")
  form("menu end")
  
  form("gadgets")
    form("table col=3 colwidth=1*,2*,1*")
        form("button id=0 width=* height=* toggle margin=5,0,5,5 text='Links'")
      form("column next")
        form("table row=3 rowheight=1*,4*,1*")
            form("button id=2, width=* height=* margin=5,5,0,5 text='Oben'")
          form("row next")
            form("button id=4 width=* height=* margin=0,5,0,5 multiline text='Mitte\lzweite Zeile'")
          form("row next")
            form("button id=3, width=* height=* margin=0,5,5,5 text='Unten'")
        form("table end")
      form("column next")
        form("button id=1 width=* height=* margin=5,5,5,0 text='Rechts'")
    form("table end")
  form("gadgets end")
form("window end")

Repeat
Until form_WaitWindowEvent() = #PB_Event_CloseWindow
Dabei fängt 'form_WaitWindowEvent()' das Resizen des Fensters
automatisch ab und ändert so die Größen der Gadgets auch alle relativ,
wenn die Sternchenrelationen oder Prozentangaben drin sind.

Zu Anfang sieht das Fenster dann so aus:

Code: Alles auswählen

WinID = OpenWindow(#PB_Any, #PB_Ignore, #PB_Ignore, 400, 300, "'test window'", #PB_Window_ScreenCentered | #PB_Window_SystemMenu | #PB_Window_SizeGadget)
If WinID
  If CreateMenu(0, WinID)
    OpenSubMenu("Datei")
      MenuItem(0, "Öffnen")
      MenuBar()
      MenuItem(1, "Beenden")
    CloseSubMenu()
    MenuItem(2, "Über")
  EndIf
  If CreateGadgetList(WindowID(WinID))
    ButtonGadget(0, 5, 5, 95, 290, "Links", #PB_Button_Toggle)
    ButtonGadget(1, 300, 5, 95, 290, "Rechts")
    ButtonGadget(2, 105, 5, 190, 45, "Oben")
    ButtonGadget(3, 105, 250, 190, 45, "Unten")
    ButtonGadget(4, 105, 55, 190, 190, "Mitte" + Chr(10) + "zweite Zeile", #PB_Button_MultiLine)
  EndIf
  
  Repeat
  Until WaitWindowEvent() = #PB_Event_CloseWindow
EndIf
End
Benutzeravatar
milan1612
Beiträge: 810
Registriert: 15.04.2007 17:58

Beitrag von milan1612 »

@Nic
Du meinst so eine Art XAML für PB?
Ja das wäre in der Tat cool, allerdings stell ich mir das recht kompliziert
zu programmieren vor :|
Bin nur noch sehr selten hier, bitte nur noch per PN kontaktieren
Benutzeravatar
Leonhard
Beiträge: 602
Registriert: 01.03.2006 21:25

Beitrag von Leonhard »

Also erst mal ein großes lob: Das teil ist super.

Ich hab mir das auch gleich auf mein Lib-Format gebracht (noch keine Dokumentation). Ist halt mein Art, jede Lib immer nachzuschreiben und zu verkleinern/beschleunigen.

Zusätzlich sind mir noch 2 Bugs aufgefallen, die im Top- und Bottom-Dock-Bereich mit dem Margin (top/bottom) auftreten. Diese Fehler sind bei meiner Version drausen.

Zusätzlich hab ich einen Parameter rein gebracht, womit es möglich ist, das Docken des Gadgets bei der Zuweisung zu unterbinden, was das Nerfige Blinken während des Fenster-Aufbaus unterbindet.

Hier meine version:

Code: Alles auswählen

;PureBasic Gadget Docking Include 
;March 2008 
;Copyright 2008 by Milan Schömig (milan1612) 
;milan1612@gmx.de 
;Developed and tested with PB 4.10 Final 

;Do whatever you want to do with this, but I ask you 
;to release any improvements you make so others 
;may benefit from them as well

;{ Library
ProcedureDLL SetGadgetMargin(GadgetID.l, *margin.Rect)
  SetProp_(GadgetID(GadgetID), "Margin", *margin)
EndProcedure
ProcedureDLL.l GetGadgetMargin(GadgetID.l)
  ProcedureReturn GetProp_(GadgetID(GadgetID), "Margin")
EndProcedure

Structure Gadget_ParentChildArray ;/ Dies ist das Array, welches dem Parent-Window zugeordet wird. Es enthält alle untergeordneten Child-Windows, die Gedockt werden sollen.
  GadgetID.l
  
  *Next ;/ Das nächste Element des Arrays
EndStructure
Structure Gadget_Dock
  DockState.b
  
  Margin.Rect
EndStructure

Declare __Docking_InitalizeDocking(GadgetID.l, hParent.l)
Declare.b __Docking_WndProc_EnumChildCallback(hWnd.l, *lParam.Rect)

Enumeration ;#Dock_*
  #Dock_None   = 0 ;/ dies ist kein Flag sondern eine Value, die gesetzt werden muss, um diesen Zustand zu erreichen.
  #Dock_Left   = %1 << 1
  #Dock_Right  = %1 << 2
  #Dock_Top    = %1 << 3
  #Dock_Bottom = %1 << 4
  #Dock_Fill   = %1 << 5
EndEnumeration

ProcedureDLL SetGadgetDockingState(GadgetID.l, DockingState.b, bResize.b = #True)
  SetProp_(GadgetID(GadgetID), "DockingState", DockingState)
  
  Protected hParent.l = GetParent_(GadgetID(GadgetID))
  
  __Docking_InitalizeDocking(GadgetID, hParent)
  
  If bResize
    SendMessage_(hParent, #WM_SIZE, 0, 0)
    InvalidateRect_(hParent, 0, 1)
  EndIf
EndProcedure
ProcedureDLL.b GetGadgetDockingState(GadgetID.l)
  ProcedureReturn GetProp_(GadgetID(GadgetID), "DockingState")
EndProcedure

Procedure.b __Docking_WndProc_EnumChildCallback(hWnd.l, *lParam.Rect)
  Protected rc.Rect
  Protected Buffer.s = Space(100)
  If GetClassName_(hWnd, @Buffer, 99)
    If Buffer = "ToolbarWindow32"
      GetClientRect_(hWnd, @rc)
      *lParam\top + (rc\bottom - rc\top) + 2
    ElseIf Buffer = "msctls_statusbar32"
      GetClientRect_(hWnd, @rc)
      *lParam\bottom - (rc\bottom - rc\top)
    EndIf
  EndIf
  ProcedureReturn 1
EndProcedure

Macro m__Docking_WndProc_DockLeft(hGadget, rc, margin)
  GetWindowRect_(hGadget, @rcGadget)
  MoveWindow_(hGadget, rc\left + margin\left, rc\top + margin\top, rcGadget\right - rcGadget\left, rc\bottom - rc\top - margin\top - margin\bottom, 0)
  rc\left + (rcGadget\right - rcGadget\left) + margin\left + margin\right
EndMacro
Macro m__Docking_WndProc_DockRight(hGadget, rc, margin)
  GetWindowRect_(hGadget, @rcGadget)
  MoveWindow_(hGadget, rc\right - rcGadget\right + rcGadget\left - margin\right, rc\top + margin\top, rcGadget\right - rcGadget\left,   rc\bottom - rc\top - margin\top - margin\bottom, 0)
  rc\right - ((rcGadget\right - rcGadget\left) + margin\left + margin\right)
EndMacro
Macro m__Docking_WndProc_DockTop(hGadget, rc, margin)
  GetWindowRect_(hGadget, @rcGadget)
  MoveWindow_(hGadget, rc\left + margin\left, rc\top + margin\top, rc\right - margin\right - rc\left - margin\right, margin\top + rcGadget\bottom - rcGadget\top - margin\bottom, 0)
  rc\top + margin\top + (rcGadget\bottom - rcGadget\top) + margin\bottom
EndMacro
Macro m__Docking_WndProc_DockBottom(hGadget, rc, margin)
  GetWindowRect_(hGadget, @rcGadget)
  MoveWindow_(hGadget, rc\left + margin\left, rc\bottom - (rcGadget\bottom - rcGadget\top) - margin\bottom, rc\right - margin\right - rc\left - margin\right, rcGadget\bottom - rcGadget\top + margin\top - margin\bottom, 0)
  rc\bottom - (margin\top + margin\bottom) - (rcGadget\bottom - rcGadget\top)
EndMacro
Macro m__Docking_WndProc_DockFill(hGadget, rc, margin)
  MoveWindow_(hGadget, rc\left + margin\left, rc\top + margin\top, rc\right - rc\left - margin\left - margin\right, rc\bottom - rc\top - margin\top - margin\bottom, 0)
EndMacro
Procedure __Docking_WndProc(hWnd.l, uMsg.l, wParam.l, lParam.l)
  Protected *this.Gadget_ParentChildArray = GetProp_(hWnd, "DockingWindowArray")
  Protected rc.Rect
  Protected rcGadget.Rect
  Protected *margin.Rect
  
  If uMsg = #WM_SIZE
    LockWindowUpdate_(hWnd)
    GetClientRect_(hWnd, rc)
    EnumChildWindows_(hWnd, @__Docking_WndProc_EnumChildCallback(), rc)
    While *this
      SendMessage_(GadgetID(*this\GadgetID), #WM_SETREDRAW, 0, 0)
      If GetParent_(GadgetID(*this\GadgetID)) = hWnd
        *margin = GetGadgetMargin(*this\GadgetID)
        
        Select GetGadgetDockingState(*this\GadgetID)
        Case #Dock_Left   : m__Docking_WndProc_DockLeft  (GadgetID(*this\GadgetID), rc, *margin)
        Case #Dock_Right  : m__Docking_WndProc_DockRight (GadgetID(*this\GadgetID), rc, *margin)
        Case #Dock_Top    : m__Docking_WndProc_DockTop   (GadgetID(*this\GadgetID), rc, *margin)
        Case #Dock_Bottom : m__Docking_WndProc_DockBottom(GadgetID(*this\GadgetID), rc, *margin)
        Case #Dock_Fill   : m__Docking_WndProc_DockFill  (GadgetID(*this\GadgetID), rc, *margin)
        EndSelect
      EndIf
      SendMessage_(GadgetID(*this\GadgetID), #WM_SETREDRAW, 1, 0)
      InvalidateRect_(*this\GadgetID, 0, 0)
      
      *this = *this\Next
    Wend
    LockWindowUpdate_(0)
    UpdateWindow_(hWnd)
  EndIf
  
  ProcedureReturn CallWindowProc_(GetProp_(hWnd, "InitalizedDockingState"), hWnd.l, uMsg.l, wParam.l, lParam.l)
EndProcedure

Procedure __Docking_InitalizeDocking(GadgetID.l, hParent.l)
  If GetProp_(hParent, "InitalizedDockingState") = 0
    SetProp_(hParent, "InitalizedDockingState", SetWindowLong_(hParent, #GWL_WNDPROC, @__Docking_WndProc()))
  EndIf
  
  Protected *ParentChild.Gadget_ParentChildArray = GetProp_(hParent, "DockingWindowArray")
  Protected *NewDockingGadget.Gadget_ParentChildArray
  
  If *ParentChild
    Repeat
      If *ParentChild\GadgetID = GadgetID
        ProcedureReturn #False ;/ Dieses Gadget wurde schon Initalisiert
      EndIf
      If *ParentChild\Next
        *ParentChild = *ParentChild\Next
      Else
        Break
      EndIf
    ForEver
  EndIf
  
  *NewDockingGadget = AllocateMemory(SizeOf(Gadget_ParentChildArray))
  *NewDockingGadget\GadgetID = GadgetID
  
  If *ParentChild = 0
    SetProp_(hParent, "DockingWindowArray", *NewDockingGadget)
  Else
    *ParentChild\Next = *NewDockingGadget
  EndIf
  
  If Not GetWindowLong_(hParent, #GWL_STYLE) & #WS_CLIPCHILDREN
    SetWindowLong_(hParent, #GWL_STYLE, GetWindowLong_(hParent, #GWL_STYLE) | #WS_CLIPCHILDREN)
  EndIf
EndProcedure
;}

#Flags = #PB_Window_MaximizeGadget|#PB_Window_MinimizeGadget|#PB_Window_ScreenCentered|#PB_Window_SizeGadget|#PB_Window_SystemMenu;|#PB_Window_Invisible
OpenWindow(0, 0, 0, 630, 480, "Dock Example", #Flags)
CreateGadgetList(WindowID(0))
  SmartWindowRefresh(0, 1)

  CreateMenu(1, WindowID(0)) 
  MenuTitle("File") 
    MenuItem(0, "Exit") 
  
  CreateToolBar(2, WindowID(0)) 
    ToolBarStandardButton(0, #PB_ToolBarIcon_New) 
    ToolBarStandardButton(1, #PB_ToolBarIcon_Open) 
  
  CreateStatusBar(3, WindowID(0)) 
    StatusBarText(3, 0, "Welcome to the docking test ;-)") 
  
  ButtonGadget(1, 0, 0, 80, 40, "Left") 
  ButtonGadget(2, 0, 0, 80, 40, "Right") 
  ButtonGadget(3, 0, 0, 80, 50, "Top") 
  ButtonGadget(4, 0, 0, 80, 50, "Bottom") 
  ButtonGadget(5, 0, 0, 80, 40, "Fill") 
  
  Define margin1.Rect
  With margin1
    \left   = 0
    \top    = 0
    \right  = 0
    \bottom = 0
  EndWith     
  SetGadgetMargin(1, @margin1)
  Define margin2.Rect
  With margin2
    \left   = 0
    \top    = 0
    \right  = 0
    \bottom = 0
  EndWith     
  SetGadgetMargin(2, @margin2)
  Define margin3.Rect
  With margin3
    \left   = 0
    \top    = 0
    \right  = 0
    \bottom = 0
  EndWith     
  SetGadgetMargin(3, @margin3)
  Define margin4.Rect
  With margin4
    \left   = 0
    \top    = 0
    \right  = 0
    \bottom = 0
  EndWith     
  SetGadgetMargin(4, @margin4)
  Define margin5.Rect
  With margin5
    \left   = 0
    \top    = 0
    \right  = 0
    \bottom = 0
  EndWith     
  SetGadgetMargin(5, @margin5)
  
  SetGadgetDockingState(1, #Dock_Left  , #False)
  SetGadgetDockingState(2, #Dock_Right , #False)
  SetGadgetDockingState(3, #Dock_Top   , #False)
  SetGadgetDockingState(4, #Dock_Bottom, #False)
  SetGadgetDockingState(5, #Dock_Fill)
SmartWindowRefresh(0, 0) 
HideWindow(0, #False)
Repeat : Until WaitWindowEvent() = #PB_Event_CloseWindow
Benutzeravatar
milan1612
Beiträge: 810
Registriert: 15.04.2007 17:58

Beitrag von milan1612 »

@Leonard
Schön dass es dir gefällt :)
Werd mir deine Änderungen gleich mal anschauen...

EDIT: Könntest du die Bugs die du gefunden hast mal kurz erläutern, dass
ich sie in meine Version mit einbauen kann?
Bin nur noch sehr selten hier, bitte nur noch per PN kontaktieren
Benutzeravatar
NicTheQuick
Ein Admin
Beiträge: 8809
Registriert: 29.08.2004 20:20
Computerausstattung: Ryzen 7 5800X, 64 GB DDR4-3200
Ubuntu 24.04.2 LTS
GeForce RTX 3080 Ti
Wohnort: Saarbrücken

Beitrag von NicTheQuick »

Erstmal Entschuldigung, dass ich hier eine Art Unterthema veranstalte und
das dazu noch im "Code, Tipps und Tricks"-Forum.
Aber da ich dieses XAML (was auch immer das ist) interessant finde, werde
ich wohl sowieso irgendwann mal sowas basteln.
Antworten