You must have used the place line and copy element commands in Mstn. In fact, the commands in Mstn are divided into two categories: view commands and basic commands. The basic commands are divided into placement and modification. The two commands we want to implement in this chapter belong to the placement class and the modification class. They need to be implemented with classes derived from DgnPrimitiveTool and DgnElementSetTool respectively. The first one is to dynamically draw the coordinates of the specified point, and the second one is to perform multiple scaling and copying of the specified element. Both of these commands have a certain practical value and are put forward by users in actual work. Let us start step by step to see the execution results.
using Bentley.MstnPlatformNET;
using System.Windows.Forms;
namespace csAddins
{
[AddIn(MdlTaskID = "csAddins")]
internal sealed class MyAddin : AddIn
{
public static MyAddin Addin = null;
private MyAddin(System.IntPtr mdlDesc) : base(mdlDesc)
{
Addin = this;
}
protected override int Run(string[] commandLine)
{
Session.Instance.Keyin("csAddins DemoForm Toolbar");
return 0;
}
}
}
2. Open the NoteCoordForm.Designer.cs file in code as shown in the figure below, turn to the end of the code, and change the declarations of several controls from private to public. The modified code snippet is as follows. The reason for this modification is that we need to access these public member variables in other class codes that follow.
private System.Windows.Forms.GroupBox grpTxtDir; public System.Windows.Forms.RadioButton rdoHoriz; public System.Windows.Forms.RadioButton rdoVert; private System.Windows.Forms.GroupBox grpLabel; public System.Windows.Forms.RadioButton rdoXY; public System.Windows.Forms.RadioButton rdoEN;
3. Similarly, modify the MultiScaleCopyForm.Designer.cs file as follows:
public System.Windows.Forms.TextBox txtScale; private System.Windows.Forms.Label label1; private System.Windows.Forms.Label label2; public System.Windows.Forms.TextBox txtXOffset; private System.Windows.Forms.Label label3; public System.Windows.Forms.TextBox txtYOffset; private System.Windows.Forms.Label label4; public System.Windows.Forms.TextBox txtZOffset; private System.Windows.Forms.Label label5; public System.Windows.Forms.TextBox txtCopies; private System.Windows.Forms.Button btnDefault;
4. In order to realize the function of dynamically labeling the specified point coordinates, let's create a class NoteCoordClass which extends DgnPrimitiveTool. Documents related to this kind of help has not yet announced, but since CE under version Addin framework to NativeCode frame almost parallel, in NativeCode there is a class of the same name, so use this class that we can refer to NativeCode help This class is explained in the documentation ( …\Bentley\MicroStationCONNECTSDK\doc\MicroStationAPI.chm ).
Note: If you encounter any error while using DgnPrimitiveTool class, make sure to add a reference to Bentley.DgnDisplayNet.dll by selecting Project > Add Reference.
using Bentley.DgnPlatformNET;
using Bentley.DgnPlatformNET.Elements;
using Bentley.GeometryNET;
using Bentley.MstnPlatformNET;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace csAddins
{
class NoteCoordClass : DgnPrimitiveTool
{
private NoteCoordForm m_myForm;
private DPoint3d m_Point = new DPoint3d();
private int m_nPoints = 0;
public NoteCoordClass() : base(0, 0)
{
}
public static void InstallNewTool()
{
NoteCoordClass noteCoordClass = new NoteCoordClass();
noteCoordClass.InstallTool();
}
protected override void OnPostInstall()
{
if (m_myForm == null)
{
m_myForm = new NoteCoordForm();
m_myForm.AttachToToolSettings(MyAddin.Addin);
m_myForm.Show();
}
AccuSnap.SnapEnabled = true;
base.OnPostInstall();
}
private Element CreateNoteElement(DgnButtonEvent ev)
{
if (1 != m_nPoints)
return null;
DgnModel dgnModel = Session.Instance.GetActiveDgnModel();
DgnFile dgnFile = Session.Instance.GetActiveDgnFile();
string[] txtStr = new string[2];
DPoint3d[] txtPts = new DPoint3d[2];
Element[] elems = new Element[3];
txtStr[0] = (m_myForm.rdoEN.Checked ? "E=" : "X=") + m_Point.X.ToString("F2");
txtStr[1] = (m_myForm.rdoEN.Checked ? "N=" : "Y=") + m_Point.Y.ToString("F2");
DgnTextStyle txtStyle = DgnTextStyle.GetSettings(dgnFile);
double width = 0, txtLineSpacing = 0;
txtStyle.GetProperty(TextStyleProperty.Width, out width);
txtStyle.GetProperty(TextStyleProperty.Height, out txtLineSpacing);
double txtLen = width * Math.Max(txtStr[0].Length, txtStr[1].Length);
DPoint3d pt1 = ev.Point, pt2 = new DPoint3d();
if (m_myForm.rdoHoriz.Checked)
{
pt2.X = pt1.X + (m_Point.X > pt1.X ? -txtLen : txtLen) * 1.2;
pt2.Y = pt1.Y;
txtPts[0].X = (pt1.X + pt2.X) / 2;
txtPts[0].Y = pt1.Y + txtLineSpacing / 2;
txtPts[1].X = txtPts[0].X;
txtPts[1].Y = pt1.Y - txtLineSpacing / 2 * 3;
}
else
{
pt2.X = pt1.X;
pt2.Y = pt1.Y + (m_Point.Y > pt1.Y ? -txtLen : txtLen) * 1.2;
txtPts[0].X = pt1.X - txtLineSpacing / 2;
txtPts[0].Y = (pt1.Y + pt2.Y) / 2;
txtPts[1].X = pt1.X + txtLineSpacing / 2 * 3;
txtPts[1].Y = txtPts[0].Y;
}
DPoint3d[] ptArr = new DPoint3d[3];
ptArr[0] = m_Point;
ptArr[1] = pt1;
ptArr[2] = pt2;
LineStringElement lineStrEle = new LineStringElement(dgnModel, null, ptArr);
List<Element> eleList = new List<Element>();
eleList.Add(lineStrEle);
for (int i = 1; i < 3; i++)
{
TextBlockProperties txtBlockProp = new TextBlockProperties(dgnModel);
txtBlockProp.IsViewIndependent = false;
ParagraphProperties paraProp = new ParagraphProperties(dgnModel);
paraProp.Justification = TextElementJustification.CenterMiddle;
RunProperties runProp = new RunProperties(txtStyle, dgnModel);
TextBlock txtBlock = new TextBlock(txtBlockProp, paraProp, runProp, dgnModel);
txtBlock.AppendText(txtStr[i - 1]);
TextHandlerBase txtHandlerBase = TextHandlerBase.CreateElement(null, txtBlock);
DTransform3d trans = DTransform3d.Identity;
DPoint3d offset = new DPoint3d();
if (m_myForm.rdoVert.Checked)
{
DRange3d range3d = new DRange3d();
txtHandlerBase.CalcElementRange(out range3d);
trans.Matrix = DMatrix3d.FromColumns(new DVector3d(0, 1, 0), new DVector3d(-1, 0, 0), new DVector3d(0, 0, 1));
offset = new DPoint3d((range3d.Low.Y - range3d.High.Y) / 2 + txtPts[i - 1].X,
(range3d.Low.X - range3d.High.X) / 2 + txtPts[i - 1].Y, 0);
}
else
{
DRange3d range3d = new DRange3d();
txtHandlerBase.CalcElementRange(out range3d);
offset = new DPoint3d((range3d.Low.X - range3d.High.X) / 2 + txtPts[i - 1].X,
(range3d.High.Y - range3d.Low.Y) / 2 + txtPts[i - 1].Y, 0);
}
trans.Translation = offset;
TransformInfo transInfo = new TransformInfo(trans);
txtHandlerBase.ApplyTransform(transInfo);
eleList.Add(txtHandlerBase);
//if (myForm.rdoVert.Checked)
// elems[i].RotateAboutZ(txtPts[i - 1], Math.PI / 2);
}
DMatrix3d rMatrix = DMatrix3d.Identity;
DPoint3d ptScale = new DPoint3d(1, 1, 1);
CellHeaderElement cellHeaderEle = new CellHeaderElement(dgnModel, "NoteCoordCell", m_Point, rMatrix, eleList);
return cellHeaderEle;
}
protected override bool OnDataButton(DgnButtonEvent ev)
{
if(0==m_nPoints)
{
BeginDynamics();
m_Point = ev.Point;
m_nPoints = 1;
return false;
}
Element element = CreateNoteElement(ev);
element.AddToModel();
OnReinitialize();
return true;
}
protected override void OnDynamicFrame(DgnButtonEvent ev)
{
Element element = CreateNoteElement(ev);
if (null == element)
return;
RedrawElems redrawElems = new RedrawElems();
redrawElems.SetDynamicsViewsFromActiveViewSet(Bentley.MstnPlatformNET.Session.GetActiveViewport());
redrawElems.DrawMode = DgnDrawMode.TempDraw;
redrawElems.DrawPurpose = DrawPurpose.Dynamics;
redrawElems.DoRedraw(element);
}
protected override void OnCleanup()
{
m_myForm.DetachFromMicroStation();
}
protected override bool OnResetButton(DgnButtonEvent ev)
{
OnRestartTool();
return true;
}
protected override void OnRestartTool()
{
InstallNewTool();
}
}
}
We display myForm in the tool setting box by calling AttachToToolSettings and Show in the method OnPostInstall and uninstall myForm by calling DetachFromMicroStation in the command OnCleanup. OnPostInstall is called after the InstallTool is called and the tool class actually becomes the current command. In DgnPrimitiveTool base class DgnTool, there is an OnInstall method, this method is called InstallTool; these tools are called before the current command. In this way, we can make some judgments in this function. If certain conditions are not met, false is returned and the current command will not be started.
5. The function of multiple zooming and copying is shown below. To this end, you need to add a class derived from DgnElementSetTool as follows.
using Bentley.DgnPlatformNET;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Bentley.DgnPlatformNET.Elements;
using Bentley.GeometryNET;
using Bentley.MstnPlatformNET;
using BIM = Bentley.Interop.MicroStationDGN;
namespace csAddins
{
class MultiScaleCopyClass : DgnElementSetTool
{
private MultiScaleCopyForm m_myForm;
public MultiScaleCopyClass() : base(0, 0)
{
}
public static void InstallNewTool()
{
MultiScaleCopyClass multiScaleCopyClass = new MultiScaleCopyClass();
multiScaleCopyClass.InstallTool();
}
protected override void OnPostInstall()
{
if (m_myForm == null)
{
m_myForm = new MultiScaleCopyForm();
m_myForm.AttachToToolSettings(MyAddin.Addin);
m_myForm.Show();
}
base.OnPostInstall();
}
protected override void OnCleanup()
{
m_myForm.DetachFromMicroStation();
}
protected override bool OnResetButton(DgnButtonEvent ev)
{
OnRestartTool();
return true;
}
protected override void OnRestartTool()
{
InstallNewTool();
}
protected override bool NeedAcceptPoint()
{
return false;
}
public override StatusInt OnElementModify(Element element)
{
Bentley.Interop.MicroStationDGN.Element newEl;
double dScale = double.Parse(m_myForm.txtScale.Text);
DgnModel dgnModel = Session.Instance.GetActiveDgnModel();
double uorPerMaster = dgnModel.GetModelInfo().UorPerMaster;
DPoint3d offsetPnt = new DPoint3d(double.Parse(m_myForm.txtXOffset.Text)* uorPerMaster,
double.Parse(m_myForm.txtYOffset.Text) * uorPerMaster,
double.Parse(m_myForm.txtZOffset.Text) * uorPerMaster);
BIM.Application app = Bentley.MstnPlatformNET.InteropServices.Utilities.ComApp;
long eleId = element.ElementId;
Bentley.Interop.MicroStationDGN.Element BIMEle = app.ActiveModelReference.GetElementByID(ref eleId);
for (int i = 0; i < int.Parse(m_myForm.txtCopies.Text); i++)
{
newEl = app.ActiveModelReference.CopyElement(BIMEle);
long longid = newEl.ID;
ElementId elementId = new ElementId(ref longid);
Element newElement = dgnModel.FindElementById(elementId);
DRange3d range = new DRange3d();
((DisplayableElement)newElement).CalcElementRange(out range);
DTransform3d dTransform = DTransform3d.Identity;
dTransform.Translation=new DPoint3d(-(range.Low.X + range.High.X) / 2, -(range.Low.Y + range.High.Y) / 2,
-(range.Low.Z + range.High.Z) / 2);
DTransform3d dTransform2 = new DTransform3d(new DMatrix3d(dScale, 0, 0, 0, dScale, 0, 0, 0, dScale));
dTransform2 = DTransform3d.Multiply(dTransform2, dTransform);
dTransform = DTransform3d.Identity;
dTransform.Translation = new DPoint3d((range.Low.X + range.High.X) / 2 + offsetPnt.X, (range.Low.Y + range.High.Y) / 2 + offsetPnt.Y,
(range.Low.Z + range.High.Z) / 2 + offsetPnt.Z);
dTransform2 = DTransform3d.Multiply(dTransform, dTransform2);
newElement.ApplyTransform(new TransformInfo(dTransform2));
newElement.ReplaceInModel(newElement);
eleId = newElement.ElementId;
BIMEle = app.ActiveModelReference.GetElementByID(ref eleId);
}
return StatusInt.Error;
}
}
}
6. Finally, let us modify the TopLevel and ToolSettings methods in the DemoForm class as follows. TopLevel is used to start multiple zoom copying, and ToolSettings is used to start marking the coordinates of the specified point. Their background calls the InstallTool method inherited from DgnTool. It should be noted that, for the sake of simplicity, the program for marking the specified point coordinates is limited to work in the two-dimensional model, and the proportion of text annotations is not considered. The modified DemoForm.cs file is shown below.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace csAddins
{
class DemoForm
{
public static void Toolbar(string unparsed)
{
ToolbarForm myForm = new ToolbarForm();
myForm.AttachAsGuiDockable(MyAddin.Addin, "toolbar");
myForm.Show();
}
public static void Modal(string unparsed)
{
ModalForm myForm = new ModalForm();
if (DialogResult.OK == myForm.ShowDialog())
MessageBox.Show(myForm.textBox1.Text.ToString());
}
public static void TopLevel(string unparsed)
{
MultiScaleCopyClass.InstallNewTool();
//MultiScaleCopyForm myForm = new MultiScaleCopyForm();
//myForm.AttachAsTopLevelForm(MyAddin.Addin, false);
//myForm.Show();
}
public static void ToolSettings(string unparsed)
{
NoteCoordClass.InstallNewTool();
//NoteCoordForm myForm = new NoteCoordForm();
//myForm.AttachToToolSettings(MyAddin.Addin);
//myForm.Show();
}
}
}
7. Generate your csAddins and test. Draw a square in a two-dimensional model in advance, click the third icon in the toolbar after loading csAddins, select a corner point and drag out a dynamic label line and the specified point coordinate text, and then click a point to confirm the label position. The two generated annotations are shown in the following figure:
Click the second tool icon, set the parameters in the toolbox as shown in the figure below, select this square and confirm to generate the copy result as shown in the figure below.
In fact, MicroStation provides functions that do not require programming to customize the interface. These customized interfaces will be saved in a file called.DGNLIB, as long as the DGNLIB file is located in a directory pointed to by the configuration variable MS_DGNLIBLIST or MS_GUIDGNLIBLIST of Mstn, the DGNLIB file will be loaded when Mstn starts. This customization can be achieved by opening the DGNLIB and selecting the right-click menu Customize Ribbon on the Ribbon interface.
| Prev:[[Adding Windows Forms to Add-ins]] | Next:[[Responding to MicroStation Events]] |