- SplitterGadgetPlus
- SwapSplitter : swap gadgets or/and other options
- DashedSplitterMode : dashed bar mode ( disable if #FALSE )
- DashedSplitterGrip : change grip size for dashed mode (disable if ZERO)
- DashedSplitterThickness : change bar thickness for dashed mode
- SnapSplitterDistance : change snap-to-border distance (disable if ZERO)
- SnapSplitterDoubleClick : snap-to-border via double-click ( disable if #FALSE )
- LockSplitter : lock splitter bar ( unlock if #FALSE )
- SplitterLocked
- SplitterDashed
- * Double-Click event
- * Custom Grip Painter
Code: Select all
Structure SGP_PARAMS
ID.i ;stored original splittergadget ID
CB.i ;stored original splittergadget callback
Flags.i ;stored original splittergadget flags
Dashed.b ;enable dashedbar
Line.i ;current dashed line ID
x.i ;Splitter Pos (for bar position calculation)
y.i ;Splitter Pos (for bar position calculation)
Thickness.i ;Bar Thickness (can't changed)
Parent.i ;Parent (not used)
SnapFirst.i ;Snap for first gadget
SnapSecond.i ;Snap for second gadget
SnapDblClick.b ;Snap to fixed gadget border
UnsnapPos.i ;Unsnap position
Pos.i ;Bar position
Locked.b ;Bar locked
GripWidth.i ;Grip width
GripFocus.b ;Grip focus
*GripPaint ;Grip painter
EndStructure
Procedure SGP_LinesCB(Window, Message, wParam, lParam)
Shared SGP_LineH
Shared SGP_LineV
Shared SGP_Owner
Shared Limit.RECT
Shared Snap.RECT
Protected ID
Protected *SGP_PARAMS.SGP_PARAMS=GetWindowLong_(Window, #GWL_USERDATA)
If *SGP_PARAMS : ID=*SGP_PARAMS\ID : EndIf
Select Message
Case #WM_MOUSEMOVE
;{/// MOVE LINES ( DASHED )
Protected mx=PeekW(@lparam)
Protected my=PeekW(@lparam+2)
Static offx=#PB_Ignore
Static offy=#PB_Ignore
If offx=#PB_Ignore : offx=-mx : EndIf
If offy=#PB_Ignore : offy=-my : EndIf
Protected x=WindowX(SGP_LineV)+mx+offx-*SGP_PARAMS\x
Protected y=WindowY(SGP_LineH)+my+offy-*SGP_PARAMS\y
;snap automaticly
If y<Snap\Top : y=Limit\Top : EndIf
If x<Snap\Left : x=Limit\Left : EndIf
If x>Snap\Right : x=Limit\Right : EndIf
If y>Snap\Bottom : y=Limit\Bottom : EndIf
;move limits
If y<Limit\Top : y=Limit\Top : EndIf
If x<Limit\Left : x=Limit\Left : EndIf
If x>Limit\Right : x=Limit\Right : EndIf
If y>Limit\Bottom : y=Limit\Bottom : EndIf
ResizeWindow(SGP_LineH, #PB_Ignore, y+*SGP_PARAMS\y, #PB_Ignore, #PB_Ignore)
ResizeWindow(SGP_LineV, x+*SGP_PARAMS\x, #PB_Ignore, #PB_Ignore, #PB_Ignore)
;}
;{/// GRIP CURSOR ( DASHED )
Structure SGP_Cursor
arrow.l
vert.l
horz.l
EndStructure
Shared SGP_Cursor.SGP_Cursor
If *SGP_PARAMS\Line=SGP_LineH
SetCursor_(SGP_Cursor\vert)
Else
SetCursor_(SGP_Cursor\horz)
EndIf
;}
Case #WM_LBUTTONUP
Protected Pos=GetGadgetState(ID)
Protected LineY=WindowY(SGP_LineH)-*SGP_PARAMS\y
Protected LineX=WindowX(SGP_LineV)-*SGP_PARAMS\x
;{/// UNSNAP ( DASHED )
If *SGP_PARAMS\UnsnapPos<>#PB_Ignore
If *SGP_PARAMS\Line=SGP_LineH
;fix pixel slide
If *SGP_PARAMS\Dashed=0 And Abs(Pos-Limit\Top)<2 : Pos=Limit\Top : EndIf
If *SGP_PARAMS\Dashed=0 And Abs(Pos-Limit\Bottom)<2 : Pos=Limit\Bottom : EndIf
If (Pos=Limit\Top Or Pos=Limit\Bottom) And Pos=LineY
HideWindow(SGP_LineH, 1)
SetGadgetState(ID, *SGP_PARAMS\UnsnapPos)
*SGP_PARAMS\GripFocus=0
*SGP_PARAMS\UnsnapPos=#PB_Ignore
EndIf
Else
;fix pixel slide
If *SGP_PARAMS\Dashed=0 And Abs(Pos-Limit\Right)<2 : Pos=Limit\Right : EndIf
If *SGP_PARAMS\Dashed=0 And Abs(Pos-Limit\Left)<2 : Pos=Limit\Left : EndIf
If (Pos=Limit\Right Or Pos=Limit\Left) And Pos=LineX
HideWindow(SGP_LineV, 1)
SetGadgetState(ID, *SGP_PARAMS\UnsnapPos)
*SGP_PARAMS\GripFocus=0
*SGP_PARAMS\UnsnapPos=#PB_Ignore
EndIf
EndIf
EndIf
;}
;{/// HIDE LINES ( DASHED )
If IsWindowVisible_(WindowID(*SGP_PARAMS\Line))
If *SGP_PARAMS\Line=SGP_LineH
If (LineY=Limit\Top Or LineY=Limit\Bottom)
If LineY<>*SGP_PARAMS\Pos
*SGP_PARAMS\UnsnapPos=*SGP_PARAMS\Pos
EndIf
Else
*SGP_PARAMS\UnsnapPos=#PB_Ignore
EndIf
SetGadgetState(ID, LineY)
HideWindow(SGP_LineH, 1)
Else
If (LineX=Limit\Right Or LineX=Limit\Left)
If LineX<>*SGP_PARAMS\Pos
*SGP_PARAMS\UnsnapPos=*SGP_PARAMS\Pos
EndIf
Else
*SGP_PARAMS\UnsnapPos=#PB_Ignore
EndIf
SetGadgetState(ID, LineX)
HideWindow(SGP_LineV, 1)
EndIf
EndIf
;}
ReleaseCapture_()
offx=#PB_Ignore
offy=#PB_Ignore
EndSelect
ProcedureReturn #PB_ProcessPureBasicEvents
EndProcedure
Procedure SGP_Lines()
Shared SGP_LineH
Shared SGP_LineV
Shared SGP_Owner
If SGP_LineH And SGP_LineV : ProcedureReturn 0 : EndIf
ExamineDesktops()
Protected w=DesktopWidth(0)
Protected h=DesktopHeight(0)
Protected a=16
Protected b=15
Protected rg0=CreateRectRgn_(0, 0, a, a)
Protected rgH=CreateRectRgn_(0, 0, w, a)
Protected rgV=CreateRectRgn_(0, 0, a, h)
Protected pt=CreateRectRgn_(0, 0, 1, 1)
;{//// DASHED SQUARE
For y=0 To b Step 2
For x=0 To b Step 2
CombineRgn_(rg0, rg0, pt, #RGN_XOR)
OffsetRgn_(pt, 1, 1)
CombineRgn_(rg0, rg0, pt, #RGN_XOR)
OffsetRgn_(pt, 1, -1)
Next
OffsetRgn_(pt, -a, 2)
Next
;}
;{//// DASHED HORIZONTAL
While OffsetRgn<w+1
CombineRgn_(rgH, rgH, rg0, #RGN_XOR)
OffsetRgn_(rg0, a, 0)
OffsetRgn+a
Wend
OffsetRgn_(rg0, -OffsetRgn, 0)
;}
;{//// DASHED VERTICAL
While OffsetRgn<h+1
CombineRgn_(rgV, rgV, rg0, #RGN_XOR)
OffsetRgn_(rg0, 0, a)
OffsetRgn+a
Wend
;}
;{//// CREATE LINES
Protected GadgetListButtonID=ButtonGadget(#PB_Any, 0, 0, 0, 0, "Hidden") ;// Update for PB 4.30b1
Protected GadgetList=GetParent_(GadgetID(GadgetListButtonID)) ;// Update for PB 4.30b1
SGP_Owner=OpenWindow(#PB_Any, 0, 0, 0, 0, "", #PB_Window_Invisible)
If SGP_Owner
SGP_LineH=OpenWindow(#PB_Any, 0, 0, w, a, "", #PB_Window_BorderLess | #PB_Window_Invisible, WindowID(SGP_Owner))
SGP_LineV=OpenWindow(#PB_Any, 9, 9, a, h, "", #PB_Window_BorderLess | #PB_Window_Invisible, WindowID(SGP_Owner))
;set dashed mode
SetWindowRgn_(WindowID(SGP_LineH), rgH, 1)
SetWindowRgn_(WindowID(SGP_LineV), rgV, 1)
;set color
SetWindowColor(SGP_LineH, GetSysColor_(#COLOR_3DSHADOW))
SetWindowColor(SGP_LineV, GetSysColor_(#COLOR_3DSHADOW))
;set callback
SetWindowCallback(@SGP_LinesCB(), SGP_LineH)
SetWindowCallback(@SGP_LinesCB(), SGP_LineV)
Protected result=1
EndIf
FreeGadget(GadgetListButtonID);// Update for PB 4.30b1
UseGadgetList(GadgetList) ;// Update for PB 4.30b1
;}
DeleteObject_(rg0)
DeleteObject_(rgH)
DeleteObject_(rgV)
DeleteObject_(pt)
Shared SGP_Cursor.SGP_Cursor
SGP_Cursor\arrow=LoadCursor_(0, #IDC_ARROW)
SGP_Cursor\vert=LoadCursor_(0, #IDC_SIZENS)
SGP_Cursor\horz=LoadCursor_(0, #IDC_SIZEWE)
ProcedureReturn result
EndProcedure
Procedure SGP_CB(Window, Message, wParam, lParam)
Shared SGP_LineH
Shared SGP_LineV
Shared SGP_Owner
Shared Limit.RECT
Shared Snap.RECT
Protected vertical
Protected focus
Protected bx, by, bw, bh, dx, dy
Protected Pos, x, y, w, h
Protected ID
Protected *SGP_PARAMS.SGP_PARAMS=GetWindowLong_(Window, #GWL_USERDATA)
If *SGP_PARAMS : ID=*SGP_PARAMS\ID : EndIf
Select Message
Case #WM_DESTROY
;{/// FREE GADGET
Protected CB=*SGP_PARAMS\CB
SetWindowLong_(GadgetID(ID), #GWL_WNDPROC, CB)
SetWindowLong_(GadgetID(ID), #GWL_USERDATA, 0)
FreeMemory(*SGP_PARAMS)
ProcedureReturn CallWindowProc_(CB, Window, Message, wParam, lParam)
;}
Case #WM_LBUTTONDOWN
;{/// SHOW LINES
;check if locked
If *SGP_PARAMS\Locked : ProcedureReturn 1 : EndIf
;line linked to gadget
SetWindowLong_(WindowID(*SGP_PARAMS\Line), #GWL_USERDATA, *SGP_PARAMS)
;line position
*SGP_PARAMS\Pos=GetGadgetState(ID)
;line limits
GetClientRect_(GadgetID(ID), @Limit)
GetClientRect_(GadgetID(ID), @Snap)
Limit\Left+GetGadgetAttribute(ID, #PB_Splitter_FirstMinimumSize)
Limit\Top+GetGadgetAttribute(ID, #PB_Splitter_FirstMinimumSize)
Limit\Right-*SGP_PARAMS\Thickness-GetGadgetAttribute(ID, #PB_Splitter_SecondMinimumSize)
Limit\Bottom-*SGP_PARAMS\Thickness-GetGadgetAttribute(ID, #PB_Splitter_SecondMinimumSize)
Snap\Left+*SGP_PARAMS\SnapFirst
Snap\Top+*SGP_PARAMS\SnapFirst
Snap\Right-*SGP_PARAMS\SnapSecond
Snap\Bottom-*SGP_PARAMS\SnapSecond
;line layout
Protected rc.RECT
GetWindowRect_(GadgetID(ID), rc.RECT)
*SGP_PARAMS\x=rc\Left
*SGP_PARAMS\y=rc\Top
ResizeWindow(SGP_LineH, *SGP_PARAMS\x, *SGP_PARAMS\y+GetGadgetState(ID), GadgetWidth(ID), *SGP_PARAMS\Thickness)
ResizeWindow(SGP_LineV, *SGP_PARAMS\x+GetGadgetState(ID), *SGP_PARAMS\y, *SGP_PARAMS\Thickness, GadgetHeight(ID))
;line display
If *SGP_PARAMS\Dashed
If *SGP_PARAMS\GripWidth=0 Or *SGP_PARAMS\GripFocus=1
ShowWindow_(WindowID(*SGP_PARAMS\Line), #SW_SHOWNA)
SetCapture_(WindowID(*SGP_PARAMS\Line))
EndIf
ProcedureReturn 1
EndIf
;}
Case #WM_LBUTTONUP
;{/// HIDE LINES
If *SGP_PARAMS\Dashed=0 And GetCapture_()=GadgetID(ID) And IsWindowVisible_(WindowID(*SGP_PARAMS\Line))
PostMessage_(WindowID(*SGP_PARAMS\Line), #WM_LBUTTONUP, 0, 0)
EndIf
;}
Case #WM_MOUSEMOVE
;{/// MOVE LINES
Pos=GetGadgetState(ID)
x=Pos
y=Pos
If GetCapture_()=GadgetID(ID)
Protected Hide.b=1
;snap automaticly
If *SGP_PARAMS\Line=SGP_LineH
If y<Snap\Top : y=Limit\Top : Hide=0 : EndIf
If y>Snap\Bottom : y=Limit\Bottom : Hide=0 : EndIf
Else
If x<Snap\Left : x=Limit\Left : Hide=0 : EndIf
If x>Snap\Right : x=Limit\Right : Hide=0 : EndIf
EndIf
;snap position preview
x+*SGP_PARAMS\x
y+*SGP_PARAMS\y
ResizeWindow(SGP_LineV, x, #PB_Ignore, #PB_Ignore, #PB_Ignore)
ResizeWindow(SGP_LineH, #PB_Ignore, y, #PB_Ignore, #PB_Ignore)
HideWindow(*SGP_PARAMS\Line, Hide)
EndIf
;}
;{/// GRIP CHECKING
SGP_CB(GadgetID(ID), #WM_TIMER, 2000, 0)
;}
;{/// GRIP CURSOR
If *SGP_PARAMS\Dashed And *SGP_PARAMS\GripWidth
Shared SGP_Cursor.SGP_Cursor
If Not *SGP_PARAMS\GripFocus
SetCursor_(SGP_Cursor\arrow)
ElseIf *SGP_PARAMS\Line=SGP_LineH
SetCursor_(SGP_Cursor\vert)
Else
SetCursor_(SGP_Cursor\horz)
EndIf
EndIf
;}
Case #WM_MOUSELEAVE, #WM_MOUSEHOVER
;{/// GRIP CURSOR
If *SGP_PARAMS\Dashed And *SGP_PARAMS\GripWidth
Shared SGP_Cursor.SGP_Cursor
SetCursor_(SGP_Cursor\arrow)
EndIf
;}
Case #WM_PAINT, #WM_ERASEBKGND
;{/// GRIP PAINT
If Message=#WM_ERASEBKGND ;And IsWindowVisible_(*SGP_PARAMS\Line)=0
; Paint Gadget
; -> Post message to paint grip
; -> Paint Grip
PostMessage_(GadgetID(ID), #WM_UPDATEUISTATE, 1, 1)
PostMessage_(GadgetID(ID), #WM_PAINT, 1, 1)
ElseIf wParam=0 Or lParam=0
; Paint Gadget
; -> Post message to paint grip
; -> Paint Grip
PostMessage_(GadgetID(ID), #WM_UPDATEUISTATE, 1, 1)
PostMessage_(GadgetID(ID), #WM_PAINT, 1, 1)
ElseIf wParam=1 And lParam=1
If *SGP_PARAMS\Dashed And *SGP_PARAMS\GripWidth
vertical=(#True And *SGP_PARAMS\Line=SGP_LineV)
focus=*SGP_PARAMS\GripFocus
If vertical
bw=*SGP_PARAMS\Thickness
bh=*SGP_PARAMS\GripWidth
bx=GetGadgetState(ID)
by=(GadgetHeight(ID)-bh)/2
Else
bw=*SGP_PARAMS\GripWidth
bh=*SGP_PARAMS\Thickness
bx=(GadgetWidth(ID)-bw)/2
by=GetGadgetState(ID)
EndIf
Protected *GadgetOutput=AllocateMemory(4*SizeOf(Long))
PokeL(*GadgetOutput+0*SizeOf(Long), 1) ;Type.l
PokeL(*GadgetOutput+1*SizeOf(Long), GadgetID(ID)) ;Windows.l
PokeL(*GadgetOutput+2*SizeOf(Long), 0) ;DC.l
PokeL(*GadgetOutput+3*SizeOf(Long), 0) ;ReleaseProc.l
StartDrawing(*GadgetOutput)
If *SGP_PARAMS\GripPaint
;{/// USE CUSTOM PAINTER
CallFunctionFast(*SGP_PARAMS\GripPaint, bx, by, bw, bh, vertical, focus)
;}
Else
;{/// USE DEFAULT PAINTER
Protected foreColor
Protected backColor
foreColor+(#True And focus=0)*GetSysColor_(#COLOR_3DFACE)
foreColor+(#True And focus>0)*GetSysColor_(#COLOR_SCROLLBAR)
;background rectangle
Box(bx, by, bw, bh, foreColor)
If vertical
;borders
Line(bx, by+0, bw, 0, GetSysColor_(#COLOR_BTNSHADOW))
Line(bx, by+1, bw, 0, GetSysColor_(#COLOR_BTNHILIGHT))
Line(bx, by+bh-2, bw, 0, GetSysColor_(#COLOR_BTNSHADOW))
Line(bx, by+bh-1, bw, 0, GetSysColor_(#COLOR_BTNHILIGHT))
;dots
For dy=10 To bh-10 Step 3
Line(bx+bw/2-1, by+dy, 2, 0, GetSysColor_(#COLOR_BTNSHADOW))
Next
Else
;borders
Line(bx+0, by, 0, bh, GetSysColor_(#COLOR_BTNSHADOW))
Line(bx+1, by, 0, bh, GetSysColor_(#COLOR_BTNHILIGHT))
Line(bx+bw-2, by, 0, bh, GetSysColor_(#COLOR_BTNSHADOW))
Line(bx+bw-1, by, 0, bh, GetSysColor_(#COLOR_BTNHILIGHT))
;dots
For dx=10 To bw-10 Step 3
Line(bx+dx, by+bh/2-1, 0, 2, GetSysColor_(#COLOR_BTNSHADOW))
Next
EndIf
;}
EndIf
StopDrawing()
FreeMemory(*GadgetOutput)
EndIf
EndIf
;}
Case #WM_TIMER
;{/// GRIP CHECKING
If wParam=2000 And *SGP_PARAMS\Dashed And *SGP_PARAMS\GripWidth
vertical=(#True And *SGP_PARAMS\Line=SGP_LineV)
focus=*SGP_PARAMS\GripFocus
If vertical
bw=*SGP_PARAMS\Thickness
bh=*SGP_PARAMS\GripWidth
bx=GetGadgetState(ID)
by=(GadgetHeight(ID)-bh)/2
Else
bw=*SGP_PARAMS\GripWidth
bh=*SGP_PARAMS\Thickness
bx=(GadgetWidth(ID)-bw)/2
by=GetGadgetState(ID)
EndIf
GetCursorPos_(@mouse.POINT)
ScreenToClient_(GadgetID(ID), @mouse.POINT)
If mouse\x>=bx And mouse\x<=bx+bw And mouse\y>=by And mouse\y<=by+bh
If *SGP_PARAMS\GripFocus=0
*SGP_PARAMS\GripFocus=1
SetTimer_(GadgetID(ID), 2000, 100, 0)
SGP_CB(GadgetID(ID), #WM_PAINT, 1, 1)
EndIf
Else
If *SGP_PARAMS\GripFocus=1
*SGP_PARAMS\GripFocus=0
KillTimer_(GadgetID(ID), 2000)
SGP_CB(GadgetID(ID), #WM_PAINT, 1, 1)
EndIf
EndIf
EndIf
;}
Case #WM_UPDATEUISTATE
;{/// BAR THICKNESS
If (wParam=1 And lParam=1)
Protected ModifiedThickness
ModifiedThickness+(#True And *SGP_PARAMS\Thickness=4 And (*SGP_PARAMS\Flags & #PB_Splitter_Separator)=0)
ModifiedThickness+(#True And *SGP_PARAMS\Thickness=7 And (*SGP_PARAMS\Flags & #PB_Splitter_Separator))
If Not ModifiedThickness
Protected ID1=GetGadgetAttribute(ID, #PB_Splitter_FirstGadget)
Protected ID2=GetGadgetAttribute(ID, #PB_Splitter_SecondGadget)
vertical=(#True And *SGP_PARAMS\Line=SGP_LineV)
If vertical
x=GadgetX(ID1)+GadgetWidth(ID1)+*SGP_PARAMS\Thickness
w=GadgetWidth(ID)-x
ResizeGadget(ID2, x, #PB_Ignore, w, #PB_Ignore)
Else
y=GadgetY(ID1)+GadgetHeight(ID1)+*SGP_PARAMS\Thickness
h=GadgetHeight(ID)-y
ResizeGadget(ID2, #PB_Ignore, y, #PB_Ignore, h)
EndIf
EndIf
EndIf
;}
Case #WM_LBUTTONDBLCLK
;{/// DOUBLE-CLICK EVENT
Protected wp
Protected lp
PokeW(@wp+0, ID)
PokeW(@wp+2, #PB_EventType_LeftDoubleClick)
lp=GadgetID(ID)
PostMessage_(*SGP_PARAMS\Parent, #WM_COMMAND, wp, lp)
;}
;{/// DOUBLE-CLICK SNAP
Select *SGP_PARAMS\SnapDblClick
Case 1
*SGP_PARAMS\UnsnapPos=*SGP_PARAMS\Pos
*SGP_PARAMS\GripFocus=0
SetGadgetState(ID, 0)
Case 2
*SGP_PARAMS\UnsnapPos=*SGP_PARAMS\Pos
*SGP_PARAMS\GripFocus=0
SetGadgetState(ID, GadgetWidth(ID)+GadgetHeight(ID))
Default
EndSelect
;}
Case #WM_WINDOWPOSCHANGED
Default
EndSelect
ProcedureReturn CallWindowProc_(*SGP_PARAMS\CB, Window, Message, wParam, lParam)
EndProcedure
ProcedureDLL SplitterGadgetPlus(ID, x, y, w, h, Gadget1, Gadget2, Flags=0, Dashed.b=#True, SnapFirst=0, SnapSecond=0)
Shared SGP_LineH
Shared SGP_LineV
Shared SGP_Owner
SGP_Lines()
;gadget
If IsGadget(ID) : FreeGadget(ID) : EndIf
Protected result=SplitterGadget(ID, x, y, w, h, Gadget1, Gadget2, Flags)
If result=0 : ProcedureReturn 0 : EndIf
If ID=#PB_Any : ID=result : EndIf
;gadget parent
Protected Parent=GadgetID(ID)
While GetParent_(Parent) : Parent=GetParent_(Parent) : Wend
;set style
Protected style=GetClassLong_(GadgetID(ID), #GCL_STYLE) | #CS_DBLCLKS
SetClassLong_(GadgetID(ID), #GCL_STYLE, style)
;set callback
Protected CB=SetWindowLong_(GadgetID(ID), #GWL_WNDPROC, @SGP_CB())
;set parameters
Protected *SGP_PARAMS.SGP_PARAMS=AllocateMemory(SizeOf(SGP_PARAMS))
*SGP_PARAMS\ID=ID
*SGP_PARAMS\CB=CB
*SGP_PARAMS\Dashed=Dashed
*SGP_PARAMS\Flags=Flags
*SGP_PARAMS\Thickness+4*(#True And (Flags & #PB_Splitter_Separator)=0)
*SGP_PARAMS\Thickness+7*(#True And (Flags & #PB_Splitter_Separator))
*SGP_PARAMS\Line+SGP_LineH*(#True And (Flags & #PB_Splitter_Vertical)=0)
*SGP_PARAMS\Line+SGP_LineV*(#True And (Flags & #PB_Splitter_Vertical))
*SGP_PARAMS\Parent=Parent
*SGP_PARAMS\SnapFirst=SnapFirst
*SGP_PARAMS\SnapSecond=SnapSecond
*SGP_PARAMS\UnsnapPos=#PB_Ignore
SetWindowLong_(GadgetID(ID), #GWL_USERDATA, *SGP_PARAMS)
SetTimer_(GadgetID(ID), 100, 500, 0)
ProcedureReturn result
EndProcedure
ProcedureDLL SnapSplitterDistance(ID, SnapFirst, SnapSecond) ; change snap-to-border distance (disable if ZERO)
Protected Window=GadgetID(ID)
Protected *SGP_PARAMS.SGP_PARAMS=GetWindowLong_(Window, #GWL_USERDATA)
*SGP_PARAMS\SnapFirst=SnapFirst
*SGP_PARAMS\SnapSecond=SnapSecond
EndProcedure
ProcedureDLL SnapSplitterDoubleClick(ID, DblClickToSnap.b=1) ; snap-to-border via double-click (disable if #FALSE)
Protected Window=GadgetID(ID)
Protected *SGP_PARAMS.SGP_PARAMS=GetWindowLong_(Window, #GWL_USERDATA)
*SGP_PARAMS\SnapDblClick=0
If DblClickToSnap
If *SGP_PARAMS\Flags & #PB_Splitter_FirstFixed
*SGP_PARAMS\SnapDblClick=1
EndIf
If *SGP_PARAMS\Flags & #PB_Splitter_SecondFixed
*SGP_PARAMS\SnapDblClick=2
EndIf
EndIf
EndProcedure
ProcedureDLL DashedSplitterThickness(ID, Thickness) ; change bar thickness for dashed mode
Protected Window=GadgetID(ID)
Protected *SGP_PARAMS.SGP_PARAMS=GetWindowLong_(Window, #GWL_USERDATA)
;check if out of range
If Thickness>16 : Thickness=16 : EndIf
If Thickness<4 : Thickness=4 : EndIf
;dashed mode with modified bar thickness
*SGP_PARAMS\Dashed=1
*SGP_PARAMS\Thickness=Thickness
PostMessage_(GadgetID(ID), #WM_UPDATEUISTATE, 1, 1)
EndProcedure
ProcedureDLL DashedSplitterGrip(ID, gripWidth, gripPaintProc=0) ; change grip size for dashed mode (disable if ZERO)
Protected Window=GadgetID(ID)
Protected *SGP_PARAMS.SGP_PARAMS=GetWindowLong_(Window, #GWL_USERDATA)
;dashed mode with grip button ( optional custom grip painter )
*SGP_PARAMS\Dashed=1
*SGP_PARAMS\GripWidth=gripWidth
*SGP_PARAMS\GripPaint=gripPaintProc
EndProcedure
ProcedureDLL DashedSplitterMode(ID, Dashed.b=1) ; enable dashed mode (disable if #FALSE)
Protected Window=GadgetID(ID)
Protected *SGP_PARAMS.SGP_PARAMS=GetWindowLong_(Window, #GWL_USERDATA)
*SGP_PARAMS\Dashed=Dashed
EndProcedure
ProcedureDLL SwapSplitter(ID, SwapBarPosition.b=1, SwapBorderSnap.b=1, SwapMinimumSize.b=1, SwapFixedGadget.b=1, SwapGadgets.b=1) ; swap gadgets and other options
Protected *SGP_PARAMS.SGP_PARAMS=GetWindowLong_(GadgetID(ID), #GWL_USERDATA)
Protected Thickness=*SGP_PARAMS\Thickness
Protected Dashed=*SGP_PARAMS\Dashed
Protected GripWidth=*SGP_PARAMS\GripWidth
Protected GripPaint=*SGP_PARAMS\GripPaint
If SwapFixedGadget
If *SGP_PARAMS\Flags & #PB_Splitter_FirstFixed
*SGP_PARAMS\Flags | #PB_Splitter_SecondFixed & ~#PB_Splitter_FirstFixed
ElseIf *SGP_PARAMS\Flags & #PB_Splitter_SecondFixed
*SGP_PARAMS\Flags | #PB_Splitter_FirstFixed & ~#PB_Splitter_SecondFixed
EndIf
EndIf
Protected SnapDblClick=*SGP_PARAMS\SnapDblClick
Protected SnapFirst=*SGP_PARAMS\SnapFirst
Protected SnapSecond=*SGP_PARAMS\SnapSecond
If SwapBorderSnap
Swap SnapFirst, SnapSecond
EndIf
Protected Min1=GetGadgetAttribute(ID, #PB_Splitter_FirstMinimumSize)
Protected Min2=GetGadgetAttribute(ID, #PB_Splitter_SecondMinimumSize)
If SwapMinimumSize
Swap Min1, Min2
EndIf
Protected Gadget1=GetGadgetAttribute(ID, #PB_Splitter_FirstGadget)
Protected Gadget2=GetGadgetAttribute(ID, #PB_Splitter_SecondGadget)
If SwapGadgets
Swap Gadget1, Gadget2
EndIf
Protected Pos=GetGadgetState(ID)
If SwapBarPosition
Shared SGP_LineH
Shared SGP_LineV
Shared SGP_Owner
Pos+(GadgetHeight(ID)-2*Pos-Thickness)*(#True And *SGP_PARAMS\Line=SGP_LineH)
Pos+(GadgetWidth(ID)-2*Pos-Thickness)*(#True And *SGP_PARAMS\Line=SGP_LineV)
EndIf
UseGadgetList(GetParent_(GadgetID(ID)));fix multi-windows
Protected Gadget0=ButtonGadget(#PB_Any, 0, 0, 0, 0, "HiddenGadget")
SetGadgetAttribute(ID, #PB_Splitter_FirstGadget, Gadget0)
SetGadgetAttribute(ID, #PB_Splitter_SecondGadget, Gadget0)
SplitterGadgetPlus(ID, GadgetX(ID), GadgetY(ID), GadgetWidth(ID), GadgetHeight(ID), Gadget1, Gadget2, *SGP_PARAMS\Flags)
SetGadgetAttribute(ID, #PB_Splitter_FirstMinimumSize, Min1)
SetGadgetAttribute(ID, #PB_Splitter_SecondMinimumSize, Min2)
SnapSplitterDistance(ID, SnapFirst, SnapSecond)
SnapSplitterDoubleClick(ID, SnapDblClick)
DashedSplitterGrip(ID, GripWidth, GripPaint)
DashedSplitterThickness(ID, Thickness)
DashedSplitterMode(ID, Dashed)
SetGadgetState(ID, Pos)
EndProcedure
ProcedureDLL LockSplitter(ID, Locked.b=1) ; lock splitter bar (unlock if #FALSE)
Protected Window=GadgetID(ID)
Protected *SGP_PARAMS.SGP_PARAMS=GetWindowLong_(Window, #GWL_USERDATA)
*SGP_PARAMS\Locked=Locked
EndProcedure
ProcedureDLL.b SplitterLocked(ID) ;Returns #True if splitter is locked
Protected Window=GadgetID(ID)
Protected *SGP_PARAMS.SGP_PARAMS=GetWindowLong_(Window, #GWL_USERDATA)
ProcedureReturn *SGP_PARAMS\Locked
EndProcedure
ProcedureDLL.b SplitterDashed(ID) ;Returns #True if splitter is dashed
Protected Window=GadgetID(ID)
Protected *SGP_PARAMS.SGP_PARAMS=GetWindowLong_(Window, #GWL_USERDATA)
ProcedureReturn *SGP_PARAMS\Dashed
EndProcedure
; ********************
; EXAMPLE @ eddy
; ********************
Procedure CustomGripPaint(bx, by, bw, bh, vertical, focus)
Protected foreColor
Protected backColor
foreColor+(#True And focus=0)*#White
foreColor+(#True And focus>0)*#Red
;background rectangle
Box(bx, by, bw, bh, foreColor)
If vertical
;borders
Line(bx, by+0, bw, 0, GetSysColor_(#COLOR_BTNSHADOW))
Line(bx, by+1, bw, 0, GetSysColor_(#COLOR_BTNHILIGHT))
Line(bx, by+bh-2, bw, 0, GetSysColor_(#COLOR_BTNSHADOW))
Line(bx, by+bh-1, bw, 0, GetSysColor_(#COLOR_BTNHILIGHT))
;dots
For dy=10 To bh-10 Step 3
Line(bx+bw/2-1, by+dy, 2, 0, GetSysColor_(#COLOR_BTNSHADOW))
Next
Else
;borders
Line(bx+0, by, 0, bh, GetSysColor_(#COLOR_BTNSHADOW))
Line(bx+1, by, 0, bh, GetSysColor_(#COLOR_BTNHILIGHT))
Line(bx+bw-2, by, 0, bh, GetSysColor_(#COLOR_BTNSHADOW))
Line(bx+bw-1, by, 0, bh, GetSysColor_(#COLOR_BTNHILIGHT))
;dots
For dx=10 To bw-10 Step 3
Line(bx+dx, by+bh/2-1, 0, 2, GetSysColor_(#COLOR_BTNSHADOW))
Next
EndIf
EndProcedure
If OpenWindow(0, 0, 0, 410, 440, "Dashed SplitterGadget And Auto Snap-To-Border", #PB_Window_SizeGadget | #PB_Window_SystemMenu)
CompilerIf #PB_Compiler_Version<430
CreateGadgetList(WindowID(0))
CompilerEndIf
ButtonGadget(300, 5, 5, 80, 20, "SWAP")
ContainerGadget(800, 0, 0, 0, 0, #PB_Container_Double) : CloseGadgetList()
ContainerGadget(801, 0, 0, 0, 0, #PB_Container_Double) : CloseGadgetList()
SplitterGadgetPlus(3, 5, 30, 0, 0, 800, 801, #PB_Splitter_FirstFixed)
SetGadgetAttribute(3, #PB_Splitter_FirstMinimumSize, 10)
SetGadgetAttribute(3, #PB_Splitter_SecondMinimumSize, 10)
DashedSplitterGrip(3, 200);(3, 200, @CustomGripPaint())
DashedSplitterThickness(3, 8)
SnapSplitterDistance(3, 50, 100)
SnapSplitterDoubleClick(3, #True)
EndIf
If OpenWindow(1, 220, 220, 410, 440, "SplitterGadget : enable / disable options", #PB_Window_SizeGadget | #PB_Window_SystemMenu)
CompilerIf #PB_Compiler_Version<430
CreateGadgetList(WindowID(1))
CompilerEndIf
CheckBoxGadget(100, 5, 5, 80, 20, "LOCKED")
CheckBoxGadget(101, 100, 5, 80, 20, "DASHED")
CheckBoxGadget(102, 200, 5, 120, 20, "SNAP-TO-BORDER")
SetGadgetState(100, #False)
SetGadgetState(101, #True)
SetGadgetState(102, #True)
ContainerGadget(700, 0, 0, 0, 0, #PB_Container_Double) : CloseGadgetList()
ContainerGadget(701, 0, 0, 0, 0, #PB_Container_Double) : CloseGadgetList()
SplitterGadgetPlus(6, 5, 30, 0, 0, 700, 701, #PB_Splitter_Vertical | #PB_Splitter_Separator | #PB_Splitter_FirstFixed, #True)
SnapSplitterDistance(6, 90, 90)
EndIf
Repeat
Select WaitWindowEvent()
Case #PB_Event_CloseWindow
End
Case #PB_Event_SizeWindow
Select EventWindow()
Case 0
ResizeGadget(3, #PB_Ignore, #PB_Ignore, WindowWidth(0)-10, WindowHeight(0)-40)
Case 1
ResizeGadget(6, #PB_Ignore, #PB_Ignore, WindowWidth(1)-10, WindowHeight(1)-40)
EndSelect
Case #PB_Event_Gadget
Select EventType()
Case #PB_EventType_LeftDoubleClick
If EventGadget()=3
Debug "Double-Click"
EndIf
Case #PB_EventType_LeftClick
Select EventGadget()
Case 300
SwapSplitter(3)
Case 100
LockSplitter(6, GetGadgetState(100))
Case 101
DashedSplitterMode(6, GetGadgetState(101))
Case 102
SnapSplitterDistance(6, 90*GetGadgetState(102), 90*GetGadgetState(102))
EndSelect
EndSelect
EndSelect
ForEver