Registering callbacks in .NET is different than in the C++ SDK. In C++, you can define a single notification handler, register for multiple notifications, and look at the NotifyInfo
passed back to the callback to determine what event happened. In .NET, you must define handlers in your code for each notification type you are interested in receiving.
Here's a C++ example (from the comsrvgup sample project included with the 3ds Max SDK - see samples\gup\comsrv\MaxDocument.cpp), notice that the same handler can be used for different notifications:
//notifications which cause us to revoke our file moniker
RegisterNotification(NotifyProc, this, NOTIFY_SYSTEM_PRE_RESET);
RegisterNotification(NotifyProc, this, NOTIFY_SYSTEM_PRE_NEW);
RegisterNotification(NotifyProc, this, NOTIFY_SYSTEM_SHUTDOWN);
In .NET, RegisterNotification() is used in a similar way , the difference being you must pass separate delegates of type GlobalDelegates.Delegate5
assigned to each callback. Callbacks are unregistered when the plugin is disposed. This ensures that 3ds Max will not attempt to call the function after the plugin has been garbage-collected.
Notification types corresponding to the C++ types defined in notify.h are found in the Autodesk.Max.SystemNotificationCode
enum.
This simple utility plugin illustrates how to register callbacks in .NET:
using System;
using System.Diagnostics;
using System.Windows;
// Max:
using Autodesk.Max;
namespace MaxSDKDocs
{
public class MyMaxCommand : AbstractCustom_CuiActionCommandAdapter
{
static bool bPrompt = true;
GlobalDelegates.Delegate5 unitsChangeHandler, fileSaveHandler;
static bool callbackRegistered = false;
// Handler methods, one for each delegate:
private void Global_UnitsChange(IntPtr obj, IntPtr info)
{
Debug.WriteLine("Units changed...");
}
private void Global_PreFileSave(IntPtr obj, IntPtr info)
{
Debug.WriteLine("About to save...");
}
MessageBoxResult showMessageBoxButton()
{
// Configure message box
string message = "Should I toggle the prompt?";
string caption = "Prompt Dialog";
MessageBoxButton buttons = MessageBoxButton.OKCancel;
MessageBoxImage icon = MessageBoxImage.Question;
MessageBoxResult defaultResult = MessageBoxResult.OK;
// Show message box
return MessageBox.Show(message, caption, buttons, icon, defaultResult);
}
public override string CustomActionText
{
get { return "Max CUI in .NET"; }
}
public override void CustomExecute(object parameter)
{
// Set up global interface:
IGlobal global = Autodesk.Max.GlobalInterface.Instance;
IInterface14 ip = global.COREInterface14;
// register the notification callbacks once:
if (!callbackRegistered)
{
this.unitsChangeHandler = new GlobalDelegates.Delegate5(this.Global_UnitsChange);
GlobalInterface.Instance.RegisterNotification(this.unitsChangeHandler, null, SystemNotificationCode.UnitsChange);
this.fileSaveHandler = new GlobalDelegates.Delegate5(this.Global_PreFileSave);
GlobalInterface.Instance.RegisterNotification(this.fileSaveHandler, null, SystemNotificationCode.FilePreSave);
callbackRegistered = true;
}
MessageBoxResult result = showMessageBoxButton();
if (result == MessageBoxResult.OK)
{
if (bPrompt)
ip.PushPrompt("Hello 3ds Max .Net API");
else
ip.PopPrompt();
bPrompt = !bPrompt;
}
}
}
}