Tabbed Dialogs

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

1. Define ID numbers

Define a unique Class_ID for each tab, and for each tabbed dialog, you are creating.

There are predefined IDs for some standard dialogs:

2. ITabDialogPluginTab class

For 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.

3. Add tabs to the dialog

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.

4. Tab filters (optional)

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

  1. Implement ITabDialogPluginTab::AcceptDialog(). This method indicates whether a tab is willing to reside in a given dialog
  2. Implement an ITabDialogFilter 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 agree
  3. Both the PluginTab 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.

5. Registering with the manager

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 ITabDialogFilterthen call ITabDialogManager::SetTabFilter()to register it indicating the ID of the dialog

6. Message handlers

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.

7. Launch the dialog

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 ITabbedDialogthat is returned from CreateTabbedDialog(). For modeless dialogs, each call to ITabbedDialog::SyncRegisteredTabs()will refresh the tab set, hiding and showing tabs as needed.

Summary of Classes

The following classes are implemented by the system:

The following classes are implemented by the plug-in:

About Tabbed dialogs in the Renderer

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 More Information

For an example of tabbed dialogs see cjrender sample located in \maxsdk\samples\render\cjrender.