Site Tools


Differences

This shows you the differences between two versions of the page.

Link to this comparison view

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}}
 +