PB 5.2 - BindEvent - AttachWindow()

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
STARGÅTE
Kommando SG1
Beiträge: 7032
Registriert: 01.11.2005 13:34
Wohnort: Glienicke
Kontaktdaten:

PB 5.2 - BindEvent - AttachWindow()

Beitrag 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
PB 6.01 ― Win 10, 21H2 ― Ryzen 9 3900X, 32 GB ― NVIDIA GeForce RTX 3080 ― Vivaldi 6.0 ― www.unionbytes.de
Aktuelles Projekt: Lizard - Skriptsprache für symbolische Berechnungen und mehr
Benutzeravatar
ts-soft
Beiträge: 22292
Registriert: 08.09.2004 00:57
Computerausstattung: Mainboard: MSI 970A-G43
CPU: AMD FX-6300 Six-Core Processor
GraKa: GeForce GTX 750 Ti, 2 GB
Memory: 16 GB DDR3-1600 - Dual Channel
Wohnort: Berlin

Re: PB 5.2 - BindEvent - AttachWindow()

Beitrag von ts-soft »

:allright:
sehr nützlich!

Vielleicht ein Modul drausmachen?

Gruß
Thomas
PureBasic 5.73 LTS | SpiderBasic 2.30 | Windows 10 Pro (x64) | Linux Mint 20.1 (x64)
Nutella hat nur sehr wenig Vitamine. Deswegen muss man davon relativ viel essen.
Bild
Benutzeravatar
RSBasic
Admin
Beiträge: 8047
Registriert: 05.10.2006 18:55
Wohnort: Gernsbach
Kontaktdaten:

Re: PB 5.2 - BindEvent - AttachWindow()

Beitrag von RSBasic »

:allright:
Aus privaten Gründen habe ich leider nicht mehr so viel Zeit wie früher. Bitte habt Verständnis dafür.
Bild
Bild
Benutzeravatar
Bisonte
Beiträge: 2471
Registriert: 01.04.2007 20:18

Re: PB 5.2 - BindEvent - AttachWindow()

Beitrag 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....
PureBasic 6.21 (Windows x86/x64) | Windows11 Pro x64 | AsRock B850 Steel Legend Wifi | R7 9800x3D | 64GB RAM | GeForce RTX 5080 | ThermaltakeView 270 TG ARGB | build by vannicom​​
Benutzeravatar
STARGÅTE
Kommando SG1
Beiträge: 7032
Registriert: 01.11.2005 13:34
Wohnort: Glienicke
Kontaktdaten:

Re: PB 5.2 - BindEvent - AttachWindow()

Beitrag 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.
PB 6.01 ― Win 10, 21H2 ― Ryzen 9 3900X, 32 GB ― NVIDIA GeForce RTX 3080 ― Vivaldi 6.0 ― www.unionbytes.de
Aktuelles Projekt: Lizard - Skriptsprache für symbolische Berechnungen und mehr
Benutzeravatar
Bisonte
Beiträge: 2471
Registriert: 01.04.2007 20:18

Re: PB 5.2 - BindEvent - AttachWindow()

Beitrag von Bisonte »

Jetzt wo du das erwähnst... Das muss man doch irgendwie abstellen können.... hm
ich setz mal die Denkkappe auf ;)
PureBasic 6.21 (Windows x86/x64) | Windows11 Pro x64 | AsRock B850 Steel Legend Wifi | R7 9800x3D | 64GB RAM | GeForce RTX 5080 | ThermaltakeView 270 TG ARGB | build by vannicom​​
Antworten