Seite 1 von 1

PB 5.2 - BindEvent - AttachWindow()

Verfasst: 26.06.2013 17:33
von STARGÅTE
Tachchen,

auch ich habe mit PB 5.20 und der neuen Funktion BindEvent() rumgespielt und damit dieses kleine Include gebastelt:

Mit AttachWindow(Window, ParentWindow [, Attributes]) kann man ein Fenster (Window) mit einem anderes Fenster (ParentWindow) verknüpfen.
Im normalen Modus (#AttachedWindow_PositionDifference), verschiebt sich das Fenster immer in abhängigkeit wo das ParentWindow ist.
Im #AttachedWindow_FrameDifference-Modus reagiert das Fenster auch auf eine Größenänderung, wenn es rechts/unten positioniert ist.
Mit #AttachedWindow_Magnetic kann ein Magneteffekt dazu geschaltet werden, sodass es zum andock-effekt kommt, wenn das Fenster nahe beim ParentWindow ist.

Und dank BindEvent() alles ohne API.

Code: Alles auswählen

Enumeration
	#AttachedWindow_PositionDifference = %000
	#AttachedWindow_FrameDifference    = %001
	#AttachedWindow_Magnetic           = %010
EndEnumeration


Structure AttachedWindow
	Attributes.i
	Window.i
	ParentWindow.i
	AlignX.i
	AlignY.i
	DeltaX.i
	DeltaY.i
EndStructure

Global NewList AttachedWindow.AttachedWindow()

Macro AttachedWindow_MagneticX(ShiftX)
	If Abs(AttachedWindow()\DeltaX-ShiftX) < 25
		AttachedWindow()\DeltaX = ShiftX
		PushListPosition(AttachedWindow())
		ResizeWindow(AttachedWindow()\Window, WindowX(AttachedWindow()\ParentWindow, #PB_Window_FrameCoordinate)+AttachedWindow()\DeltaX, #PB_Ignore, #PB_Ignore, #PB_Ignore)
		PopListPosition(AttachedWindow())
	EndIf
EndMacro

Macro AttachedWindow_MagneticY(ShiftY)
	If Abs(AttachedWindow()\DeltaY-(ShiftY)) < 25
		AttachedWindow()\DeltaY = ShiftY
		PushListPosition(AttachedWindow())
		ResizeWindow(AttachedWindow()\Window, #PB_Ignore, WindowY(AttachedWindow()\ParentWindow, #PB_Window_FrameCoordinate)+AttachedWindow()\DeltaY, #PB_Ignore, #PB_Ignore)
		PopListPosition(AttachedWindow())
	EndIf
EndMacro

Procedure AttachedWindow_FollowCallback()
	Protected ParentWindow.i = EventWindow()
	Protected Window.i = EventWindow()
	ForEach AttachedWindow()
		With AttachedWindow()
			If \ParentWindow = ParentWindow
				PushListPosition(AttachedWindow())
				If \Attributes & #AttachedWindow_FrameDifference 
					If \AlignX And \AlignY
						ResizeWindow(\Window, WindowX(ParentWindow)+WindowWidth(ParentWindow, #PB_Window_FrameCoordinate)+\DeltaX-\AlignX, WindowY(ParentWindow)+WindowHeight(ParentWindow, #PB_Window_FrameCoordinate)+\DeltaY-\AlignY, #PB_Ignore, #PB_Ignore)
					ElseIf \AlignX
						ResizeWindow(\Window, WindowX(ParentWindow)+WindowWidth(ParentWindow, #PB_Window_FrameCoordinate)+\DeltaX-\AlignX, WindowY(ParentWindow)+\DeltaY, #PB_Ignore, #PB_Ignore)
					ElseIf \AlignY
						ResizeWindow(\Window, WindowX(ParentWindow)+\DeltaX, WindowY(ParentWindow)+WindowHeight(ParentWindow, #PB_Window_FrameCoordinate)+\DeltaY-\AlignY, #PB_Ignore, #PB_Ignore)
					Else
						ResizeWindow(\Window, WindowX(ParentWindow)+\DeltaX, WindowY(ParentWindow)+\DeltaY, #PB_Ignore, #PB_Ignore)
					EndIf
				Else
					ResizeWindow(\Window, WindowX(ParentWindow)+\DeltaX, WindowY(ParentWindow)+\DeltaY, #PB_Ignore, #PB_Ignore)
				EndIf
				PopListPosition(AttachedWindow())
			ElseIf \Window = Window
				\DeltaX = WindowX(\Window) - WindowX(\ParentWindow)
				\DeltaY = WindowY(\Window) - WindowY(\ParentWindow)
				If \Attributes & #AttachedWindow_FrameDifference And \DeltaX > (WindowWidth(\ParentWindow, #PB_Window_FrameCoordinate)-WindowWidth(\Window, #PB_Window_FrameCoordinate))/2
					\AlignX = WindowWidth(\ParentWindow, #PB_Window_FrameCoordinate)
				Else
					\AlignX = 0
				EndIf
				If \Attributes & #AttachedWindow_FrameDifference And \DeltaY > (WindowHeight(\ParentWindow, #PB_Window_FrameCoordinate)-WindowHeight(\Window, #PB_Window_FrameCoordinate))/2
					\AlignY = WindowHeight(\ParentWindow, #PB_Window_FrameCoordinate)
				Else
					\AlignY = 0
				EndIf
				If \Attributes & #AttachedWindow_Magnetic
					AttachedWindow_MagneticX(-WindowWidth(\Window, #PB_Window_FrameCoordinate))
					AttachedWindow_MagneticX(0)
					AttachedWindow_MagneticX(WindowWidth(\ParentWindow, #PB_Window_FrameCoordinate))
					AttachedWindow_MagneticX((WindowWidth(\ParentWindow, #PB_Window_FrameCoordinate)-WindowWidth(\Window, #PB_Window_FrameCoordinate)))
					AttachedWindow_MagneticY(-WindowHeight(\Window, #PB_Window_FrameCoordinate))
					AttachedWindow_MagneticY(0)
					AttachedWindow_MagneticY(WindowHeight(\ParentWindow, #PB_Window_FrameCoordinate))
					AttachedWindow_MagneticY((WindowHeight(\ParentWindow, #PB_Window_FrameCoordinate)-WindowHeight(\Window, #PB_Window_FrameCoordinate)))
				EndIf
			EndIf
		EndWith
	Next
EndProcedure

Procedure AttachWindow(Window.i, ParentWindow.i, Attributes.i=#AttachedWindow_PositionDifference)
	AddElement(AttachedWindow())
	With AttachedWindow()
		\Attributes   = Attributes
		\Window       = Window
		\ParentWindow = ParentWindow
		\DeltaX       = WindowX(Window) - WindowX(ParentWindow)
		\DeltaY       = WindowY(Window) - WindowY(ParentWindow)
		If \Attributes & #AttachedWindow_FrameDifference And \DeltaX > (WindowWidth(\ParentWindow, #PB_Window_FrameCoordinate)-WindowWidth(\Window, #PB_Window_FrameCoordinate))/2
			\AlignX = WindowWidth(\ParentWindow, #PB_Window_FrameCoordinate)
		Else
			\AlignX = 0
		EndIf
		If \Attributes & #AttachedWindow_FrameDifference And \DeltaY > (WindowHeight(\ParentWindow, #PB_Window_FrameCoordinate)-WindowHeight(\Window, #PB_Window_FrameCoordinate))/2
			\AlignY = WindowHeight(\ParentWindow, #PB_Window_FrameCoordinate)
		Else
			\AlignY = 0
		EndIf
	EndWith
	BindEvent(#PB_Event_MoveWindow, @AttachedWindow_FollowCallback(), ParentWindow)
	If Attributes & #AttachedWindow_FrameDifference
		BindEvent(#PB_Event_SizeWindow, @AttachedWindow_FollowCallback(), ParentWindow)
	EndIf
	BindEvent(#PB_Event_MoveWindow, @AttachedWindow_FollowCallback(), Window)
EndProcedure

Procedure DetachWindow(Window.i)
	ForEach AttachedWindow()
		If AttachedWindow()\Window = Window
			DeleteElement(AttachedWindow())
		EndIf
	Next
	UnbindEvent(#PB_Event_MoveWindow, @AttachedWindow_FollowCallback(), ParentWindow)
	UnbindEvent(#PB_Event_SizeWindow, @AttachedWindow_FollowCallback(), ParentWindow)
	UnbindEvent(#PB_Event_MoveWindow, @AttachedWindow_FollowCallback(), Window)
EndProcedure




;- Example

Enumeration
	#Window_Main
	#Window_Child1
	#Window_Child2
	#Window_SubChild
	#Gadget
EndEnumeration


OpenWindow(#Window_Main, 300, 200, 400, 400, "Main", #PB_Window_MinimizeGadget|#PB_Window_SizeGadget|#PB_Window_ScreenCentered)

OpenWindow(#Window_Child1, WindowX(#Window_Main)+50, WindowY(#Window_Main, #PB_Window_FrameCoordinate)+50, 200, 300, "Child 1 (Position Attach)", #PB_Window_SizeGadget, WindowID(#Window_Main))
AttachWindow(#Window_Child1, #Window_Main)

OpenWindow(#Window_Child2, WindowX(#Window_Main)+WindowWidth(#Window_Main, #PB_Window_FrameCoordinate), WindowY(#Window_Main, #PB_Window_FrameCoordinate), 200, 300, "Child 2 (Frame Magnetic)", #PB_Window_SizeGadget, WindowID(#Window_Main))
AttachWindow(#Window_Child2, #Window_Main, #AttachedWindow_FrameDifference|#AttachedWindow_Magnetic)

OpenWindow(#Window_SubChild, WindowX(#Window_Child2), WindowY(#Window_Child2, #PB_Window_FrameCoordinate)+WindowHeight(#Window_Child2, #PB_Window_FrameCoordinate), 200, 100, "SubChild", #PB_Window_SizeGadget, WindowID(#Window_Child2))
AttachWindow(#Window_SubChild, #Window_Child2, #AttachedWindow_FrameDifference)

Repeat
	
	Event = WaitWindowEvent()
	
	Select Event
		Case #PB_Event_CloseWindow
			End
	EndSelect
	
ForEver

Re: PB 5.2 - BindEvent - AttachWindow()

Verfasst: 26.06.2013 17:46
von ts-soft
:allright:
sehr nützlich!

Vielleicht ein Modul drausmachen?

Gruß
Thomas

Re: PB 5.2 - BindEvent - AttachWindow()

Verfasst: 26.06.2013 18:35
von RSBasic
:allright:

Re: PB 5.2 - BindEvent - AttachWindow()

Verfasst: 26.06.2013 20:03
von Bisonte
Sieht gut aus, Aber warum fängt das "Child 2" Fenster bösartig an zu flackern, wenn man das Main Fenster mit der MAus
in der Höhe verändert (kleiner machen) ? Das geht soweit, das das Programm crasht....

Ich werd mal die b3 installiern, vielleicht siehts da ganz anders aus ;)

Edit : Leider nein... Gleiches Flackern bis zum Crash....

Re: PB 5.2 - BindEvent - AttachWindow()

Verfasst: 26.06.2013 22:12
von STARGÅTE
@Bisonte: Das hat einen "ganz Einfachen" Grund:
Im Modus: #AttachedWindow_Magnetic versucht der Callback ja das Fenster immer an einer Seiten auszurichten.
Wenn du nun das Fenster gerade so vergrößerst, dass es theoretisch an beiden Seiten einrasten könnte, dann macht es das auch, und zwar für immer: Erst rastet er oben ein, somit kommt es zu einem #PB_Event_MoveWindow Event, also rastet er wieder unten ein, was wieder ein #PB_Event_MoveWindow erzeugt usw.

Das (Endlosschleife) ist/war ein absehbares Problem bei Callbacks in BindEvent(), welche selbst wieder ein Event erzeugen, was mit dem Callback verbunden ist.

Re: PB 5.2 - BindEvent - AttachWindow()

Verfasst: 26.06.2013 22:22
von Bisonte
Jetzt wo du das erwähnst... Das muss man doch irgendwie abstellen können.... hm
ich setz mal die Denkkappe auf ;)