So, hab ganz vergessen das die 2. Version schon länger fertig ist.
Komplett neugeschrieben und (hoffentlich) ein bisschen schneller.
Das Grundkonzept bleibt das gleiche, allerdings ist die Bedienung jetzt etwas
komplizierter. Einfach mal das Beispiel anschauen oder die Include durchforsten.
Sollte einigermaßen gut kommentiert sein...
Die Include:
Code: Alles auswählen
;PureBasic Dock Include
;Second Edition
;Copyright 2008 - milan1612
;milan1612@gmx.de
EnableExplicit
;-== Public Interface ======================================
Enumeration
#DockNone
#DockLeft
#DockRight
#DockTop
#DockBottom
#DockFill
EndEnumeration
Structure Dock
DockState.l
MarginLeft.l
MarginRight.l
MarginTop.l
MarginBottom.l
RedrawOnCall.l
AntiFlicker.l
EndStructure
DeclareDLL SetGadgetDock(Gadget.l, *Options.Dock)
DeclareDLL IsGadgetDocked(Gadget.l)
;-== Implementation =========================================
;Internal Declarations
Declare UpdateDockInfo(Gadget.l, *Options.Dock)
Declare DockSubclassParent(Gadget.l)
Declare DockWindowCallback(WindowID.l, Message.l, wParam.l, lParam.l)
Declare FreeGadgetInfoCallback(GadgetID.l, UnUsed.l)
Declare CalculateClientArea(WindowID.l, *Rect.RECT)
Declare StatusToolBarEnumCallback(WindowID.l, Parent.l)
Declare DockGadgets(WindowID.l)
Declare DockEnumCallback(GadgetID.l, *Rect.RECT)
;Main Initialization Procedure (see Dock Structure above)
ProcedureDLL SetGadgetDock(Gadget.l, *Options.Dock)
Protected *MemID.Dock
If *Options
If Not IsGadget(Gadget) : ProcedureReturn 0 : EndIf
If IsGadgetDocked(Gadget)
If *Options\DockState = #DockNone
*MemID = GetProp_(GadgetID(Gadget), @"_DockInfo")
If *MemID
FreeMemory(*MemID)
RemoveProp_(GadgetID(Gadget), @"_DockInfo")
EndIf
Else
UpdateDockInfo(Gadget, *Options)
EndIf
ProcedureReturn 1
EndIf
*MemID = AllocateMemory(SizeOf(Dock))
If *MemID
DockSubclassParent(Gadget)
CopyMemory(*Options, *MemID, SizeOf(Dock))
SetProp_(GadgetID(Gadget), @"_DockInfo", *MemID)
EnumChildWindows_(GetParent_(GadgetID(Gadget)), @StatusToolBarEnumCallback(), GetParent_(GadgetID(Gadget)))
If *Options\RedrawOnCall
SendMessage_(GetParent_(GadgetID(Gadget)), #WM_SIZE, 0, 0)
InvalidateRect_(GetParent_(GadgetID(Gadget)), 0, 0)
EndIf
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
If GadgetType(Gadget) = #PB_GadgetType_Frame3D
If Not GetWindowLong_(GadgetID(Gadget), #GWL_EXSTYLE) & #WS_EX_TRANSPARENT
SetWindowLong_(GadgetID(Gadget), #GWL_EXSTYLE, GetWindowLong_(GadgetID(Gadget), #GWL_EXSTYLE) | #WS_EX_TRANSPARENT)
EndIf
EndIf
If GadgetType(Gadget) = #PB_GadgetType_Panel
If Not GetWindowLong_(GadgetID(Gadget), #GWL_EXSTYLE) & #WS_EX_COMPOSITED
SetWindowLong_(GadgetID(Gadget), #GWL_EXSTYLE, GetWindowLong_(GadgetID(Gadget), #GWL_EXSTYLE) | #WS_EX_COMPOSITED)
EndIf
EndIf
EndIf
Else
ProcedureReturn 0
EndIf
ProcedureReturn 1
EndProcedure
;Checks if the gadget is docked, if true it returns the address to the stored dockinfo
ProcedureDLL IsGadgetDocked(Gadget.l)
If IsGadget(Gadget)
ProcedureReturn GetProp_(GadgetID(Gadget), @"_DockInfo")
Else
ProcedureReturn 0
EndIf
EndProcedure
;-== Internals ==============================================
;Updates the stored dockinfo
Procedure UpdateDockInfo(Gadget.l, *Options.Dock)
Protected *MemID.Dock
*MemID = GetProp_(GadgetID(Gadget), @"_DockInfo")
If *MemID
CopyMemory(*Options, *MemID, SizeOf(Dock))
EndIf
EndProcedure
;Subclasses (if necessary) the parent of the child
Procedure DockSubclassParent(Gadget.l)
Protected ParentHandle.l
Protected OldProc.l
ParentHandle = GetParent_(GadgetID(Gadget))
OldProc = GetProp_(ParentHandle, @"_OldProcAddress")
If Not OldProc
OldProc = SetWindowLong_(ParentHandle, #GWL_WNDPROC, @DockWindowCallback())
SetProp_(ParentHandle, @"_OldProcAddress", OldProc)
EndIf
EndProcedure
;The gadgets parent callback
Procedure DockWindowCallback(WindowID.l, Message.l, wParam.l, lParam.l)
Protected OldProc.l
Protected Result.l
Protected Buffer.s
OldProc = GetProp_(WindowID, @"_OldProcAddress")
Select Message
Case #WM_DESTROY
EnumChildWindows_(WindowID, @FreeGadgetInfoCallback(), 1)
Case #WM_NCDESTROY
RemoveProp_(WindowID, @"_OldProcAddress")
Case #WM_SIZE
DockGadgets(WindowID)
Case #WM_PARENTNOTIFY
If wParam & $FFFF = #WM_CREATE Or wParam & $FFFF = #WM_DESTROY
Buffer = Space(100)
If GetClassName_(lParam, @Buffer, 100)
Buffer = LCase(Buffer)
If Buffer = "toolbarwindow32"
If wParam & $FFFF = #WM_CREATE
SetProp_(WindowID, @"_ToolBarHandle", lParam)
Else
RemoveProp_(WindowID, @"_ToolBarHandle")
EndIf
ElseIf Buffer = "msctls_statusbar32"
If wParam & $FFFF = #WM_CREATE
SetProp_(WindowID, @"_StatusBarHandle", lParam)
Else
RemoveProp_(WindowID, @"_StatusBarHandle")
EndIf
EndIf
EndIf
EndIf
Default
Result = CallWindowProc_(OldProc, WindowID, Message, wParam, lParam)
EndSelect
ProcedureReturn Result
EndProcedure
;EnumChildWindows Callback to free the stored memory of the gadgets when destroyed
Procedure FreeGadgetInfoCallback(GadgetID.l, UnUsed.l)
Protected *DockID.Dock
*DockID = GetProp_(GadgetID, @"_DockInfo")
If *DockID
FreeMemory(*DockID)
RemoveProp_(GadgetID, @"_DockInfo")
EndIf
ProcedureReturn 1
EndProcedure
;Calculates the rectangle that is then used to position the gadgets
Procedure CalculateClientArea(WindowID.l, *Rect.RECT)
Protected StatusBar, ToolBar
Protected TempRect.RECT
GetClientRect_(WindowID, *Rect.RECT)
StatusBar = GetProp_(WindowID, @"_StatusBarHandle")
ToolBar = GetProp_(WindowID, @"_ToolBarHandle")
If ToolBar
GetWindowRect_(ToolBar, @TempRect)
*Rect\top + (TempRect\bottom - TempRect\top) + 2
SendMessage_(ToolBar, #WM_SIZE, 0, 0)
EndIf
If StatusBar
GetWindowRect_(StatusBar, @TempRect)
*Rect\bottom - (TempRect\bottom - TempRect\top)
SendMessage_(StatusBar, #WM_SIZE, 0, 0)
EndIf
EndProcedure
;EnumChildWindows Callback to find & identify possible status- and toolbars
Procedure StatusToolBarEnumCallback(WindowID.l, Parent.l)
Protected Buffer.s = Space(100)
If GetClassName_(WindowID, @Buffer, 100)
Buffer = LCase(Buffer)
If Buffer = "toolbarwindow32"
SetProp_(Parent, @"_ToolBarHandle", WindowID)
ElseIf Buffer = "msctls_statusbar32"
SetProp_(Parent, @"_StatusBarHandle", WindowID)
EndIf
EndIf
ProcedureReturn 1
EndProcedure
;Handles the entire dock process
Procedure DockGadgets(WindowID.l)
Protected Rect.RECT
LockWindowUpdate_(WindowID)
CalculateClientArea(WindowID, @Rect)
EnumChildWindows_(WindowID, @DockEnumCallback(), @Rect)
LockWindowUpdate_(0)
UpdateWindow_(WindowID)
EndProcedure
;EnumChildWindows Callback to dock the gadgets
;Warning: Enumerates Child-childs as well (todo)
Procedure DockEnumCallback(GadgetID.l, *Rect.RECT)
Protected *Info.Dock
Protected GadgetX, GadgetY, GadgetW, GadgetH
Protected GadgetRect.RECT
*Info = GetProp_(GadgetID, @"_DockInfo")
If *Info
GetWindowRect_(GadgetID, @GadgetRect)
If *Info\AntiFlicker
SendMessage_(GadgetID, #WM_SETREDRAW, 0, 0)
EndIf
Select *Info\DockState
Case #DockLeft
GadgetX = *Rect\left + *Info\MarginLeft
GadgetY = *Rect\top + *Info\MarginTop
GadgetW = GadgetRect\right - GadgetRect\left
GadgetH = *Rect\bottom - *Rect\top - *Info\MarginTop - *Info\MarginBottom
*Rect\left = *Rect\left + *Info\MarginLeft + (GadgetRect\right - GadgetRect\left) + *Info\MarginRight
Case #DockRight
GadgetX = (*Rect\right - (GadgetRect\right - GadgetRect\left)) - *Info\MarginRight
GadgetY = *Rect\top + *Info\MarginTop
GadgetW = GadgetRect\right - GadgetRect\left
GadgetH = (*Rect\bottom - *Rect\top) - (*Info\MarginTop + *Info\MarginBottom)
*Rect\right = *Rect\right - (*Info\MarginRight + *Info\MarginLeft) - (GadgetRect\right - GadgetRect\left)
Case #DockTop
GadgetX = *Rect\left + *Info\MarginLeft
GadgetY = *Rect\top + *Info\MarginTop
GadgetW = (*Rect\right - *Rect\left) - (*Info\MarginLeft + *Info\MarginRight)
GadgetH = GadgetRect\bottom - GadgetRect\top
*Rect\top = *Rect\top + *Info\MarginTop + (GadgetRect\bottom - GadgetRect\top) + *Info\MarginBottom
Case #DockBottom
GadgetX = *Rect\left + *Info\MarginLeft
GadgetY = *Rect\bottom - (GadgetRect\bottom - GadgetRect\top) - *Info\MarginBottom
GadgetW = *Rect\right - *Rect\left - *Info\MarginLeft - *Info\MarginRight
GadgetH = (GadgetRect\bottom - GadgetRect\top)
*Rect\bottom = *Rect\bottom - (*Info\MarginBottom + *Info\MarginTop + (GadgetRect\bottom - GadgetRect\top))
Case #DockFill
GadgetX = *Rect\left + *Info\MarginLeft
GadgetY = *Rect\top + *Info\MarginTop
GadgetW = *Rect\right - *Rect\left - *Info\MarginLeft - *Info\MarginRight
GadgetH = *Rect\bottom - *Rect\top - *Info\MarginTop - *Info\MarginBottom
EndSelect
MoveWindow_(GadgetID, GadgetX, GadgetY, GadgetW, GadgetH, 1)
If *Info\AntiFlicker
SendMessage_(GadgetID, #WM_SIZE, 0, 0)
SendMessage_(GadgetID, #WM_SETREDRAW, 1, 0)
InvalidateRect_(GadgetID, 0, 0)
EndIf
EndIf
ProcedureReturn 1
EndProcedure
Und ein kleines Beispiel:
Code: Alles auswählen
;IncludeFile "Dock.pb"
#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))
ButtonGadget(0, 0, 0, 80, 20, "Left")
ButtonGadget(1, 0, 0, 80, 20, "Right")
ButtonGadget(2, 0, 0, 80, 40, "Top")
ButtonGadget(3, 0, 0, 80, 40, "Bottom")
ButtonGadget(4, 0, 0, 80, 20, "Fill")
Define info.Dock
info\DockState = #DockLeft
info\MarginLeft = 2
info\MarginTop = 2
info\MarginBottom = 2
info\AntiFlicker = 1
SetGadgetDock(0, @info)
ZeroMemory_(@info, SizeOf(Dock))
info\DockState = #DockRight
info\MarginRight = 2
info\MarginTop = 2
info\MarginBottom = 2
info\AntiFlicker = 1
SetGadgetDock(1, @info)
ZeroMemory_(@info, SizeOf(Dock))
info\DockState = #DockTop
info\MarginLeft = 2
info\MarginRight = 2
info\MarginTop = 2
info\AntiFlicker = 1
SetGadgetDock(2, @info)
ZeroMemory_(@info, SizeOf(Dock))
info\DockState = #DockBottom
info\MarginLeft = 2
info\MarginRight = 2
info\MarginBottom = 2
info\AntiFlicker = 1
SetGadgetDock(3, @info)
ZeroMemory_(@info, SizeOf(Dock))
info\DockState = #DockFill
info\MarginLeft = 2
info\MarginRight = 2
info\MarginBottom = 2
info\MarginTop = 2
info\RedrawOnCall = 1
info\AntiFlicker = 1
SetGadgetDock(4, @info)
Repeat : Until WaitWindowEvent() = #PB_Event_CloseWindow
Bitte nicht hauen falls was nicht funktionieren sollte (ist schon ne Weile her)
