mmMaxControls : .NET Controls with a 3dsmax Style

Lately I’ve seen several posts on the CGTalk MAXScript forum asking how one could make the standard .Net WinForms controls look like the standard 3dsmax UI elements.

Towards this end, I’ve written a collection of some commonly used controls that imitate the 3dsmax look and feel to the pixel, thus maintaining uniformity in your scripted or compiled interface, but giving you the high level of control that DotNet offers.

The package is called mmMaxControls, and is freely available for personal or commercial use. It targets version 2.0 of the DotNet framework, which should make is backwards compatible many versions (the earliest I’ve tested is 3dsmax 2009, theoretically it may work on as far back as 3dsmax 9).

General Features:

  • Look exactly like 3dsmax controls.
  • Control colors update when 3dsmax colors update.
  • No keyboard focus issues that plague standard DotNet controls in 3dsmax (EnableAccelerators is automatically managed by the library).
  • All the customization options of DotNet controls.
  • Can be used in any DotNet language. e.g. if you are developing a 3dsmax plugin in c# without referencing the 3dsmax SDK (for example, for versions earlier than 3dsmax 2012SAP), this is your best bet for native-looking 3dsmax controls.
  • Can be used in both a MAXScript Rollout as a DotNetControl or in a WinForms Form.

Download mmMaxControls v1.02 (12k)

The library is fully documented: Online | Zipped HTML.

Below is the code used for creating the MAXScript rollout at the top of this post.

dotnet.loadAssembly @"C:\mmMaxControls.dll"
try(destroyDialog mmMaxControls)catch()
rollout mmMaxControls "mmMaxControls" width:235
	groupBox grpBtn "Button" width:225 height:55 pos:[5,5]
	dotNetControl mmBtn1 "mmMaxControls.Button" width:62 height:25 pos:[15,25]
	dotNetControl mmBtn2 "mmMaxControls.Button" width:60 height:25 pos:[80,25]
	dotNetControl mmBtn3 "mmMaxControls.Button" width:25 height:25 pos:[143,25]
	dotNetControl mmBtn4 "mmMaxControls.Button" width:50 height:25 pos:[171,25]
	groupBox grpChk "CheckButton" width:225 height:55 pos:[5,65]
	dotNetControl mmChk1 "mmMaxControls.CheckButton" width:25 height:25 pos:[15,85]
	dotNetControl mmChk2 "mmMaxControls.CheckButton" width:70 height:25 pos:[45,85]
	dotNetControl mmChk3 "mmMaxControls.CheckButton" width:72 height:25 pos:[120,85]
	dotNetControl mmChk4 "mmMaxControls.CheckButton" width:25 height:25 pos:[195,85]
	groupBox grpFlyBtn "FlyoutButton" width:110 height:60 pos:[5,125]
	dotNetControl mmFlyBtn "mmMaxControls.FlyoutButton" width:32 height:32 pos:[43,145]
	groupBox grpFlyChk "FlyoutCheckButton" width:110 height:60 pos:[120,125]
	dotNetControl mmFlyChk "mmMaxControls.FlyoutCheckButton" width:32 height:32 pos:[157,145]
	groupBox grpDrop "DropDownList" width:225 height:50 pos:[5,190]
	dotNetControl mmDrop "mmMaxControls.DropDownList" width:200 height:21 pos:[15,210]
	groupBox grpTxt "TextBox" width:225 height:120 pos:[5,245]
	dotNetControl mmText1 "mmMaxControls.TextBox" width:200 height:21 pos:[15,265]
	dotNetControl mmText2 "mmMaxControls.TextBox" width:200 height:63 pos:[15,290]
	groupBox grpSpn "Spinner" width:225 height:65 pos:[5,370]
	label mmSpn1Lab "That's draggable" pos:[15,390]
	dotNetControl mmSpn1 "mmMaxControls.Spinner" width:80 height:16 pos:[140,390]
	label mmSpn2Lab "And screen-wrapping" pos:[15,412]
	dotNetControl mmSpn2 "mmMaxControls.Spinner" width:80 height:16 pos:[140,412]
	on mmMaxControls open do
		local logoImg = dotnetObject "System.Drawing.Bitmap" @"C:\logo.png"
		local blueImg = dotnetObject "System.Drawing.Bitmap" @"C:\logoBlue.png"
		local flyoutStrip = dotnetObject "System.Drawing.Bitmap" @"C:\imageStrip.png"
		mmBtn1.text = "DotNet"
		mmBtn1.image = logoImg
		mmBtn1.imageAlign = mmBtn1.imageAlign.MiddleLeft
		mmBtn1.TextAlign = mmBtn1.textAlign.MiddleRight
		mmBtn2.text = "Controls"
		mmBtn3.image = logoImg
		mmBtn3.ShowFocusFrame = off
		mmBtn4.text = "With"
		mmBtn4.FrameOnMouseOverOnly = on
		mmChk1.text = "A"
		mmChk2.text = "3dsmax"
		mmChk2.image = blueImg
		mmChk2.imageAlign = mmChk1.imageAlign.MiddleLeft
		mmChk2.TextAlign = mmChk1.textAlign.MiddleRight
		mmChk2.ShowFocusFrame = off
		mmChk3.text = "Look"
		mmChk3.ShowFocusFrame = off
		mmChk3.FrameOnMouseOverOnly = on
		mmChk4.image = blueImg
		mmChk4.ShowFocusFrame = off
		mmChk4.FrameOnMouseOverOnly = on
		mmText2.multiLine = on
		mmSpn1.minimum = 0.1
		mmSpn1.maximum = 1
		mmSpn1.increment = .001
		mmspn1.value = mmspn1.defaultValue = 0.5
		mmSpn1.decimalPlaces = 3
		mmSpn2.increment = 1
		mmSpn2.maximum = 10000
		mmSpn2.value = mmSpn2.defaultValue = 100
		mmSpn2.decimalPlaces = 0
		mmDrop.items.addRange #("A", "DropDownList", "control", "that", "inherits", "from", "Combobox")
		mmDrop.selectedIndex = 0
		mmFlyBtn.setImageStrip flyoutStrip 4
		mmFlyBtn.toolTips = #("Easily", "Set", "Button", "Tooltips")
		mmFlyChk.setImageStrip flyoutStrip 4
		mmFlyChk.toolTips = #("Same", "Thing", "But", "Checkable")
		mmFlyChk.flyoutTime = 100
createDialog mmMaxControls

These are the bitmaps used in the example code:

Update: v1.01

I’ve updated the library to v1.01, fixing a few bugs and adding a few small methods.

  • Spinner: Backspace key was not working.
  • Spinner: now behaves correctly for resetting and cancelling a spin operation.
  • Spinner: now goes faster/slower with control/alt buttons pressed, as native 3dsmax spinner.
  • Spinner: text area would not accept the enter key when used as a DotNetControl.
  • Spinner: now shows the correct mouse cursor when dragging.
  • Spinner: ‘dragging’ behavior now only begins when the mouse has left the control area.
  • Spinner: Added .Clear() method for setting the control in an indeterminate state.
  • Spinner: Added events for ButtonDown and ButtonUp, similar to the native 3dsmax events.
  • Button: Contents are now corrently moved 1 pixel to the right and down when pressed.
  • CheckButtons: Frame is now always shown when button is checked, even if FrameOnMouseOverOnly is on.
  • Flyout controls: Opening the flyout no longer steals focus from the host dialog.
  • Flyout controls: Added .ShowFlyout() method for programmatically opening the flyout, e.g. – when you want another button to open the flyout.

Thanks to DenisT from CGTalk for catching most of these bugs.

Another Update: v1.02

I’ve fixed some more bugs and inaccuracies:

  • Spinner: Very minor change of point of transitioning from click to drag behavior, now completely matches 3dsmax.
  • CheckButton: Now shows checked background on mouse down, instead of mouse up.
  • FlyoutButton and FlyoutCheckButton: Flyout items are now correctly shifted 1 pixel right and down on mouse over.
  • FlyoutButton: ItemSelected is now also triggered when the button is clicked without the flyout opening.

Introducing VFB+ v2.3

First of all, I must apologize for not updating this blog more often. Virtually all of my free time in the past six months has gone towards making sure the next update of VFB+ will be as powerful, stable and convenient as possible.

This release is packed full of new features, almost all of them requested by users! A considerable number of bugs has also been fixed, and performance greatly improved.

Amongst the new features you will find:

  • Chromatic aberration!
  • VFB+ now supports rendering via Backburner. This means that you can install VFB+ on your render nodes (no license required for this mode), and get your network renders come back with your color correction and stamps.
  • sRGB color space toggle.
  • Estimated render time display. Yes, even if your renderer does not report this data natively (e.g. – Mental Ray).
  • Save all elements of current image with one click.
  • And much much more… I recommend taking a look at the complete change log, and the new video which demonstrates some of the new features.

    I’ve also made the help files available online as well as the compiled .CHM.

    Thanks to all users for your requests, bug reports and general feedback.

    Oh, and of course, this upgrade is free for all existing users. Simply download the trial from this page and replace VFBPlus2.dlx in your \plugins\ folder, your license should work as usual.