[Closed] Modal dialog and mouse
I’ve created two dialogs, we can call them now MainDialog(non-modal) and SubDialog(modal). MainDialog is opened first and when button is pressed, SubDialog opens. SubDialog does some stuff and then closes itself.
Problem is, that when the SubDialog is open and I press mouse button over some MainDialog control(for example checkbox) the MainDialog’s control gets that mouse command AFTER the SubDialog is closed (unchecked checkbox becomes checked etc.). I dont want user to interact with MainDialog controls at all when SubDialog is open.
Is there a way to prevent this for happening? Of course I could use some flags to check if SubDialog is open dont check buttons blahblah, but i’m looking for better way
there is no easy way to temporally disable mouse click in MXS, but if you want to know how to do it using c# I can give you the snippet…
Cheap hack could be to lock (.enabled = false) the Main-Dialog options on Sub-Dialog open, or assign them to variables, and then unlock (.enabled = true) them or reassign the original values from the variables on Sub-Dialog close.
-Eric
the problem is: you can protect your ui elements, but you can’t protect max ui or max viewports from clicking…
I was responding to this statement: of:
In which my example does what was asked for. You are correct in that it won’t lock interaction with the UI, but VVaari seemed to be more concerned with the With locking the MainDialog interaction.
-Eric
…but VVaari seemed to be more concerned with the With locking the MainDialog interaction.
because he doesn’t know yet how bad with max interaction is…
What about the CreateDialog modal:<boolean> setting? Set this to true on the Sub Dialog and you can’t access anything in Max outside that dialog. Problem you may run into is if you set the main dialog to modal and launch a new dialog, in this case the modal precident has been set by the main dialog, and you can’t override that with the sub dialog.
-Eric
Modal dialog is definitely a solution in many cases. But it doesn’t work in some another. Lets say I want to have a progress bar as a window. I have some run process in my main tool (dialog) and I want to show the progress in other window. In this case I cant make secondary dialog modal…
I understand that it isn’t perfect, but so far both of my options will work for the case presented here. I will let VVaari figure out what really does and doesn’t work for what he is trying to do.
-Eric
Thanks guys for answers!
I already have SubDialog as modal. It’s kind of loading dialog where user doesn’t click anything, he just waits and after stuff is loaded, SubDialog closes. But if the user clicks mouse over some MainDialog or Max UI component while SubDialog is running, component gets “activated” after SubDialog is closed. It’s like mouse click gets stored in some “mouse-click-buffer” and it gets released after SubDialog closes
I have done cheap hack for my MainDialog where components gets enabled after SubDialog is closed. I was just wondering if there is better way. I don’t really care about Max UI components here.
denisT, sure would be nice to see how its done in C#
Here is it:
/* C# code
using System.Runtime.InteropServices;
class Input
{
[DllImport(“user32.dll”)]
public static extern bool BlockInput(bool fBlockIt);
}
*/
The BlockInput function blocks keyboard and mouse input events from reaching applications.
/*********** Compile C# ON FLY ************/
fn getInputClass =
(
source = ""
source += "using System.Runtime.InteropServices;
"
source += "class Input
"
source += "{
"
source += " [DllImport(\"user32.dll\")]
"
source += " public static extern bool BlockInput(bool fBlockIt);
"
source += "}
"
-- Compile on fly
csharpProvider = dotnetobject "Microsoft.CSharp.CSharpCodeProvider"
compilerParams = dotnetobject "System.CodeDom.Compiler.CompilerParameters"
compilerParams.GenerateInMemory = on
compilerResults = csharpProvider.CompileAssemblyFromSource compilerParams #(source)
input = compilerResults.CompiledAssembly.CreateInstance "Input"
)
/****** Sample ************/
try(destroydialog theRol) catch()
global theTimer -- it's better to have it global
rollout theRol "Block Input by denisT"
(
label lb "" align:#left offset:[0,2]
local ticks = 0, input
fn testTimer =
(
fn printTime =
(
lb.text = "Local Time: " + localtime
ticks += 1
if keyboard.escpressed or ticks > 10 do -- keyboard.escpressed BLOCKED
(
theTimer.stop()
input.BlockInput off -- UNBLOCK Input
try(destroydialog theRol) catch()
)
)
theTimer = dotNetObject "System.Windows.Forms.Timer" --create Timer for 10 ticks
dotnet.addEventHandler theTimer "tick" printTime
theTimer.interval = 1000
theTimer.start()
theTimer
)
on theRol open do
(
input = getInputClass()
lb.text = "Local Time: " + localtime
input.BlockInput on -- BLOCK Input
theTimer = testTimer()
)
)
createDialog theRol width:200 height:30 modal:on -- (it might not be modal)
/************************************/
if you are interested how to hide/show and position mouse cursor let me know…
That snippet looks interesting and the way you can generate C#-code inside maxscript is totally new to me, thanks a lot!
Would it be possible to create something like maxscript’s mouseTracker() using C#? I guess it would but how hard is it? I don’t like mouseTracker that much because you can’t stop tracking unless cursor goes over viewport, so starting and stopping tracking using rollout controls doesn’t work. Atleast I haven’t figured out how to do it.
You can stop tracking using rollout controls
try(destroydialog mouseTracker) catch()
rollout mouseTracker "Mouse Tracking"
(
local act = off
fn mouseTracking msg ir obj faceNum shift ctrl alt =
(
if msg == #mouseAbort or msg == undefined or not act then #abort else #continue
)
button start "Start" width:80 across:2
button stop "Stop" width:80
on start pressed do
(
start.enabled = not (act = on)
mouseTrack trackCallback:mouseTracking
start.enabled = not (act = off)
)
on stop pressed do act = off
)
createDialog mouseTracker width:190 height:30