Kean Walmsley

July 2009

Sun Mon Tue Wed Thu Fri Sat
      1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31  

Twitter Updates

    follow me on Twitter



    « Driving a multi-sheet AutoCAD plot using .NET | Main | Free webcast reminder: "AutoCAD: 10 easy ways to crash your AutoCAD addin" »

    October 01, 2007

    Previewing and plotting a single sheet in AutoCAD using .NET

    This week's posts take the code I threw together last week for single-sheet and multi-sheet plotting, and introduces the concept of "plot preview".

    I'm learning as I go for much of this, so there are structural (although usually not functional) changes being made to the code as it develops. In this instance, for example, I've factored off common functionality needed by both previewing and plotting into a single helper function. This will no doubt evolve further (and change in structure) when I come to apply the principle to multi-sheet plotting later in the week.

    Here's the C# code:

    using Autodesk.AutoCAD.Runtime;

    using Autodesk.AutoCAD.ApplicationServices;

    using Autodesk.AutoCAD.DatabaseServices;

    using Autodesk.AutoCAD.EditorInput;

    using Autodesk.AutoCAD.PlottingServices;


    namespace PlottingApplication

    {

      public class PreviewCommands

      {

        [CommandMethod("simprev")]

        static public void SimplePreview()

        {

          Document doc =

            Application.DocumentManager.MdiActiveDocument;

          Editor ed = doc.Editor;

          Database db = doc.Database;


          // PlotEngines do the previewing and plotting


          if (PlotFactory.ProcessPlotState ==

              ProcessPlotState.NotPlotting)

          {

            // First we preview...


            PreviewEndPlotStatus stat;

            PlotEngine pre =

              PlotFactory.CreatePreviewEngine(

                (int)PreviewEngineFlags.Plot

              );

            using (pre)

            {

              stat =

                PlotOrPreview(

                  pre,

                  true,

                  db.CurrentSpaceId,

                  ""

                );

            }

            if (stat == PreviewEndPlotStatus.Plot)

            {

              // And if the user asks, we plot...


              PlotEngine ple =

                PlotFactory.CreatePublishEngine();

              stat =

                PlotOrPreview(

                  ple,

                  false,

                  db.CurrentSpaceId,

                  "c:\\previewed-plot"

                );

            }

          }

          else

          {

            ed.WriteMessage(

              "\nAnother plot is in progress."

            );

          }

        }


        static PreviewEndPlotStatus PlotOrPreview(

          PlotEngine pe,

          bool isPreview,

          ObjectId spaceId,

          string filename)

        {

          Document doc =

            Application.DocumentManager.MdiActiveDocument;

          Editor ed = doc.Editor;

          Database db = doc.Database;


          PreviewEndPlotStatus ret =

            PreviewEndPlotStatus.Cancel;


          Transaction tr =

            db.TransactionManager.StartTransaction();

          using (tr)

          {

            // We'll be plotting the current layout


            BlockTableRecord btr =

              (BlockTableRecord)tr.GetObject(

                spaceId,

                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 PlotSettings object

            // based on the layout settings

            // which we then customize


            PlotSettings ps =

              new PlotSettings(lo.ModelType);

            ps.CopyFrom(lo);


            // The PlotSettingsValidator helps

            // create a valid PlotSettings object


            PlotSettingsValidator psv =

              PlotSettingsValidator.Current;


            // We'll plot the extents, centered and

            // scaled to fit


            psv.SetPlotType(

              ps,

              Autodesk.AutoCAD.DatabaseServices.PlotType.Extents

            );

            psv.SetUseStandardScale(ps, true);

            psv.SetStdScaleType(ps, StdScaleType.ScaleToFit);

            psv.SetPlotCentered(ps, true);


            // We'll use the standard DWF PC3, as

            // for today we're just plotting to file


            psv.SetPlotConfigurationName(

              ps,

              "DWF6 ePlot.pc3",

              "ANSI_A_(8.50_x_11.00_Inches)"

            );


            // 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);


            // Create a Progress Dialog to provide info

            // and allow thej user to cancel


            PlotProgressDialog ppd =

              new PlotProgressDialog(isPreview, 1, true);

            using (ppd)

            {

              ppd.set_PlotMsgString(

                PlotMessageIndex.DialogTitle,

                "Custom Preview Progress"

              );

              ppd.set_PlotMsgString(

                PlotMessageIndex.SheetName,

                doc.Name.Substring(

                  doc.Name.LastIndexOf("\\") + 1

                )

              );

              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 plot/preview, at last


              ppd.OnBeginPlot();

              ppd.IsVisible = true;

              pe.BeginPlot(ppd, null);


              // We'll be plotting/previewing

              // a single document


              pe.BeginDocument(

                pi,

                doc.Name,

                null,

                1,

                !isPreview,

                filename

              );


              // 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);

              ppd.SheetProgressPos = 50;

              pe.EndGenerateGraphics(null);


              // Finish the sheet


              PreviewEndPlotInfo pepi =

                new PreviewEndPlotInfo();

              pe.EndPage(pepi);

              ret = pepi.Status;


              ppd.SheetProgressPos = 100;

              ppd.OnEndSheet();


              // Finish the document


              pe.EndDocument(null);


              // And finish the plot


              ppd.PlotProgressPos = 100;

              ppd.OnEndPlot();

              pe.EndPlot(null);

            }


            // Committing is cheaper than aborting


            tr.Commit();

          }

          return ret;

        }

      }

    }

    When you execute the SIMPREV command, you receive enter a "preview" mode, from where you can either cancel or plot. The trick was really in determining the button selected by the user, which we do by passing an appropriate object (of class PreviewEndPlotInfo) into the EndPage() function, to collect information on what the users selects. The next post will take this further, allowing the user to cycle through multiple sheets using "next" and "previous" buttons.

    TrackBack

    TrackBack URL for this entry:
    http://www.typepad.com/services/trackback/6a00d83452464869e200e54f0251ec8834

    Listed below are links to weblogs that reference Previewing and plotting a single sheet in AutoCAD using .NET:

    Comments

    first, thank you for posting to this blog. I have learned a lot from you and this site.

    I copied the above code to a fresh project but wanted to plot to the StyleSheet "monochrome.ctb." however, I get the below error. am I missing something?

    I place the below code between the
    SetStdScaleType and SetPlotCentered lines.

    psv.SetCurrentStyleSheet(ps, "monochrome.ctb");

    --------
    System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. ---> Autodesk.AutoCAD.Runtime.Exception: eInvalidInput
    at Autodesk.AutoCAD.DatabaseServices.PlotSettingsValidator.SetCurrentStyleSheet(PlotSettings plotSet, String styleSheetName)
    at ClassLibrary.PreviewCommands.PlotOrPreview

    I see what you're experiencing... interestingly when I add this call before yours (even if I don't use the results directly), the code works:

    System.Collections.Specialized.StringCollection sc = psv.GetPlotStyleSheetList();

    Regards,

    Kean

    Verify your Comment

    Previewing your Comment

    This is only a preview. Your comment has not yet been posted.

    Working...
    Your comment could not be posted. Error type:
    Your comment has been posted. Post another comment

    The letters and numbers you entered did not match the image. Please try again.

    As a final step before posting your comment, enter the letters and numbers you see in the image below. This prevents automated programs from posting comments.

    Having trouble reading this image? View an alternate.

    Working...

    Post a comment

    Feed & Share

    Search