We talked about how to do so manually in Visual Studio 2008 and 2010 respectively before. As introduced, a lot of details have to be taken care of regarding C++/CLI project settings especially when 64 bit Revit is used as the target product platform. If any of the details is slipped out of our mind, disaster would just happen, Revit/Visual Debugger will not be happy and/or the assembly will behave weird.
Now let’s see how RevitAddinWizard can help us create such a Revit C++/CLI addin project automatically and quickly. All worries will just go away.
RevitAddinWizard now supports Visual Studio both 2008 and 2010 and Revit both 32 bit and 64 bit regarding C++/CLI Revit addin project creation. Steps are the same in Visual Studio 2008 and 2010 but some UI looking is a bit different. We use Visual Studio 2008 here to demonstrate.
The Revit .NET Addin template regarding C++/CLI project type can be found from the following place of the New Project window:
After a project name is given and a location is chosen, the Revit .NET Addin Wizard will appear. Its settings are exactly the same for C++/CLI development as for C# and VB.NET. To make the story full, all its pages are appended below for reference:
Since a 64bit Revit has been chosen as the target product, one more target platform, x64, will be created automatically into the project configurations and set as the active:
Of course, a lot more are happening behind the scene, for example, Target .NET Framework adjustments, more .NET assembly references, Revit API assembly references, Target Machine linker setting, Debugging Information Format setting, Preprocessor Definition switching, and Debug Command pointing, which were discussed in detail in two previous posts:
Now, let’s look at the project contents:
Here is the Namespace.h:
#pragma once
using namespace Autodesk::Revit::ApplicationServices;
using namespace Autodesk::Revit::Attributes;
using namespace Autodesk::Revit::DB;
using namespace Autodesk::Revit::DB::Events;
using namespace Autodesk::Revit::DB::Architecture;
using namespace Autodesk::Revit::DB::Structure;
using namespace Autodesk::Revit::DB::Mechanical;
using namespace Autodesk::Revit::DB::Electrical;
using namespace Autodesk::Revit::DB::Plumbing;
using namespace Autodesk::Revit::UI;
using namespace Autodesk::Revit::UI::Selection;
using namespace Autodesk::Revit::UI::Events;
using namespace Autodesk::Revit::Collections;
using namespace Autodesk::Revit::Exceptions;
using namespace Autodesk::Revit::Utility;
namespace RvtAppSrv = Autodesk::Revit::ApplicationServices;
namespace RvtDB = Autodesk::Revit::DB;
Here is the Stdafx.h:
#pragma once
#using <mscorlib.dll>
using namespace System;
using namespace System::Collections;
using namespace System::Collections::Generic;
using namespace System::Text;
using namespace System::Linq;
using namespace System::Xml;
using namespace System::Reflection;
using namespace System::ComponentModel;
using namespace System::Globalization;
using namespace System::Resources;
using namespace System::Threading;
using namespace System::IO;
using namespace System::Windows;
using namespace System::Windows::Media::Imaging;
using namespace System::Windows::Forms;
using namespace System::Windows::Interop;
using namespace System::Drawing;
using namespace System::Drawing::Imaging;
Here is what the Images of the Resources.resx look like:
Here is the ExtApp.cpp:
#include "StdAfx.h"
#include "Namespaces.h"
namespace RevitAddinVCProject
{
[Transaction(TransactionMode::Manual)]
[Regeneration(RegenerationOption::Manual)]
public ref class ExtApp : IExternalApplication
{
#pragma region Cached Variables
public:
static UIControlledApplication^ _cachedUiCtrApp;
#pragma endregion
#pragma region IExternalApplication Members
virtual Result OnStartup(UIControlledApplication^ uiApp)
{
_cachedUiCtrApp = uiApp;
try
{
RibbonPanel^ ribbonPanel = CreateRibbonPanel();
//TODO: add you code below->
return Result::Succeeded;
}
catch (Exception^ ex)
{
MessageBox::Show( ex->ToString() );
return Result::Failed;
}
}
virtual Result OnShutdown(UIControlledApplication^ uiApp)
{
try
{
//TODO: add you code below->
return Result::Succeeded;
}
catch (Exception^ ex)
{
MessageBox::Show(ex->ToString());
return Result::Failed;
}
}
#pragma endregion
#pragma region Local Methods
private:
RibbonPanel^ CreateRibbonPanel()
{
RibbonPanel^ panel = _cachedUiCtrApp->CreateRibbonPanel("RevitAddinVCProject");
////Default button:
PushButtonData^ pbDataExtCmd = gcnew PushButtonData("ExtCmd", "ExtCmd", Assembly::GetExecutingAssembly()->Location, "RevitAddinVCProject.ExtCmd");
PushButton^ pbExtCmd = static_cast<PushButton^>(panel->AddItem(pbDataExtCmd));
pbExtCmd->ToolTip = "ExtCmd";
pbExtCmd->LargeImage = BmpImageSource("ExtCmd32x32");
pbExtCmd->Image = BmpImageSource("ExtCmd16x16");
////More buttons:
return panel;
}
System::Windows::Media::ImageSource^ BmpImageSource(String^ embeddedPath)
{
ResourceManager^ resources = gcnew ResourceManager("RevitAddinVCProject.Resources", Assembly::GetExecutingAssembly());
System::Drawing::Bitmap^ img = (cli::safe_cast<System::Drawing::Bitmap^>(resources->GetObject(embeddedPath)));
IntPtr hBitmap = img->GetHbitmap();
return System::Windows::Interop::Imaging::CreateBitmapSourceFromHBitmap(hBitmap, IntPtr::Zero, Int32Rect::Empty, BitmapSizeOptions::FromEmptyOptions());
}
#pragma endregion
};
}
Here is the ExtCmd.cpp:
#include "stdafx.h"
#include "Namespaces.h"
namespace RevitAddinVCProject
{
[Transaction(TransactionMode::Manual)]
[Regeneration(RegenerationOption::Manual)]
public ref class ExtCmd : IExternalCommand
{
#pragma region Cached Variables
private:
static ExternalCommandData^ _cachedCmdData;
public:
static property UIApplication^ CachedUiApp
{
UIApplication^ get()
{
return _cachedCmdData->Application;
}
}
static property RvtAppSrv::Application^ CachedApp
{
RvtAppSrv::Application^ get()
{
return CachedUiApp->Application;
}
}
static property RvtDB::Document^ CachedDoc
{
RvtDB::Document^ get()
{
return CachedUiApp->ActiveUIDocument->Document;
}
}
#pragma endregion
#pragma region IExternalCommand Members
public:
virtual Result Execute(ExternalCommandData^ cmdData, String^% msg, ElementSet^ elemSet)
{
_cachedCmdData = cmdData;
try
{
//TODO: add your code below.
return Result::Succeeded;
}
catch(System::Exception^ ex)
{
msg = ex->ToString();
return Result::Failed;
}
return Result::Succeeded;
}
#pragma endregion
};
}
Here is the RevitAddinVCProject.Addin or RevitAddinVCProject – Test.Addin:
<?xml version="1.0" encoding="utf-8"?>
<RevitAddIns>
<AddIn Type="Application">
<Assembly>C:\Temp\RevitAddinVCProject\x64\Debug\RevitAddinVCProject.dll</Assembly>
<FullClassName>RevitAddinVCProject.ExtApp</FullClassName>
<ClientId>a874398b-334e-4363-9332-edaf12155ce9</ClientId>
<Name>RevitAddinVCProject</Name>
</AddIn>
</RevitAddIns>
Last but not least, here is the ReadMe.txt:
========================================================================
Revit Addin VS Project Created by RevitAddinWizard
Updates can be checked on:
http://spiderinnet.typepad.com
========================================================================
The project supports the following options:
+ Project properties:
Assembly name: RevitAddinVCProject
Revit version: 2011
API lib path: C:\Program Files\Autodesk\Revit Architecture 2011\Program
Start Revit: True
+ External application:
Add one: True
Class name: ExtApp
Transaction mode: Manual
Regeneration option: Manual
Create a ribbon: True
+ External command:
Add one: True
Class name: ExtCmd
Description: The command ExtCmd
Transaction mode: Manual
Regeneration option: Manual
Add it into menu: False
OK, now everything is set. Press F5 and you are ready to go!
In Visual Studio 2010, RevitAddinWizard behaves the same regarding C++/CLI Revit addin project creation.
Recent Comments