Moving a Dialog with a button?


#1

Trying to find the best way to go about moving a dialog via, left click + drag (holding left mouse button) using a button within the rollout.

So far I got this. It works kind of, but it seems to crash max, and can’t uncheck the button.


try (destroydialog exdialog)
catch ()
global exdialog
rollout exdialog ""
(
	checkbutton moveexdialog "Click + Drag Me" pos:[5,5] width:95 height:20
	button closedialog "Close Me" pos:[105,5] width:55 height:20
	on moveexdialog changed state do
	(
		while state == true do
		(
			origmousepos = (mouse.screenpos - (moveexdialog.pos + [42,7]))
			SetDialogPos exdialog origmousepos
		)
	)
	on closedialog pressed do
	(
		try (destroydialog exdialog)
		catch ()
	)
)
createdialog exdialog width:170 height:30 style:#(#style_sysmenu, #style_minimizebox, #style_normalbox)

Looking for a cleaner way, and something that is hold left mouse button + drag, then on release it un-checks the button.

Please anyone with a solution via maxscript reply with the maxscript.


#2

Found a solution, not sure if its the best, or cleanest but here it is.


try (destroydialog exdialog)
catch ()
global exdialog
rollout exdialog ""
(
	checkbutton moveexdialog "Click + Drag Me" pos:[5,5] width:95 height:20
	button closedialog "Close Me" pos:[105,5] width:55 height:20
	timer themoverollouttimer interval:10 active:false
	on themoverollouttimer tick do
	(
		origmousepos = (mouse.screenpos - (moveexdialog.pos + [42,7]))
		if (GetDialogPos exdialog) != origmousepos do
		(
			SetDialogPos exdialog origmousepos
		)
	)
	on moveexdialog changed state do
	(
		if state == true do
		(
			themoverollouttimer.active = true
		)
		if state == false do
		(
			themoverollouttimer.active = false
		)
	)
	on closedialog pressed do
	(
		try (destroydialog exdialog)
		catch ()
	)
)
createdialog exdialog width:170 height:30 style:#(#style_sysmenu, #style_minimizebox, #style_normalbox)

But I still need to find a way for it to work on left button held on the button, check the checkbutton, then when released needs to uncheck the checkbutton.

Anyone have any ideas?


#3

Here’s a better idea, use a dotnet button:

try (destroydialog exdialog)catch ()
global exdialog
rollout exdialog ""
(
	local mouseOffset = [0,0]
	local dragging = off
	
	dotNetControl moveexdialog "Button" pos:[5,5] width:95 height:20
	button closedialog "Close Me" pos:[105,5] width:55 height:20

	on exDialog open do
	(
		moveexdialog.text = "Move"
	)
	
	on moveexdialog mouseMove do
	(
		if (dragging) do
		(
			local newPos = mouse.screenpos - mouseOffset
			if (GetDialogPos exdialog) != newPos do
			(
				SetDialogPos exdialog newPos
			)
		)
	)
	
	on moveexdialog mousedown do
	(
		mouseOffset = mouse.screenPos - getDialogPos exDialog
		dragging = on
	)
	
	on moveexdialog mouseUp do
	(
		dragging = off
	)
	
	on closedialog pressed do
	(
		try (destroydialog exdialog)
		catch ()
	)
)
createdialog exdialog width:170 height:30 style:#(#style_sysmenu, #style_minimizebox, #style_normalbox)

#4

Ah thanks, exactly what I wanted, but one thing, is it possible to make it into a image button instead of text?


#5

Yes, use the .image property of the button, assign it a system.drawing.bitmap.


#6

Isn’t is useless to check if (GetDialogPos exdialog) != newPos in the mouseMove function?


#7

Got it! mouseMove is fired twice each time, don’t understand why!
Here the modified code for those who want to check.
By the way, love your snippet lo. So clean! :thumbsup:

try (destroydialog exdialog)catch ()
global exdialog
rollout exdialog ""
(
	local mouseOffset = [0,0]
	local dragging = off
	
	dotNetControl moveexdialog "Button" pos:[5,5] width:95 height:20
	button closedialog "Close Me" pos:[105,5] width:55 height:20

	on exDialog open do
	(
		moveexdialog.text = "Move"
	)
	
	on moveexdialog mouseMove do
	(
		if (dragging) do
		(
			local diagPos = GetDialogPos exdialog
			local newPos = mouse.screenpos - mouseOffset
			format "% %
" diagPos newPos 
			if diagPos != newPos then
			(
				SetDialogPos exdialog newPos
				print "moved"
			)
			else
			(
				print "no move "
			)
		)
	)
	
	on moveexdialog mousedown do
	(
		mouseOffset = mouse.screenPos - getDialogPos exDialog
		dragging = on
	)
	
	on moveexdialog mouseUp do
	(
		dragging = off
	)
	
	on closedialog pressed do
	(
		try (destroydialog exdialog)
		catch ()
	)
)
createdialog exdialog width:170 height:30 style:#(#style_sysmenu, #style_minimizebox, #style_normalbox)

#8

Calling SetDialogPos is what fires the second mouseMove event. It can be proved using this code:

on moveexdialog mouseMove do
	(
		if (dragging) do
		(
			local diagPos = GetDialogPos exdialog
			local newPos = mouse.screenpos - mouseOffset
			format "% %
" diagPos newPos 
			if diagPos != newPos then
			(
				dragging = off
				SetDialogPos exdialog newPos
				(dotnetClass "Application").doEvents() --process all queued messages
				dragging = on
				print "moved"
			)
			else
			(
				print "no move "
			)
		)
	)

#9

OK thanks lo! I did dragable rollout before and didn’t notice the double event.
At least I will know next time :slight_smile:


#10

sometimes i don’t want to use any dotnet controls in my mxs dialog… so for many years this works for me:


 try(destroydialog dialog) catch()
 rollout dialog "" width:160 height:20
 (
 	groupbox border width:160 height:26 pos:[0,-6]
 	timer mover active:off interval:50
 	
 	local start
 	on mover tick do if mouse.pos != start do
 	(
 		setdialogpos dialog ((getdialogpos dialog) + mouse.pos - start)
 		start = mouse.pos
 	)
 	on dialog lbuttondown pos do
 	(
 		start = mouse.pos
 		mover.active = on
 	)
 	on dialog lbuttonup pos do mover.active = off
 	on dialog rbuttonup pos do destroydialog dialog
 )
 createDialog dialog style:#()
 

if i want to make some “visual” titlebar i use an imgTag and its events instead of the rollout’s.


#11

Denis, did you used the timer for optimization? (kinda overkill?)
I usually did exactly the same without the timer and a local boolean as replace.


#12

how do you catch mouse moveevent without a timer?
yes… you can do it with rollout mousemove, but as i said i usually use imgTag

also… i did some experiments and found that with timer the motion is smoother and never being lost


#13

Ok denis, I didn’t see the imgTag in your snippet. That’s why I didn’t pay attention to it.
Now I see how your rollouts must look like.
Here’s my version, with “lo’s double event avoidance trick”! :slight_smile:

try(destroydialog UICAcomplete) catch()

rollout UICAcomplete "complete" width:200 height:200
(
	local screenSize = [0,0]
	local DragState = false
	local WinPos = [0,0]
	------------------------------------------------------------------------
	-- avoid out of screen rollout
	fn updatePos pos =
	(
		if (pos.x < 0) do (pos.x = 0); if (pos.y < 0) do (pos.y = 0)
		if (pos.x+UICAcomplete.width > screenSize.x) do (pos.x = screenSize.x-UICAcomplete.width)
		if (pos.y+UICAcomplete.height > screenSize.y) do (pos.y = screenSize.y-UICAcomplete.height)
		setDialogPos UICAcomplete pos
	)
	------------------------------------------------------------------------
	on UICAcomplete open do 
	(
		screenSize = [systemTools.GetScreenWidth(),systemTools.GetScreenHeight()]
		updatePos mouse.screenpos
	)
	------------------------------------------------------------------------
	-- drag
	on UICAcomplete lbuttonup mousepos do DragState = false
	on UICAcomplete lbuttondown mousepos do 
	(
		DragState = true
		WinPos = mousepos
	)
	on UICAcomplete mousemove mousepos do
	(
		if DragState == true do
		(
			localPos = mouse.screenpos-WinPos
			diagPos = GetDialogPos UICAcomplete
			if diagPos != localPos do
			(
				updatePos localPos
			)
		)
	)
	------------------------------------------------------------------------
	on UICAcomplete rbuttondown arg do (destroydialog UICAcomplete)
)

createdialog UICAcomplete style:#()

#14

This thread has been automatically closed as it remained inactive for 12 months. If you wish to continue the discussion, please create a new thread in the appropriate forum.