Developers can use the tabbed dialog system to create their own tabbed dialogs as well as working with 3ds Max's own tabbed dialogs. The steps below present a how-to guide for doing this. Theses step
Define a unique Class_ID
for each tab, and for each tabbed dialog, you are creating.
There are predefined IDs for some standard dialogs:
TAB_DIALOG_PREFERENCES_ID
- preferences dialogTAB_DIALOG_PROPERTIES_ID
- object properties dialogTAB_DIALOG_PATH_ID
- customize paths dialogTAB_DIALOG_RENDER_ID
- render dialogTAB_DIALOG_VIDEO_POST_ID
- video postTAB_DIALOG_ENVIRONMENT_ID
- environment dialogFor each tab, create one implementation of ITabDialogPluginTab
. If you have a group of tabs that will always appear together, you need only one implementation for the whole group.
Your ITabDialogPluginTab::AddTabToDialog()
method should call dialog
->AddPage() or dialog
->AddRollout().
Pass the tab's name, your dialog template, and the message procedure. Make sure to pass the class ID you've defined for the tab.
If you have a group of tabs appearing together, you can add multiple pages or rollouts to the dialog.
These steps are optional. You can implement some or all of these options if you want tabs to show and hide dynamically according to the state of the dialog
ITabDialogPluginTab::AcceptDialog()
. This method indicates whether a tab is willing to reside in a given dialogITabDialogFilter
and override its ITabDialogFilter::AcceptTab()
method. The return value indicates if a dialog is willing to accept a given tab. The return value TAB_DIALOG_ADD_TAB
means the tab should be displayed. The return value TAB_DIALOG_REMOVE_TAB
means the tab should not be displayed and will be removed. Returning both values combined using "or" means the tab will be removed, and immediately re-displayed. Note: A tab only appears if both the dialog and the tab agreePluginTab
and the DialogFilter
have some optional methods that you can implement if your Accept()
methods need them. These are: GetReferenceMaker()
, GetAnimatable()
, GetClassID()
, and GetSuperClassID()
. These allow your Accept()
methods to distinguish one tab from another, or one dialog from another. The ITabDialogPluginTab
can return the class ID of the tab it's associated with, and the ITabDialogFilter
can return the class ID of the dialog it is associated with.Your ITabDialogPluginTab
and ITabDialogFilter
(if any) need to be registered with the manager. The manager itself can be obtained with the global function GetTabDialogManager()
.
First call ITabDialogManager::RegisterTab()
to register a ITabDialogPluginTab
, indicating the ID of the dialog tjat the tab should be used with. You may register a tab with multiple different dialogs.
Next, if you have ITabDialogFilter
then call ITabDialogManager::SetTabFilter()
to register it indicating the ID of the dialog
To handle window messages for your tabs and dialogs, you can to create implementations of ITabPageProc
(one for each tab) and ITabDialogProc
(one for each dialog). For each of these, the only method to implement is dialogProc()
.
These classes have a number of convenience methods, like Commit()
, Close()
, and Cancel()
, which simply call the dialogProc()
with certain preset parameters.
At this point, you are ready to launch the dialog.
First call ITabDialogManager::CreateTabbedDialog()
on the dialog manager returned from GetTabDialogManager()
passing the dialog's ITabDialogProc
and the class ID defined for the dialog. If your dialog template already contains a tab control UI element, pass its ID in the tabID
parameter, otherwise pass -1. The other parameters are explained in the method's code comment in the header file.
Next call the ITabbedDialog::DoFloater()
or ITabbedDialog::DoModal()
method on the ITabbedDialog
that is returned from CreateTabbedDialog()
. For modeless dialogs, each call to ITabbedDialog::SyncRegisteredTabs()
will refresh the tab set, hiding and showing tabs as needed.
The following classes are implemented by the system:
ITabDialogManager
ITabPage
ITabbedDialog
TabDialogPointer
- This is a "smart pointer" provided for convenience, it allows the dialog to be disposed when the pointer goes out of scopeThe following classes are implemented by the plug-in:
ITabDialogPluginTab
ITabDialogFilter
ITabDialogProc
ITabPageProc
ITabDialogObject
- this is specifically for use with renderer plug-ins, see IRendParams
.Renderers should use AddTabRollupPage()
to add their rollup to the render dialog, but AddRollupPage()
should be used when adding a rollout to the progress dialog.
In 3ds Max, the render dialog will always display the "Common" tab and the renderer's individual parameter tab. It will display the "Raytracer" and "Advanced Lighting" tab only if the renderer chooses to display them. The "Render Elements" tab is displayed only if the renderer supports the IRenderElementCompatible
interface.
To control which tabs are displayed, a renderer can provide an ITabDialogObject interface and implement AcceptTab().
For an example of tabbed dialogs see cjrender sample located in \\maxsdk
\samples\render\cjrender.