[Closed] Close event handler on native window
it there a way to get close event handler when closing any of the native 3ds max dialogs like ( material editor, render setup , light lister , max listener, etc ) by pressing the the “X” button or alt+f4 ?
i want to make that action trigger something to be done
If you want to keep it simple just probe once a second if any of these windows are still open. Otherwise you’ll need to use window sub-classing or hooks like SetWinEventHook
i want a certain macro button to be unchecked when the dialog get closed
is the two methods you provided are the only methods ?
are they your scripted macros?
if so, we can use the isChecked handler.
for example:
on ischecked do MatEditor.isOpen()
material editor, render setup , light lister
so it’s not possible for these
I’m curious what’s cheaper to use performance wise. SetWinEventHook or a timer that simply checks if a certain window is opened at the moment?
SetWinEventHook
global WinHook =
(
source = "using System;\n"
source += "using System.Runtime.InteropServices;\n"
source += "class WinHook\n"
source += "{
public class MsgEventArgs : EventArgs
{
public MsgEventArgs( IntPtr hwnd, uint eventType )
{
HWND = hwnd;
EventType = eventType;
}
public readonly IntPtr HWND;
public readonly uint EventType;
}
public static event EventHandler MessageEvent;
public static IntPtr hWinHook;
delegate void WinEventDelegate(IntPtr hWinEventHook, uint eventType,
IntPtr hwnd, int idObject, int idChild, uint dwEventThread, uint dwmsEventTime);
[DllImport(\"user32.dll\")]
static extern IntPtr SetWinEventHook(uint eventMin, uint eventMax, IntPtr
hmodWinEventProc, WinEventDelegate lpfnWinEventProc, uint idProcess,
uint idThread, uint dwFlags);
[DllImport(\"user32.dll\")]
static extern bool UnhookWinEvent(IntPtr hWinEventHook);
const uint EVENT_OBJECT_CREATE = 0x8000;
const uint EVENT_SYSTEM_DESTROY = 0x8001;
const uint WINEVENT_OUTOFCONTEXT = 0;
static WinEventDelegate procDelegate = new WinEventDelegate(WinEventProc);
public static void Start( uint procID, uint threadID )
{
hWinHook = SetWinEventHook(EVENT_OBJECT_CREATE, EVENT_SYSTEM_DESTROY, IntPtr.Zero,
procDelegate, procID, threadID, WINEVENT_OUTOFCONTEXT);
}
public static void Stop()
{
if ( hWinHook != null ) UnhookWinEvent( hWinHook );
}
static void WinEventProc(IntPtr hWinEventHook, uint eventType,
IntPtr hwnd, int idObject, int idChild, uint dwEventThread, uint dwmsEventTime)
{
if(idObject != 0 || idChild != 0)
{
return;
}
if ( MessageEvent != null )
{
MsgEventArgs msg = new MsgEventArgs( hwnd, eventType );
MessageEvent( null, msg );
}
}
"
source += "}\n"
csharpProvider = dotnetobject "Microsoft.CSharp.CSharpCodeProvider"
compilerParams = dotnetobject "System.CodeDom.Compiler.CompilerParameters"
compilerParams.ReferencedAssemblies.Add("System.dll");
compilerParams.GenerateInMemory = on
compilerResults = csharpProvider.CompileAssemblyFromSource compilerParams #(source)
if (compilerResults.Errors.Count > 0 ) then
(
local errs = stringstream ""
for i = 0 to (compilerResults.Errors.Count-1) do
(
local err = compilerResults.Errors.Item[i]
format "Error:% Line:% Column:% %\n" err.ErrorNumber err.Line err.Column err.ErrorText to:errs
)
format "%\n" errs
undefined
)
else
(
compilerResults.CompiledAssembly.CreateInstance "WinHook"
)
)
fn OnMsg s ev =
(
if ev.EventType == 0x8000 do
(
format "[ create ] %: %\n" ev.HWND (windows.getHWNDData ev.hwnd)
)
if ev.EventType == 0x8001 do
(
format "[ destroy ] %: %\n" ev.HWND (windows.getHWNDData ev.hwnd)
)
)
WinHook.Stop()
dotNet.removeAllEventHandlers WinHook
proc = (dotNetClass "System.Diagnostics.Process").GetCurrentProcess()
thread = GetCurrentThreadId()
dotNet.addEventHandler WinHook "MessageEvent" OnMsg
WinHook.Start proc.ID thread
i read in the setwineventhook and from what i undertand that their will be a backgroud proccess always monitoring the window until its closed
does the subclassing works the same ?
Yes, but when subclassing a window you override WndProc of each window individually. Search for MessageSnooper and you’ll find a few mxs examples
you only need to check WS_VISIBLE window flag… you can do GetWindowLong(hWnd, GWL_STYLE) and test for WS_VISIBLE.
or IsWindowVisible in win32
i found this old amazing post that does exactly what i want but with created dialogs rollouts not with native max dialogs like ( material editor , etc)
Thanks, Light. Since I’m new to Maxscript, it’s going to take a little while to digest what’s going on exactly, but I think you’ve given me enought to start digging on my on. Thank you.
I’m curious what good the closeDialogs handler is then, if it’s not needed in order to change the state of the button back to “unchecked”. Your method here is superior because it actually unchecks the button if the floater is closed by hitting the windows “x” button. The closeDialogs handler doesn’t do that.
denisT:
on ischecked do MatEditor.isOpen()
actually what am trying to do is the exact opposite to make the button unchecked when the window get closed
will that be triggered with me closing using the X button or i have to attach it to a timer ?
Recent Topics
-
Need help with script to automate certain things
By siddhartha 7 days ago
-
By Dave 3 months ago
-
By MZ1 1 year ago
-
By brianstorm 1 year ago
-
By MZ1 1 year ago
-
Support class with multiple name (C#,SDK)
By MZ1 1 year ago
-
How to sort subarrays for Mat ID swapping
By brianstorm 1 year ago