[Closed] Moving a Dialog with a button?
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.
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?
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)
Ah thanks, exactly what I wanted, but one thing, is it possible to make it into a image button instead of text?
Yes, use the .image property of the button, assign it a system.drawing.bitmap.
Isn’t is useless to check if (GetDialogPos exdialog) != newPos in the mouseMove function?
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!
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)
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 "
)
)
)
OK thanks lo! I did dragable rollout before and didn’t notice the double event.
At least I will know next time
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.
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.
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
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”!
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:#()