CAD 二次开发(.Net)-1

参考资料《AutoCAD二次开发(李冠亿).pdf》

功能一:以C#实现根据范围输出WMF文件

         在CAD中,输出文件主要以两种方式:打印(plotting),输出(Export,该函数主要存在于Com组件中)

       输出方式(一)代码:

    

using System.Collections.Generic;
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Runtime;

using Autodesk.AutoCAD.Interop;        / /需要添加对cad  com组件引用      
using Autodesk.AutoCAD.Interop.Common;  //需要添加对cad com组件引用 

[assembly: CommandClass(typeof(ExportWmf.MyCommands))]

namespace ExportWmf
{
    public class MyCommands
    {
        private static string wmfFile=@"C:\Temp\MyDrawing";

        [CommandMethod("WmfExport")]
        public static void RunMyCommand()
        {
            Document dwg = Application.DocumentManager.MdiActiveDocument;
            Editor ed = dwg.Editor;

            AcadSelectionSet ss = null;
            AcadDocument doc = (AcadDocument)dwg.AcadDocument;

            try
            {
                AcadApplication app=Application.AcadApplication as AcadApplication;
                app.ZoomExtents();

                //--Use COM API to select objects
                //ss = GetAcadSelectionSet1(doc);

                //Use .NET API to select objects, and 
                //selected objects must to be cast to AcadEntity
                //before populated into AcadSelecctionSet
                ss = GetAcadSelectionSet2(dwg);

                if (System.IO.File.Exists(wmfFile)) System.IO.File.Delete(wmfFile);

                doc.Export(wmfFile, "WMF", ss);
            }
            catch (System.Exception ex)
            {
                ed.WriteMessage("\nCommand \"MyCmd\" failed:");
                ed.WriteMessage("\n{0}\n{1}", ex.Message, ex.StackTrace);
            }
            finally
            {
                ss.Delete();
                Autodesk.AutoCAD.Internal.Utils.PostCommandPrompt();
            }
        }

        private static AcadSelectionSet GetAcadSelectionSet1(AcadDocument doc)
        {
            AcadSelectionSet ss = doc.SelectionSets.Add("WmfSet");

            ss.Select(AcSelect.acSelectionSetAll);

            return ss;
        }

        private static AcadSelectionSet GetAcadSelectionSet2(Document dwg)
        {
            AcadDocument doc = dwg.AcadDocument as AcadDocument;
            AcadSelectionSet ss = doc.SelectionSets.Add("WmfSet");

            List<AcadEntity> lst = new List<AcadEntity>();

            PromptSelectionResult res = dwg.Editor.SelectAll();
            if (res.Status == PromptStatus.OK)
            {
                using (Transaction tran = dwg.TransactionManager.StartTransaction())
                {
                    foreach (ObjectId id in res.Value.GetObjectIds())
                    {
                        Entity ent = (Entity)tran.GetObject(id, OpenMode.ForRead);
                        lst.Add(ent.AcadObject as AcadEntity);
                    }

                    tran.Commit();
                }

                ss.AddItems(lst.ToArray());
                return ss;
            }
            else
            {
                return null;
            }
        }
    }
}

 

      输出代码:由于Autodesk.AutoCAD.Interop.DLL 与。net 两套API  定义具有重复性,因此对代码进行修改,利用C#“扩展方法” 对 代码进行优化

  

using BF = System.Reflection.BindingFlags;

namespace LateBindingHelpers
{
    public static class LateBinding
    {
        public static object GetInstance(string appName)
        {
            return System.Runtime.InteropServices.Marshal.GetActiveObject(appName);
        }

        public static object CreateInstance(string appName)
        {
            return System.Activator.CreateInstance(System.Type.GetTypeFromProgID(appName));
        }

        public static object GetOrCreateInstance(string appName)
        {
            try { return GetInstance(appName); }
            catch { return CreateInstance(appName); }
        }

        public static void ReleaseInstance(this object obj)
        {
            System.Runtime.InteropServices.Marshal.ReleaseComObject(obj);
        }

        public static object Get(this object obj, string propName, params object[] parameter)
        {
            return obj.GetType().InvokeMember(propName, BF.GetProperty, null, obj, parameter);
        }

        public static void Set(this object obj, string propName, params object[] parameter)
        {
            obj.GetType().InvokeMember(propName, BF.SetProperty, null, obj, parameter);
        }

        public static object Invoke(this object obj, string methName, params object[] parameter)
        {
            return obj.GetType().InvokeMember(methName, BF.InvokeMethod, null, obj, parameter);
        }
    }
}

 

 

 

using LateBindingHelpers;   //自定义 object 扩展函数        

[CommandMethod("ExportWMF")] static public void ExportWMF() { Document doc = Application.DocumentManager.MdiActiveDocument; Database db = doc.Database; Editor ed = doc.Editor; using (Transaction trans = db.TransactionManager.StartTransaction()) { BlockTable bt = trans.GetObject(db.BlockTableId, OpenMode.ForRead) as BlockTable; BlockTableRecord btr = trans.GetObject(bt[BlockTableRecord.ModelSpace], OpenMode.ForWrite) as BlockTableRecord; ObjectId refid = db.OverlayXref(@"F:\CADtest\aaaa.dwg", "name"); BlockReference br = new BlockReference(Point3d.Origin, refid); btr.AppendEntity(br); trans.AddNewlyCreatedDBObject(br, true); trans.Commit(); } // PromptSelectionResult psr = ed.GetSelection(); // PromptSelectionResult psr = ed.SelectAll(); double x1=271; double y1=257; double z1=0; double x2=380; double y2=181; double z2=0; Point3d p1=new Point3d(x1,y1,z1); Point3d p2=new Point3d(x2,y2,z2); PromptSelectionResult psr = ed.SelectCrossingWindow(p1, p2); if (psr.Status != PromptStatus.OK) return; object acadDoc = doc.AcadDocument; // replace with doc.Getacaddocument() for A2013+ object selSet = acadDoc.Get("ActiveSelectionSet"); acadDoc.Invoke( "Export", System.IO.Path.ChangeExtension(db.Filename, "wmf"), "wmf", selSet); selSet.Invoke("Delete"); }

 

 

 

 

 

 

 

 

        打印代码:

    

[CommandMethod("winplot")]
        static public void windowPlot()
        {
            Document doc = Application.DocumentManager.MdiActiveDocument;
            Editor ed = doc.Editor;
            Database db = doc.Database;
            string namea = doc.Name;
            PromptPointOptions ppo = new PromptPointOptions("\n select first coner of plot area:");
            ppo.AllowNone = false;

            PromptPointResult ppr = ed.GetPoint(ppo);
            if (ppr.Status != PromptStatus.OK)
                return;
            Point3d first = ppr.Value;

            PromptCornerOptions pco = new PromptCornerOptions("\n select sencond corner of plot area:", first);
            ppr = ed.GetCorner(pco);
            if (ppr.Status != PromptStatus.OK)
                return;
            Point3d second = ppr.Value;

            // transform  from UCS to DCS 
            ResultBuffer rbFrom = new ResultBuffer(new TypedValue(5003, 1)),
                          rbTo = new ResultBuffer(new TypedValue(5003, 2));
            double[] firres = new double[] { 0, 0, 0 };
            double[] secres = new double[] { 0, 0, 0 };

            //transform the first point...
            acedTrans(
                first.ToArray(),
                rbFrom.UnmanagedObject,
                rbTo.UnmanagedObject,
                0,
                firres
            );
            
            //....the second
            acedTrans(
               second.ToArray(),
               rbFrom.UnmanagedObject,
               rbTo.UnmanagedObject,
               0,
               secres
            );

            // we can sately drop the Z-coord at this stage
            Extents2d window = new Extents2d(firres[0], firres[1], secres[0], secres[1]);

            Transaction tr = db.TransactionManager.StartTransaction();

            using (tr)
            {
                //we'll be plotting the current layout
                BlockTableRecord btr = (BlockTableRecord)tr.GetObject(db.CurrentSpaceId, OpenMode.ForRead);
                Layout lo = (Layout)tr.GetObject(btr.LayoutId, OpenMode.ForRead);
                //we need a plotInfo object
                // linked to the layout
                PlotInfo pi = new PlotInfo();
                pi.Layout = btr.LayoutId;

                //we need a plotsetting objec
                //based on the layout settings
                //which we then customize

                PlotSettings ps = new PlotSettings(lo.ModelType);
                ps.CopyFrom(lo);

                //the plotsettingValidator helps create a valid Plotsettings object

                PlotSettingsValidator psv = PlotSettingsValidator.Current;

                //we will plot the extense, centerred and scaled to fit

                psv.SetPlotWindowArea(ps, window);
                psv.SetPlotType(ps, Autodesk.AutoCAD.DatabaseServices.PlotType.Window);
                psv.SetUseStandardScale(ps, true);
                psv.SetStdScaleType(ps, StdScaleType.ScaleToFit);
                psv.SetPlotCentered(ps, true);


                //we will use the staandard DWF PCS3 ,as for today we ate just plooting to file

              //  psv.SetPlotConfigurationName(ps, "DWF6 ePlot.pc3", "ANSI_A_(8.50_x_11.00_Inches)");
              //  psv.SetPlotConfigurationName(ps, "PublishToWeb PNG.pc3", "VGA_(800.00_x_600.00_Pixels)");
                psv.SetPlotConfigurationName(ps, "PublishToWeb PNG.pc3", "XGA_Hi-Res_(1600.00_x_1200.00_Pixels)");
                
                // we need to link the plotinfo to the plotsettings and then validate it

                pi.OverrideSettings = ps;
                PlotInfoValidator piv = new PlotInfoValidator();
                piv.MediaMatchingPolicy = MatchingPolicy.MatchEnabled;
                piv.Validate(pi);

                // a plotEngine does the actual plotting (can also create one for preview);
                try
                {

                    if (PlotFactory.ProcessPlotState == ProcessPlotState.NotPlotting)
                    {

                        PlotEngine pe = PlotFactory.CreatePublishEngine();
                        using (pe)
                        {
                            //create a progress dialog to privide info and allow the user to canle
                            PlotProgressDialog ppd = new PlotProgressDialog(false, 1, true);
                            using (ppd)
                            {
                                ppd.set_PlotMsgString(PlotMessageIndex.DialogTitle, "Custom Plot Progress");
                                ppd.set_PlotMsgString(PlotMessageIndex.CancelJobButtonMessage, "Cancel Job");
                                ppd.set_PlotMsgString(PlotMessageIndex.CancelSheetButtonMessage, "Cancel Sheet");
                                ppd.set_PlotMsgString(PlotMessageIndex.SheetSetProgressCaption, "Sheet set progress");
                                ppd.set_PlotMsgString(PlotMessageIndex.SheetProgressCaption, "Sheet Progress");

                                ppd.LowerPlotProgressRange = 0;
                                ppd.UpperPlotProgressRange = 100;
                                ppd.PlotProgressPos = 0;

                                // let's start the lot  as last

                                ppd.OnBeginPlot();
                                ppd.IsVisible = true;
                                pe.BeginPlot(ppd, null);

                                // we'll be plooting a single document
                                pe.BeginDocument(pi, doc.Name, null, 1, true, "c:\\test-output\\b7.png");

                                //which  contains a single sheet
                                ppd.OnBeginSheet();

                                ppd.LowerSheetProgressRange = 0;
                                ppd.UpperSheetProgressRange = 100;
                                ppd.SheetProgressPos = 0;

                                PlotPageInfo ppi = new PlotPageInfo();
                                pe.BeginPage(ppi, pi, true, null);

                                pe.BeginGenerateGraphics(null);
                                pe.EndGenerateGraphics(null);

                                //finish the sheet
                                pe.EndPage(null);
                                ppd.SheetProgressPos = 100;
                                ppd.OnEndSheet();

                                //finish the document
                                pe.EndDocument(null);

                                // and finish the plot
                                ppd.PlotProgressPos = 100;
                                ppd.OnEndPlot();
                                pe.EndPlot(null);
                            }

                        }
                    }
                    else
                    {

                        ed.WriteMessage("\nAnother plot is in progress.");

                    }

                }
                catch( Autodesk.AutoCAD.Runtime.Exception  ee)
                {
                    ed.WriteMessage("error:"+ee.Message.ToString());

                }



            }

 

posted on 2014-03-27 16:09  markygis  阅读(12992)  评论(3编辑  收藏  举报