How To > Use ActiveX Controls> Develop a Selected Objects Inspector - Part One |
This tutorial will demonstrate how to set up an ActiveX Control in a MAXScript rollout to display details about selected scene objects.
ActiveX Controls have been deprecated by Microsoft in the latest versions of the Windows operating system in favor of the DotNet framework and its controls.
While MAXScript still supports ActiveX controls, these have to be installed and registered on the system to be accessible to MAXScript.
As a replacement of ActiveX controls, MAXScript supports DotNet controls in 3ds Max 9 and higher.
Please see the topic Converting ActiveX ListView Control to DotNet ListView Control
ActiveX Controls in MAXScript Rollouts
ListView ActiveX Control Example
We start by defining a simple MacroScript with the name SceneListview which will appear in the category "HowTo". Simple (old-style) macroScripts do not have on execute do or on isEnabled event handlers. The code inside the MacroScript definition is executed immediately when the ActionItem (button, menu item or keyboard shortcut) representing the MacroScript is activated.
This is the rollout to be created when the MacroScript is executed. It will display the title "ListView Selected". The variable listview_rollout will be local to the macroScript and will be used later on to create a dialog out of the rollout definition.
This is the function which will perform the initialization of the ListView ActiveX control we will create. The control itself will be passed as argument to the function.
We want the ListViewControl to display grid lines.
We also want to see the column headers, so we define the view type as lvwReport.
By setting this property to true, we ensure that selecting a row will select across all columns.
This user variable is assigned an array containing the names of the columns to be created.
The i loop will go through all elements of the array defined above. Inside the loop, a new column will be created for each entry in the array.
By calling the function add() in the ColumnHeaders property of the listview, we add a new column to the list. A reference to the column is returned and written in the user variable "column", so we can now access properties of the column.
For example, we can set the text in the column header to the string stored in the array we are looping through.
This is the end of the i loop..
This is the end of the function.
This is the function which will fill in the data of the selected scene objects into the Listview ActiveX control. The control itself will be passed as argument to the function.
This loop will iterate through all objects currently selected in the scene. The variable o will contain one object at a time, the loop will repeat as ofter as there are objects in the selection set.
We add a new row to the Listview.
Then we set the text displayed in the first column of the list to the name of the object.
Now we add a new sub-item (which is basically the following column) by calling the .add() method in the ListSubItems property of the current listItem (which represents the first column). The result is written into the user variable sub_li
We can now set the .text property of the new column to the class of the current object. Since the result of classof() is not a string, we have to explicitly convert it to string before assigning it to the .text property.
We create a third column the same way as above and assign the number of vertices in the mesh of the current object to the .text property of the new column. Since the number of vertices is returned as an integer, we have to convert it to a string before assigning it to the .text property.
Some of the selected objects might not have a .mesh property (for example lights, helpers, cameras, targetObjects etc.) In these cases, trying to access o.mesh.numverts would cause an error. For these cases, we put the try()catch() error trap. If the attempt to read the vertex count fails, we assign the string "--" to the .text property of the sub-list item instead.
We create another column the same way as above and assign the number of f aces in the mesh of the current object to the .text property of the new column. Since the number of faces is returned as an integer, we have to convert it to a string before assigning it to the .text property.
Some of the selected objects might not have a .mesh property (for example lights, helpers, cameras, targetObjects etc.) In these cases, trying to access o.mesh.numfaces would cause an error. For these cases, we put the try()catch() error trap. If the attempt to read the face count fails, we assign the string "--" to the .text property of the sub-list item instead.
Finally, we create another column the same way as above and assign the material of the current object to the .text property of the new column. Objects without a material will display "undefined" in the column.
This is it - the ActiveX control we have been processing in the above functions! It is the only user interface element in the rollout. It is centered to the rollout and slightly smaller than the dialog dimensions.
When the rollout is opened for display as a dialog, this event handler will be called.
We can use the event to both initialize and fill in the listview with the currently selected objects' data.
This is the end of the on open event handler.
This is the end of the rollout definition.
Before creating the dialog, we try to close it. Since the variable listview_rollout is local to the MacroScript, calling the MacroScript multiple times will always access the same variable and will be able to close a previously opened dialog before creating a new one.
At the end, we create the dialog using the rollout we defined above.
After evaluating the script, you will find a new ActionItem in the "HowTo" category of the Customize User Interface dialog. Assign it to a toolbar, menu, QuadMenu or keyboard shortcut to be able to access it quickly.
Select some scene objects and press the button/select the menu item or press the keyboard shortcut - a new dialog with a listView ActiveX control displaying the name, class, vertex and face count and assigned material should appear.
Select some other object and call the script again - the old dialog will be closed, a new one will be opened and will display the data of the new selection.
This is a very basic version of the script. To see how it can be further improved and customized, see How To ... Develop a Selected Objects Inspector using ListView ActiveX Control - Part Two