Keyboard Accelerators and Dialog Messages
See Also: Class Interface, Custom Controls.
Keyboard Shortcuts
Important Note: A new system to handle keyboard accelerators was added for R4. This system supercedes those used in previous release. For information on this system see Class ActionTable. The information shown below applies to previous version of the SDK APIs.
Important Note: In release 3.0 a new system to handle keyboard shortcuts was established. This system is used to register shortcuts in a uniform manner. In the Customize / Preference Settings / Keyboard tab dialog there is a section to assign Plug-In shortcuts to commands. For details on how this works see the topic Keyboard Shortcut System.
Keyboard Accelerators
Developers might want to implement keyboard accelerators for some of their plug-ins functions. Because 3ds max plug-ins are modeless, when using R1 there was inherently a conflict between the accelerator keys that the user expected to run standard 3ds max functions, and those supplied by the plug-in. For this reason, a developer had to limit their accelerator key usage as much as possible. However in R2 and later the 'Plug-In Keyboard Shortcut Toggle' icon was added. This controls this conflict such that the user can choose if the plug-in accelerators are in effect or if the system accelerators are. Thus in R2 and later developer are free to registers all the accelerators they need and the user can control which are available.
When a plug-in has its parameters up and registers some accelerators, these accelerators take precedence over 3ds max when the 'Plug-In Keyboard Shortcut Toggle' is on. The methods below (from Class Interface) enable the developer to do this.
virtual void RegisterAccelTable( HWND hWnd, HACCEL hAccel )=0;
This method registers a keyboard accelerator table. Window messages generated by the accelerator table are sent to the hWnd parameter.
virtual int UnRegisterAccelTable( HWND hWnd, HACCEL hAccel )=0;
This method un-registers a keyboard accelerator table.
Receiving Input to Edit Controls
If a plug-in wants to receive keyboard input using a Windows edit control, it must disable the keyboard accelerators. 3ds max uses un-modified keys (such as 'f' to change to the front view). Unless a plug-in disabled the accelerators it would not get this input. The following global functions are used to enable, disable and check the enabled state of the keyboard accelerators.
void DisableAccelerators();
When this method is called, ALL keyboard accelerators are disabled and are no longer processed.
void EnableAccelerators();
When this method is called, the keyboard accelerators are processed again.
BOOL AcceleratorsEnabled();
Determines if the keyboard accelerators are enabled. Returns TRUE if enabled; FALSE if disabled.
For modal dialogs, Windows itself essentially handles disabling and enabling accelerators automatically. For modeless dialogs, a plug-in may have to deal with these functions. If a plug-in uses all standard 3ds max custom edit controls for its editing, it won't need to deal with enabling and disabling accelerators as this is handled by the custom controls. On the other hand, if a plug-in uses any Windows edit controls, such as a combo box that has an edit field and drop down, they will have to call these functions.
For example, in a combo box, when an edit field gets focus, the Windows message CBN_SETFOCUS is sent. At this time, a plug-in should call DisableAccelerators(). If the plug-in did not do this, and if the user typed an 'f', the current 3ds max viewport would change to the front view. By disabling all the accelerators, the plug-in will receive the characters itself. When the dialog proc receives CBN_KILLFOCUS, the accelerators may be enabled using EnableAccelerators().
Floating Dialogs
If a plug-in creates a floating dialog box there are two important things that should be done.
1) A plug-in must use the 3ds max window handle as the parent passed to the "DialogBox" of "DialogBoxParam". One can get this handle using the method Interface::GetMAXHWnd().
2) The method Interface::RegisterDlgWnd(HWND hDlg) must be called passing the handle of the dialog window.
Following these steps will prevent problems with the user of the dialog being able to operate the rest of 3ds max while your dialog is active.