This shows you the differences between two versions of the page.
|
developer:sdksamples:skin [2012/05/08] giulio |
developer:sdksamples:skin [2012/06/04] (current) dale |
||
|---|---|---|---|
| Line 1: | Line 1: | ||
| + | ====== Create a Skin using the Rhino C++ SDK ====== | ||
| + | > **Developer:** //[[developer:cplusplusplugins|C++]]// | ||
| + | > **Summary:** //The Rhino Application Platform (RAP) provides the tools for C++ developers to wrap their application around Rhino by creating a custom Skin.// | ||
| + | |||
| + | =====Overview===== | ||
| + | Rhino allows developers to customize most of Rhino's interface so that the application appears to be their own. We call this a custom //Skin//. With a custom Skin, you can change the application icon, splash screen, the menu bar, the application title bar, the about box, and the toolbars. | ||
| + | |||
| + | {{http://en.wiki.mcneel.com/content/upload/images/hippo.gif}} | ||
| + | |||
| + | Creating a custom Skin for Rhino involves creating two code modules: | ||
| + | |||
| + | * **<skin name>.rhs** is a regular MFC DLL that implements the skin's icon, splash screen, and, optionally, a menu. In this article, we will refer this to the Skin DLL. | ||
| + | * **<skin name>.rhp** is a Rhino utility plug-in that implements the menu handler, if necessary, and one or more custom commands. In this article, we will refer to this as the Skin Plug-in. | ||
| + | |||
| + | =====Create the Skin DLL===== | ||
| + | * A Skin DLL is a regular MFC DLL that implements the skin's icon, splash screen, and, optionally, a menu. | ||
| + | * To create the Skin DLL, launch Visual Studio and run the //Rhino Skin DLL// wizard installed by the Rhino SDK. | ||
| + | * The Rhino Skin DLL wizard will create three classes: | ||
| + | - A CWinApp-derived class. This is the entry point of the DLL. | ||
| + | - A CRhinoSkinDLL-derived class. This class allows you to specify Rhino's icon, splash screen and menu. For more information on this class, see rhinoSdkSkinDLL.h. | ||
| + | - CSplashWnd. This is a basic implementation of a splash screen class. If you require something fancier, feel free to replace it with your own implementation. | ||
| + | * Modify the project's icon and splash screen bitmap. If your Skin is going to override Rhino's main menu, then you will need to create your menu resources as well. | ||
| + | * Do not forget to fill out the developer information block found at the top of your DLL's .CPP file. This block is similar to that of Rhino plug-ins. | ||
| + | |||
| + | =====Create the Skin Plug-in===== | ||
| + | * A Skin Plug-in is a Rhino utility plug-in that implements the menu handler, if necessary, and one or more custom commands. | ||
| + | * To create a Rhino utility plug-in, launch Visual Studio and run the //Rhino Plug-in// wizard installed by the Rhino SDK. When picking the wizard to run, make sure to add the new project to the open solution instead of creating a new solution. This way, your Skin project will be origanized into a single solution. | ||
| + | * If the Skin DLL provides a custom menu, then copy the UUID generated by the plug-in AppWizard and found in your plug-in's CRhinoPlugIn::PlugInID() member to your Skin's CRhinoSkinDLL::SkinPlugInID() member. | ||
| + | * **Important!** These two methods must return the same UUID. This is a critical step as it identifies the main plug-in that Rhino will load to manage its menus and extend the Rhino command set. | ||
| + | * Add the following overrides to the header file of your CRhinoPlugIn-derived class: | ||
| + | |||
| + | <code c++> | ||
| + | // Skin DLL menu update handler | ||
| + | void OnInitPlugInMenuPopups(WPARAM wparam, LPARAM lparam); | ||
| + | |||
| + | // Skin DLL menu command handler | ||
| + | BOOL OnPlugInMenuCommand(WPARAM wparam ); | ||
| + | |||
| + | // Change to CRhinoPlugIn::load_plugin_at_startup | ||
| + | plugin_load_time PlugInLoadTime(); | ||
| + | </code> | ||
| + | |||
| + | * Add the following definition to the .CPP file of your CRhinoPlugIn-derived class. | ||
| + | |||
| + | <code c++> | ||
| + | CRhinoPlugIn::plugin_load_time CSkinPlugInSamplePlugIn::PlugInLoadTime() | ||
| + | { | ||
| + | // Override to change load time to "at startup" | ||
| + | return CRhinoPlugIn::load_plugin_at_startup; | ||
| + | } | ||
| + | </code> | ||
| + | |||
| + | * If your Skin DLL is providing a custom menu, then add a source file named MenuHandler.cpp to the plug-in project and put the definition of CRhinoPlugIn::OnInitPlugInMenuPopups() and CRhinoPlugIn::OnPlugInMenuCommand() in this file. | ||
| + | * **Important!** Include the Skin DLL's Resource.h file in MenuHandler.cpp to provide access to the Skin DLL's menu resource identifiers. For example: | ||
| + | |||
| + | <code c++> | ||
| + | #include "stdafx.h" | ||
| + | #include "MySkinPlugIn.h" | ||
| + | #include "../MySkinDLL/Resource.h" | ||
| + | |||
| + | // Put these to overrides in a separate CPP file so they could | ||
| + | // include the MySkinDLL/Resource.h file without conflicting | ||
| + | // with this projects resource.h | ||
| + | |||
| + | void CSkinPlugInSamplePlugIn::OnInitPlugInMenuPopups(WPARAM wParam, LPARAM lParam) | ||
| + | { | ||
| + | HMENU hMenu = (HMENU)wParam; | ||
| + | if( NULL == hMenu ) | ||
| + | return; | ||
| + | |||
| + | switch( GetMenuItemID(hMenu, LOWORD(lParam)) ) | ||
| + | { | ||
| + | case IDM_SAMPLE_DISABLE: | ||
| + | ::EnableMenuItem( hMenu, IDM_SAMPLE_DISABLE, MF_BYCOMMAND|MF_DISABLED|MF_GRAYED ); | ||
| + | break; | ||
| + | case IDM_SAMPLE_SUB_DISABLE: | ||
| + | ::EnableMenuItem( hMenu, IDM_SAMPLE_SUB_DISABLE, MF_BYCOMMAND|MF_DISABLED|MF_GRAYED ); | ||
| + | break; | ||
| + | // TODO... | ||
| + | } | ||
| + | } | ||
| + | |||
| + | BOOL CSkinPlugInSamplePlugIn::OnPlugInMenuCommand(WPARAM wParam) | ||
| + | { | ||
| + | ON_wString w; | ||
| + | switch( (UINT)wParam ) | ||
| + | { | ||
| + | case IDM_SAMPLE_ONE: | ||
| + | w = L"Test Item One"; | ||
| + | break; | ||
| + | case IDM_SAMPLE_TWO: | ||
| + | w = L"Two"; | ||
| + | break; | ||
| + | case IDM_SAMPLE_DISABLE: | ||
| + | w = L"Disabled"; | ||
| + | break; | ||
| + | case IDM_SAMPLE_SUB_A: | ||
| + | w = L"Sub Menu A"; | ||
| + | break; | ||
| + | case IDM_SAMPLE_SUB_B: | ||
| + | w = L"Sub Menu B"; | ||
| + | break; | ||
| + | case IDM_SAMPLE_SUB_DISABLE: | ||
| + | w = L"Sub Menu Disabled"; | ||
| + | break; | ||
| + | default: | ||
| + | return true; | ||
| + | } | ||
| + | |||
| + | ::RhinoMessageBox( w, L"OnMenu", MB_OK ); | ||
| + | return true; | ||
| + | } | ||
| + | </code> | ||
| + | |||
| + | =====Finishing Up===== | ||
| + | * Compile the Skin Plug-in. | ||
| + | * Load the Skin Plug-in using Rhino's PluginManager command so it has a chance to self-register. | ||
| + | * Compile the Skin DLL. | ||
| + | |||
| + | =====Installation===== | ||
| + | To install your custom Skin, use **REGEDIT.EXE** to add a scheme key to your registry with a path to your Skin DLL. For example: | ||
| + | |||
| + | |**Item**|**Value**| | ||
| + | |Subkey|HKEY_LOCAL_MACHINE\SOFTWARE\McNeel\Rhinoceros\4.0\Scheme: MySkin| | ||
| + | |Entry name|SkinDLLPath| | ||
| + | |Type|REG_SZ| | ||
| + | |Data value|C:\Src\MySkin\MySkinDLL\Release\MySkinDLL.rhs| | ||
| + | |||
| + | You can now test your custom Skin by creating shortcut to your Rhino executable with /scheme="<scheme name from the previous step>" as command line argument. For example: | ||
| + | |||
| + | <code> | ||
| + | "C:\Program Files\Rhinoceros 4.0\System\Rhino4.exe" /scheme=MySkin | ||
| + | </code> | ||
| + | |||
| + | |||
| + | |||
| + | =====Additional Information===== | ||
| + | If the user chooses not to run your skinned version of Rhino, you might want to prevent your skin plug-in loading. You can do this by checking to see if the name of the scheme, that Rhino is using, matches your skin's scheme name. Do this checking in your plug-in's CRhinoPlugIn::OnLoadPlugIn() member. | ||
| + | |||
| + | For example: | ||
| + | |||
| + | <code c++> | ||
| + | BOOL CSkinPlugInSamplePlugIn::OnLoadPlugIn() | ||
| + | { | ||
| + | ON_wString scheme = RhinoApp().RegistrySchemeName(); | ||
| + | if( scheme.CompareNoCase(L"Scheme: MySkin") != 0 ) | ||
| + | return -1; // Fail silently... | ||
| + | |||
| + | // TODO... | ||
| + | |||
| + | return CRhinoUtilityPlugIn::OnLoadPlugIn(); | ||
| + | } | ||
| + | </code> | ||
| + | |||
| + | \\ | ||
| + | |||
| + | {{tag>Developer cplusplus}} | ||
| + | |||