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
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
Code: Alles auswählen
DockGadget(Gadget, DockState, MarginLeft, MarginRight, MarginTop, MargineBottom)
Code: Alles auswählen
UnDockGadget(Gadget)
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