参考资料《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:TempMyDrawing"; [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(" Command "MyCmd" failed:"); ed.WriteMessage(" {0} {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:CADtestaaaa.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(" 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(" 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(" Another plot is in progress."); } } catch( Autodesk.AutoCAD.Runtime.Exception ee) { ed.WriteMessage("error:"+ee.Message.ToString()); } }