Hi,
You may avoid using SendStringToexecute because it doesn't run synchronously.
You can define a 'Rectangle' Type with the properties and method you need.
Here's an example:
public class Rectangle
{
// constructor
public Rectangle(Point3d p1, Point3d p2)
{
LowerLeft = new Point3d(Math.Min(p1.X, p2.X), Math.Min(p1.Y, p2.Y), 0.0);
UpperRight = new Point3d(Math.Max(p1.X, p2.X), Math.Max(p1.Y, p2.Y), 0.0);
Length = UpperRight.X - LowerLeft.X;
Width = UpperRight.Y - LowerLeft.Y;
Area = Length * Width;
}
// public read only properties
public Point3d LowerLeft { get; private set; }
public Point3d UpperRight { get; private set; }
public double Length { get; private set; }
public double Width { get; private set; }
public double Area { get; private set; }
public SelectionSet CrossingSelectionSet
{
get { return Select(true); }
}
public SelectionSet WindowSelectionSet
{
get { return Select(false); }
}
// public method, draws the rectangle in the current space.
public void Draw()
{
Database db = HostApplicationServices.WorkingDatabase;
using (Transaction tr = db.TransactionManager.StartTransaction())
{
BlockTableRecord btr = (BlockTableRecord)tr.GetObject(db.CurrentSpaceId, OpenMode.ForWrite);
using (Polyline pline = new Polyline())
{
pline.AddVertexAt(0, new Point2d(LowerLeft.X, LowerLeft.Y), 0.0, 0.0, 0.0);
pline.AddVertexAt(1, new Point2d(UpperRight.X, LowerLeft.Y), 0.0, 0.0, 0.0);
pline.AddVertexAt(2, new Point2d(UpperRight.X, UpperRight.Y), 0.0, 0.0, 0.0);
pline.AddVertexAt(3, new Point2d(LowerLeft.X, UpperRight.Y), 0.0, 0.0, 0.0);
pline.Closed = true;
btr.AppendEntity(pline);
tr.AddNewlyCreatedDBObject(pline, true);
}
tr.Commit();
}
}
// public static method, creates a new instance of Rectangle if the user specifies two points
public static Rectangle Create()
{
Editor ed = Application.DocumentManager.MdiActiveDocument.Editor;
PromptPointResult ppr = ed.GetPoint("\nFirst corner: ");
if (ppr.Status == PromptStatus.Cancel)
return null;
Point3d pt = ppr.Value;
ppr = ed.GetCorner("\nSecond corner: ", pt);
if (ppr.Status == PromptStatus.Cancel)
return null;
Matrix3d ucs = ed.CurrentUserCoordinateSystem;
return new Rectangle(pt.TransformBy(ucs), ppr.Value.TransformBy(ucs));
}
// private method, returns the selection set
private SelectionSet Select(bool crossing)
{
Editor ed = AcAp.DocumentManager.MdiActiveDocument.Editor;
Matrix3d wcs = ed.CurrentUserCoordinateSystem.Inverse();
return crossing ?
ed.SelectCrossingWindow(LowerLeft.TransformBy(wcs), UpperRight.TransformBy(wcs)).Value :
ed.SelectWindow(LowerLeft.TransformBy(wcs), UpperRight.TransformBy(wcs)).Value;
}
}
Then, using this type, you can prompt the user to draw a rectangle the same wat as the native AutoCAD Command, get the data you need (length, width and area), use the rectangle to get a selection set.
Here's a little example:
[CommandMethod("test")]
public void test()
{
Editor ed = Application.DocumentManager.MdiActiveDocument.Editor;
Rectangle rect = Rectangle.Create();
if (rect == null)
return;
SelectionSet ss = rect.WindowSelectionSet;
ed.SetImpliedSelection(ss);
rect.Draw();
ed.WriteMessage("\nLength = {0} Width = {1} Area = {2}", rect.Length, rect.Width, rect.Area);
}