Intelligent custom object handles in MultiCAD.NET

Ease of editing drawings is one of the key characteristics of CAD systems. An important tool for working with drawing objects is grips - special markers at key points of the object that allow you to modify the object with the mouse, without using the menu or command line.
The handle control mechanism in MultiCAD.NET allows you to work with both simple and intelligent pens. We wrote about simple pens in a previous article, here we will consider intelligent pens, which, in addition to the shape (round, triangular, diamond-shaped, etc.), differ from simple ones in that they can change individual parameters of an object, call a pop-up menu, or perform a set of actions defined in a handler. In addition to this smart pen API, you can also create simple pens, but using a new, unified approach.
Under the cut, the code for creating several types of smart pens of the object and animated images demonstrating their use.
McSmartGrip <T> Class
The MultiCAD.NET API uses a class to describe smart pens
McSmartGrip<T>
. This class contains several constructor options with various lists of parameters, as well as event handlers that are generated depending on user actions:MoveGrip
- called when the handle is moved,MouseMove
- called when moving the pen interactive type,GetContextMenu
- called when you click on the handle with the typeGripType.PopupMenu
,OnCommand
- is called when you click on the handle with the typeGripType.Button
or on the context menu item obtained fromGetContextMenu
.
For example, to create a simple pen that is responsible for moving the point of an object, the following constructor can be used:
var simpleGrip = new McSmartGrip<ObjectRefEntity>(position, (obj, g, offset) => { obj.TryModify(); obj._pnt += offset; }
This constructor provides for the implementation of the delegate
MoveGrip
, which we did using the lambda expression ( http://msdn.microsoft.com/ru-ru/library/bb397687.aspx ), namely, we moved the position of the object by an amount offset
.Handle Registration
Handles of a custom object are registered using the
AppendGrip()
class method GripPointsInfo
:publicvoidAppendGrip(Multicad.CustomObjectBase.McBaseGrip grip);
This class is used as an argument to a method
GetGripPoints()
that is called to get handles each time an object is displayed:publicvirtualboolGetGripPoints(Multicad.CustomObjectBase.GripPointsInfo info);
The following code snippet creates and adds the same simple pen:
publicoverrideboolGetGripPoints(GripPointsInfo info)
{
info.AppendGrip(new McSmartGrip<ObjectRefEntity>(_pnt, (obj, g, offset) => { obj.TryModify(); obj._pnt += offset; }));
}
As you can see, the whole procedure is very compact and takes only one line of code. However, this concerned the most elementary case, namely, simple pens. Let's look at what other types of pens are supported in the MultiCAD.NET API, as well as the specifics of working with each of them.
Types of pens
Using MulitiCAD.NET, you can create the following types of pens:
Simple
- a simple pen. Handle handling processing is implemented inMoveGrip
.PopupMenu
- a pen that, when clicked, displays pop-up menus. Event handling is implemented inOnCommand
.Button
- a pen-button, when pressed, the actions described inOnCommand
.Interactive
- a type that is similar toSimple
, but allows you to work with object snaps. Unlike a simple handle, event handling is implemented inMouseMove
.
The appearance of the pens
One object may contain several pens of various types; in order to visually distinguish them, you can assign the appearance of each of them, determining its shape and color. The variety of shapes of pens is determined by enumeration
McBaseGrip.GripAppearance
. Here are some of them: 
You can also set the desired color of the pens from the set of colors defined in the class
GripColors
, or you can define the color in the standard way using System.Drawing.Color
. Let's see how it works. As an example, we take the familiar primitive
TextInBox
described in this article and create several intelligent pens of various types for it.Simple pen
We already mentioned this type of pens in the article, and, as the name suggests, it is used for simple actions, for example, for moving points of an object. Add one simple handle to move the corner point of our primitive:
info.AppendGrip(new McSmartGrip<ObjectRefEntity>(_pnt, (obj, g, offset) => { obj.TryModify(); obj._pnt += offset; }));
The result of the operation of such a pen is in the animated illustration:

Knob
Add a pen-button that will control the display of the frame around the text by clicking. To create such a pen, use the constructor with the type of pen
McBaseGrip.GripType.Button
and the base color. The button handler OnCommand
changes the value of the frame drawing indicator _show_frame
to the opposite. For the created button-handle, we define the appearance “on”, which will change to “off” when pressed, and vice versa.var OnOffGrip = new McSmartGrip<TextInBox>(McBaseGrip.GripType.Button, 1, _pnt + stepVector,
McBaseGrip.GripAppearance.SwitchOn, 0, "Hide Frame", GripColors.Base);
OnOffGrip.Tag = "OnOffGrip";
if (_show_frame == false)
OnOffGrip.SetAppearanceAndText(McBaseGrip.GripAppearance.SwitchOff, "Show frame");
OnOffGrip.OnCommand = (obj, commandId, grip) => { obj.TryModify(); obj._show_frame = !obj._show_frame;};
info.AppendGrip(OnOffGrip);
Result:

Also, by pressing the knob, the necessary registered command can be called up:
var cmdGrip = new McSmartGrip<TextInBox>( McBaseGrip.GripType.Button, 1, _pnt + 2 * stepVector,
McBaseGrip.GripAppearance.Circle, 0, "button", GripColors.Base);
cmdGrip.Tag="cmd";
cmdGrip.OnCommand = (obj, commandId, grip) =>
{
McContext.ExecuteCommand(grip.Tag.ToString());
};
Menu handle
Another type of pens that can be created in MultiCAD.NET is the handle for invoking the context menu. This type of handle is used when the user needs to select from the list the required value of an object parameter from the list.
This type of pens is created using a constructor with an indication of the type
McBaseGrip.GripType.PopupMenu
and appearance defined by the value McBaseGrip.GripAppearance.PopupMenu
. To work with the context menu, it is necessary to implement two delegates: GetContextMenu
- call the menu when you click on the handle, OnCommand
- call actions when selecting itemsvar ctxGrip = new McSmartGrip<TextInBox>(McBaseGrip.GripType.PopupMenu, 2, _pnt + 2 * stepVector,
McBaseGrip.GripAppearance.PopupMenu, 0, "Select menu", System.Drawing.Color.Lime);
ctxGrip.GetContextMenu = (obj, items) =>
{
items.Add(new ContextMenuItem("Command 1", "none", 1));
};
ctxGrip.OnCommand = (obj, commandId, grip) =>
{
if (grip.Id == 2)
{
switch (commandId)
{
case1:
{
MessageBox.Show("Command 1 is selected");
break;
}
}
}
};
info.AppendGrip(ctxGrip);
Result:

Interactive pen
And finally, the last type of pens that we look at is interactive. The main difference between these handles is that they can use information about binding objects and, depending on this, determine their behavior.
As an example, we add one of these pens, which allows us to change the text of our primitive to the name of the selected object (except for the parent object). Depending on the binding object, the pen will change color: in the initial state, the pen will have a color
GripColors.Base
, when you hover over the parent object, the color will change to Color.Red
, to any other object that supports the binding, to Color.Green
. An interactive pen is created by the constructor indicating the type
McBaseGrip.GripType.Interactive
, and the pen is implemented in the delegate MouseMove
(unlike simple pens, where it is usedMoveGrip
) var interactiveGrip = new McSmartGrip<TextInBox>(McBaseGrip.GripType.Interactive, 3, _pnt + 3 * stepVector,
McBaseGrip.GripAppearance.Arrow, 0, "interactive", GripColors.Base);
interactiveGrip.IsMovable = true;
interactiveGrip.MouseMove = (obj, entInfo, grip, offset) =>
{
grip.Color = GripColors.Base;
if (!entInfo.SnapedObjectId.IsNull)
{
if (ID == entInfo.SnapedObjectId)
{
grip.Color = Color.Red;
}
else
{
grip.Color = Color.Green;
obj.TryModify();
obj.Text = (entInfo.SnapedObjectId.GetObject().GetType().ToString());
}
}
};
info.AppendGrip(interactiveGrip);
Result: the text “Text field” is replaced by “MultiCAD.Samples.TextInBox”.

We have listed the main types of smart pens that allow you to create an effective interface for working with custom objects created on MultiCAD.NET. MultiCAD.NET documentation is part of the nanoCAD SDK, which can be accessed by registering with the nanoCAD Developer Club .
Discussion of the article is also available on our forum: forum.nanocad.ru/index.php?showtopic=6518 .
Article translation into English: Smart grips of custom object in MultiCAD.NET