Create Flyouts in the CommandManager Example (C#)
This example shows how to use an add-in to create flyouts in the CommandManager
and in context-sensitive menus of selected entities.
//--------------------------------------------------------------------------
// Preconditions:
// 1. Ensure that you have installed the add-in templates for
your
// version of Visual Studio from the most
recent API SDK.
// 2. In Microsoft Visual
Studio, create a project using
// Other Languages > Visual C# > My Templates >
SwCSharpAddin.
// 3. Name the project FlyoutAddin.
// 4. Copy and paste
this into SwAddin.cs of your C# project.
// 5. Click Project >
FlyoutAddin Properties > Debug.
// 6. Select Start external program and type the pathname of your
// SolidWorks
executable.
// 7. Click F5 to start
debugging this add-in.
//
// Postconditions:
// 1. In SolidWorks,
select C# Add-in > CreateCube.
// 2. Click C# Add-in in
the CommandManager.
// Inspect the Immediate Window.
// 3. Click a face of the
cube.
// 4. Click the flyout
icon in the face's context-sensitive menu.
// 5. Select a command
item and inspect the Immediate Window.
//---------------------------------------------------------------------------
// SwAddin.cs:
using
System;
using
System.Runtime.InteropServices;
using
System.Collections;
using
System.Reflection;
using
SolidWorks.Interop.sldworks;
using
SolidWorks.Interop.swpublished;
using
SolidWorks.Interop.swconst;
using
SolidWorksTools;
using
SolidWorksTools.File;
using
System.Collections.Generic;
using
System.Diagnostics;
namespace
FlyoutAddin
{
///
<summary>
///
This C# add-in shows how to create a flyout menu in both the CommandManager
///
and the context-sensitive menus of selected faces.
///
</summary>
[Guid("cc6bb106-bf87-49e0-b0fb-dcb49eab0bbe"),
ComVisible(true)]
[SwAddin(
Description = "A flyout menu
appears on the toolbar and on the context-sensitive menus of selected
faces.",
Title = "C# Add-in",
LoadAtStartup = true
)]
public
class
SwAddin
: ISwAddin
{
#region
Local Variables
ISldWorks
iSwApp = null;
ICommandManager
iCmdMgr = null;
ICommandGroup
cmdGroup;
IFlyoutGroup
flyoutGroup;
int
addinID = 0;
BitmapHandler
iBmp;
public
const
int
mainCmdGroupID = 5;
public
const
int
mainItemID1 = 0;
public
const
int
mainItemID2 = 1;
public
const
int
mainItemID3 = 2;
public
const
int
flyoutGroupID = 91;
#region
Event Handler Variables
Hashtable
openDocs = new
Hashtable();
SolidWorks.Interop.sldworks.SldWorks
SwEventPtr = null;
#endregion
#region Property Manager Variables
UserPMPage
ppage = null;
#endregion
//
Public Properties
public
ISldWorks
SwApp
{
get
{ return
iSwApp; }
}
public
ICommandManager
CmdMgr
{
get
{ return
iCmdMgr; }
}
public
Hashtable
OpenDocs
{
get
{ return
openDocs; }
}
#endregion
#region SolidWorks Registration
[ComRegisterFunctionAttribute]
public
static
void
RegisterFunction(Type
t)
{
#region
Get Custom Attribute: SwAddinAttribute
SwAddinAttribute
SWattr = null;
Type
type = typeof(SwAddin);
foreach
(System.Attribute
attr in
type.GetCustomAttributes(false))
{
if
(attr is
SwAddinAttribute)
{
SWattr = attr as
SwAddinAttribute;
break;
}
}
#endregion
try
{
Microsoft.Win32.RegistryKey
hklm = Microsoft.Win32.Registry.LocalMachine;
Microsoft.Win32.RegistryKey
hkcu = Microsoft.Win32.Registry.CurrentUser;
string
keyname = "SOFTWARE\\SolidWorks\\Addins\\{"
+ t.GUID.ToString() + "}";
Microsoft.Win32.RegistryKey
addinkey = hklm.CreateSubKey(keyname);
addinkey.SetValue(null,
0);
addinkey.SetValue("Description",
SWattr.Description);
addinkey.SetValue("Title",
SWattr.Title);
keyname = "Software\\SolidWorks\\AddInsStartup\\{"
+ t.GUID.ToString() + "}";
addinkey = hkcu.CreateSubKey(keyname);
addinkey.SetValue(null,
Convert.ToInt32(SWattr.LoadAtStartup),
Microsoft.Win32.RegistryValueKind.DWord);
}
catch
(System.NullReferenceException
nl)
{
Console.WriteLine("There
was a problem registering this dll: SWattr is null. \n\""
+ nl.Message + "\"");
System.Windows.Forms.MessageBox.Show("There
was a problem registering this dll: SWattr is null.\n\""
+ nl.Message + "\"");
}
catch
(System.Exception
e)
{
Console.WriteLine(e.Message);
System.Windows.Forms.MessageBox.Show("There
was a problem registering the function: \n\""
+ e.Message + "\"");
}
}
[ComUnregisterFunctionAttribute]
public
static
void
UnregisterFunction(Type
t)
{
try
{
Microsoft.Win32.RegistryKey
hklm = Microsoft.Win32.Registry.LocalMachine;
Microsoft.Win32.RegistryKey
hkcu = Microsoft.Win32.Registry.CurrentUser;
string
keyname = "SOFTWARE\\SolidWorks\\Addins\\{"
+ t.GUID.ToString() + "}";
hklm.DeleteSubKey(keyname);
keyname = "Software\\SolidWorks\\AddInsStartup\\{"
+ t.GUID.ToString() + "}";
hkcu.DeleteSubKey(keyname);
}
catch
(System.NullReferenceException
nl)
{
Console.WriteLine("There
was a problem unregistering this dll: " +
nl.Message);
System.Windows.Forms.MessageBox.Show("There
was a problem unregistering this dll: \n\""
+ nl.Message + "\"");
}
catch
(System.Exception
e)
{
Console.WriteLine("There
was a problem unregistering this dll: " +
e.Message);
System.Windows.Forms.MessageBox.Show("There
was a problem unregistering this dll: \n\""
+ e.Message + "\"");
}
}
#endregion
#region ISwAddin Implementation
public
SwAddin()
{
}
public
bool
ConnectToSW(object
ThisSW, int
cookie)
{
iSwApp = (ISldWorks)ThisSW;
addinID = cookie;
//Setup callbacks
iSwApp.SetAddinCallbackInfo(0,
this,
addinID);
#region
Setup the Command Manager
iCmdMgr = iSwApp.GetCommandManager(cookie);
AddCommandMgr();
#endregion
#region Setup the Event
Handlers
SwEventPtr = (SolidWorks.Interop.sldworks.SldWorks)iSwApp;
openDocs = new
Hashtable();
AttachEventHandlers();
#endregion
#region Setup Sample Property
Manager
AddPMP();
#endregion
return
true;
}
public
bool
DisconnectFromSW()
{
RemoveCommandMgr();
RemovePMP();
DetachEventHandlers();
System.Runtime.InteropServices.Marshal.ReleaseComObject(iCmdMgr);
iCmdMgr = null;
System.Runtime.InteropServices.Marshal.ReleaseComObject(iSwApp);
iSwApp = null;
//The addin _must_ call
GC.Collect() here in order to retrieve all managed code pointers
GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();
GC.WaitForPendingFinalizers();
return
true;
}
#endregion
#region UI Methods
public
void
updateBtns()
{
flyoutGroup = iCmdMgr.GetFlyoutGroup(91);
flyoutGroup.RemoveAllCommandItems();
flyoutGroup.AddCommandItem("FlyoutCommand
1", "FlyoutCommand
1", 0,
"FlyoutCommandItem1",
"FlyoutEnableCommandItem1");
flyoutGroup.AddCommandItem("FlyoutCommand
2", "FlyoutCommand
2", 0,
"FlyoutCommandItem2",
"FlyoutEnableCommandItem2");
flyoutGroup.FlyoutType = (int)swCommandFlyoutStyle_e.swCommandFlyoutStyle_Simple;
//flyoutGroup.FlyoutType = (int)swCommandFlyoutStyle_e.swCommandFlyoutStyle_LastUsed;
//flyoutGroup.FlyoutType
= (int)swCommandFlyoutStyle_e.swCommandFlyoutStyle_Favorite;
IFlyoutGroup
fogrp;
fogrp = iCmdMgr.GetFlyoutGroup(91);
Debug.Print(" CmdID:
" + fogrp.CmdID);
Debug.Print(" Button
count: " + fogrp.ButtonCount);
Debug.Print(" Flyout
Type: " + fogrp.FlyoutType);
Debug.Print(" SmallMainIcon:
" + fogrp.SmallMainIcon);
Debug.Print(" LargeMainIcon:
" + fogrp.LargeMainIcon);
Debug.Print(" SmallIconList:
" + fogrp.SmallIconList);
Debug.Print(" LargeIconList:
" + fogrp.LargeIconList);
}
public
void
AddCommandMgr()
{
if
(iBmp == null)
iBmp = new
BitmapHandler();
Assembly
thisAssembly;
int
cmdIndex0, cmdIndex1;
string
Title = "C# Add-in",
ToolTip = "Flyout demo";
int[]
docTypes = new
int[]{(int)swDocumentTypes_e.swDocASSEMBLY,
(int)swDocumentTypes_e.swDocDRAWING,
(int)swDocumentTypes_e.swDocPART};
thisAssembly = System.Reflection.Assembly.GetAssembly(this.GetType());
int
cmdGroupErr = 0;
bool
ignorePrevious = false;
object
registryIDs;
//get the ID information stored
in the registry
bool
getDataResult = iCmdMgr.GetGroupDataFromRegistry(mainCmdGroupID,
out
registryIDs);
int[]
knownIDs = new
int[2] {
mainItemID1, mainItemID2 };
if
(getDataResult)
{
if
(!CompareIDs((int[])registryIDs,
knownIDs)) //if the IDs don't match, reset
the commandGroup
{
ignorePrevious = true;
}
}
cmdGroup = iCmdMgr.CreateCommandGroup2(mainCmdGroupID,
Title, ToolTip, "",
-1, ignorePrevious, ref
cmdGroupErr);
cmdGroup.LargeIconList = iBmp.CreateFileFromResourceBitmap("FlyoutAddin.ToolbarLarge.bmp",
thisAssembly);
cmdGroup.SmallIconList = iBmp.CreateFileFromResourceBitmap("FlyoutAddin.ToolbarSmall.bmp",
thisAssembly);
cmdGroup.LargeMainIcon = iBmp.CreateFileFromResourceBitmap("FlyoutAddin.MainIconLarge.bmp",
thisAssembly);
cmdGroup.SmallMainIcon = iBmp.CreateFileFromResourceBitmap("FlyoutAddin.MainIconSmall.bmp",
thisAssembly);
int
menuToolbarOption = (int)(swCommandItemType_e.swMenuItem
| swCommandItemType_e.swToolbarItem);
cmdIndex0 = cmdGroup.AddCommandItem2("CreateCube",
-1, "Create a cube",
"Create cube",
0, "CreateCube",
"",
mainItemID1, menuToolbarOption);
cmdIndex1 = cmdGroup.AddCommandItem2("Show
PMP", -1,
"Display sample property manager",
"Show PMP",
2, "ShowPMP",
"EnablePMP",
mainItemID2, menuToolbarOption);
cmdGroup.HasToolbar =
true;
cmdGroup.HasMenu = true;
cmdGroup.Activate();
bool
bResult;
flyoutGroup = iCmdMgr.CreateFlyoutGroup(flyoutGroupID,
"Dynamic Flyout",
"Flyout Tooltip",
"Flyout Hint",
cmdGroup.SmallMainIcon, cmdGroup.LargeMainIcon,
cmdGroup.SmallIconList, cmdGroup.LargeIconList,
"FlyoutCallback",
"FlyoutEnable");
// Add the FlyoutGroup to the
context-sensitive menus of faces in parts
bResult = flyoutGroup.AddContextMenuFlyout((int)swDocumentTypes_e.swDocPART,
(int)swSelectType_e.swSelFACES);
Debug.Print("Context
menu flyout created for faces in parts: " +
bResult.ToString());
// Get the total number of
FlyoutGroups in CommandManager
Debug.Print("Number
of FlyoutGroups is " + iCmdMgr.NumberOfFlyoutGroups);
// Get the FlyoutGroups
object[]
objGroups;
objGroups = (object[])iCmdMgr.GetFlyoutGroups();
Debug.Print("Find
all FlyoutGroups in CommandManager:");
int
i;
for
(i = 0; i <= objGroups.GetUpperBound(0); i++)
{
Debug.Print("FlyoutGroup
found");
}
// Get a FlyoutGroup by its
user-defined ID
IFlyoutGroup
fogrp;
fogrp = iCmdMgr.GetFlyoutGroup(91);
Debug.Print(" CmdID:
" + fogrp.CmdID);
Debug.Print(" Button
count: " + fogrp.ButtonCount);
Debug.Print(" Flyout
Type: " + fogrp.FlyoutType);
Debug.Print(" SmallMainIcon:
" + fogrp.SmallMainIcon);
Debug.Print(" LargeMainIcon:
" + fogrp.LargeMainIcon);
Debug.Print(" SmallIconList:
" + fogrp.SmallIconList);
Debug.Print(" LargeIconList:
" + fogrp.LargeIconList);
foreach
(int type
in docTypes)
{
CommandTab
cmdTab;
cmdTab = iCmdMgr.GetCommandTab(type, Title);
if
(cmdTab != null
& !getDataResult | ignorePrevious)//if tab
exists, but we have ignored the registry info (or changed command group ID),
re-create the tab. Otherwise the ids won't matchup and the tab will be
blank
{
bool
res = iCmdMgr.RemoveCommandTab(cmdTab);
cmdTab = null;
}
//if cmdTab is null, must
be first load (possibly after reset), add the commands to the tabs
if
(cmdTab == null)
{
cmdTab = iCmdMgr.AddCommandTab(type, Title);
CommandTabBox
cmdBox = cmdTab.AddCommandTabBox();
int[]
cmdIDs = new
int[3];
int[]
TextType = new
int[3];
cmdIDs[0] = cmdGroup.get_CommandID(cmdIndex0);
TextType[0] = (int)swCommandTabButtonTextDisplay_e.swCommandTabButton_TextHorizontal;
cmdIDs[1] = cmdGroup.get_CommandID(cmdIndex1);
TextType[1] = (int)swCommandTabButtonTextDisplay_e.swCommandTabButton_TextHorizontal;
cmdIDs[2] = cmdGroup.ToolbarId;
TextType[2] = (int)swCommandTabButtonTextDisplay_e.swCommandTabButton_TextHorizontal
| (int)swCommandTabButtonFlyoutStyle_e.swCommandTabButton_ActionFlyout;
bResult = cmdBox.AddCommands(cmdIDs, TextType);
CommandTabBox
cmdBox1 = cmdTab.AddCommandTabBox();
cmdIDs = new
int[1];
TextType = new
int[1];
cmdIDs[0] = flyoutGroup.CmdID;
TextType[0] = (int)swCommandTabButtonTextDisplay_e.swCommandTabButton_TextBelow
| (int)swCommandTabButtonFlyoutStyle_e.swCommandTabButton_ActionFlyout;
bResult = cmdBox1.AddCommands(cmdIDs, TextType);
cmdTab.AddSeparator(cmdBox1, cmdIDs[0]);
}
}
thisAssembly = null;
}
public
void
RemoveCommandMgr()
{
iBmp.Dispose();
iCmdMgr.RemoveCommandGroup(mainCmdGroupID);
iCmdMgr.RemoveFlyoutGroup(flyoutGroupID);
}
public
bool
CompareIDs(int[]
storedIDs, int[]
addinIDs)
{
List<int>
storedList = new
List<int>(storedIDs);
List<int>
addinList = new
List<int>(addinIDs);
addinList.Sort();
storedList.Sort();
if
(addinList.Count != storedList.Count)
{
return
false;
}
else
{
for
(int i = 0;
i < addinList.Count; i++)
{
if
(addinList[i] != storedList[i])
{
return
false;
}
}
}
return
true;
}
public
Boolean
AddPMP()
{
ppage = new
UserPMPage(this);
return
true;
}
public
Boolean
RemovePMP()
{
ppage = null;
return
true;
}
#endregion
#region UI Callbacks
public
void
CreateCube()
{
//make sure we have a part open
string
partTemplate = iSwApp.GetUserPreferenceStringValue((int)swUserPreferenceStringValue_e.swDefaultTemplatePart);
if
((partTemplate != null)
&& (partTemplate != ""))
{
IModelDoc2
modDoc = (IModelDoc2)iSwApp.NewDocument(partTemplate,
(int)swDwgPaperSizes_e.swDwgPaperA2size,
0.0, 0.0);
modDoc.InsertSketch2(true);
modDoc.SketchRectangle(0, 0, 0, .1, .1, .1,
false);
//Extrude the sketch
IFeatureManager
featMan = modDoc.FeatureManager;
featMan.FeatureExtrusion(true,
false,
false,
(int)swEndConditions_e.swEndCondBlind,
(int)swEndConditions_e.swEndCondBlind,
0.1, 0.0,
false,
false,
false,
false,
0.0, 0.0,
false,
false,
false,
false,
true,
false,
false);
}
else
{
System.Windows.Forms.MessageBox.Show("There
is no part template available. Please check your options and make sure there
is a part template selected, or select a new part template.");
}
}
public
void
ShowPMP()
{
if
(ppage != null)
ppage.Show();
}
public
int
EnablePMP()
{
if
(iSwApp.ActiveDoc != null)
return
1;
else
return
0;
}
public
void
FlyoutCallback()
{
updateBtns();
}
public
int
FlyoutEnable() {
// enable the flyout only if
command group buttons are enabled
if
(cmdGroup.HasEnabledButton)
return
1;
else
return
0;
}
public
void
FlyoutCommandItem1() { Debug.Print("Flyout
command 1 called"); }
public
int
FlyoutEnableCommandItem1() { return
1; }
public
void
FlyoutCommandItem2() { Debug.Print("Flyout
command 2 called"); }
public
int
FlyoutEnableCommandItem2() { return
1; }
#endregion
#region Event Methods
public
bool
AttachEventHandlers()
{
AttachSwEvents();
//Listen for events on all
currently open docs
AttachEventsToAllDocuments();
return
true;
}
private
bool
AttachSwEvents()
{
try
{
SwEventPtr.ActiveDocChangeNotify +=
new
DSldWorksEvents_ActiveDocChangeNotifyEventHandler(OnDocChange);
SwEventPtr.DocumentLoadNotify2 +=
new
DSldWorksEvents_DocumentLoadNotify2EventHandler(OnDocLoad);
SwEventPtr.FileNewNotify2 +=
new
DSldWorksEvents_FileNewNotify2EventHandler(OnFileNew);
SwEventPtr.ActiveModelDocChangeNotify +=
new
DSldWorksEvents_ActiveModelDocChangeNotifyEventHandler(OnModelChange);
SwEventPtr.FileOpenPostNotify +=
new
DSldWorksEvents_FileOpenPostNotifyEventHandler(FileOpenPostNotify);
return
true;
}
catch
(Exception
e)
{
Console.WriteLine(e.Message);
return
false;
}
}
private
bool
DetachSwEvents()
{
try
{
SwEventPtr.ActiveDocChangeNotify -=
new
DSldWorksEvents_ActiveDocChangeNotifyEventHandler(OnDocChange);
SwEventPtr.DocumentLoadNotify2 -=
new
DSldWorksEvents_DocumentLoadNotify2EventHandler(OnDocLoad);
SwEventPtr.FileNewNotify2 -=
new
DSldWorksEvents_FileNewNotify2EventHandler(OnFileNew);
SwEventPtr.ActiveModelDocChangeNotify -=
new
DSldWorksEvents_ActiveModelDocChangeNotifyEventHandler(OnModelChange);
SwEventPtr.FileOpenPostNotify -=
new
DSldWorksEvents_FileOpenPostNotifyEventHandler(FileOpenPostNotify);
return
true;
}
catch
(Exception
e)
{
Console.WriteLine(e.Message);
return
false;
}
}
public
void
AttachEventsToAllDocuments()
{
ModelDoc2
modDoc = (ModelDoc2)iSwApp.GetFirstDocument();
while
(modDoc != null)
{
if
(!openDocs.Contains(modDoc))
{
AttachModelDocEventHandler(modDoc);
}
modDoc = (ModelDoc2)modDoc.GetNext();
}
}
public
bool
AttachModelDocEventHandler(ModelDoc2
modDoc)
{
if
(modDoc == null)
return
false;
DocumentEventHandler
docHandler = null;
if
(!openDocs.Contains(modDoc))
{
switch
(modDoc.GetType())
{
case
(int)swDocumentTypes_e.swDocPART:
{
docHandler = new
PartEventHandler(modDoc,
this);
break;
}
case
(int)swDocumentTypes_e.swDocASSEMBLY:
{
docHandler = new
AssemblyEventHandler(modDoc,
this);
break;
}
case
(int)swDocumentTypes_e.swDocDRAWING:
{
docHandler = new
DrawingEventHandler(modDoc,
this);
break;
}
default:
{
return
false;
//Unsupported document type
}
}
docHandler.AttachEventHandlers();
openDocs.Add(modDoc, docHandler);
}
return
true;
}
public
bool
DetachModelEventHandler(ModelDoc2
modDoc)
{
DocumentEventHandler
docHandler;
docHandler = (DocumentEventHandler)openDocs[modDoc];
openDocs.Remove(modDoc);
modDoc = null;
docHandler = null;
return
true;
}
public
bool
DetachEventHandlers()
{
DetachSwEvents();
//Close events on all currently
open docs
DocumentEventHandler
docHandler;
int
numKeys = openDocs.Count;
object[]
keys = new
Object[numKeys];
//Remove all document event
handlers
openDocs.Keys.CopyTo(keys, 0);
foreach
(ModelDoc2
key in
keys)
{
docHandler = (DocumentEventHandler)openDocs[key];
docHandler.DetachEventHandlers();
//This also removes the pair from the hash
docHandler =
null;
}
return
true;
}
#endregion
#region Event Handlers
//Events
public
int
OnDocChange()
{
return
0;
}
public
int
OnDocLoad(string
docTitle, string
docPath)
{
return
0;
}
int
FileOpenPostNotify(string
FileName)
{
AttachEventsToAllDocuments();
return
0;
}
public
int
OnFileNew(object
newDoc, int
docType, string
templateName)
{
AttachEventsToAllDocuments();
return
0;
}
public
int
OnModelChange()
{
return
0;
}
#endregion
}
}