Allowing selection of an AutoCAD plot device and media name using .NET

A comment came in on this previous post regarding how best to know whether a media name is valid during your plot configuration.

There are a few approaches, other than the one I chose of hardcoding the device and media names. The first is to implement a user interface of some kind which allows the user to select the device and media names. Another approach for setting the media name is to use PlotSettingsValidator.SetClosestMediaName() to choose the media name that most closely matches the paper size you desire.

Today I'll focus on the first option, although I'm only going to implement a basic, command-line user interface. It should be straightforward to extend this to implement a WinForm with comboboxes for the device and media names.

I implemented a simple function called ChooseDeviceAndMedia() which queries the current device list, allows selection from it, and then gets the media name list and allows selection from that. I chose not to worry about displaying locale-specific names, for now - I'll leave that for a future post (let me know if you're interested :-).

Here's the function integrated into the C# code from this previous post, which defines a command called MPLOT:

using Autodesk.AutoCAD.Runtime;

using Autodesk.AutoCAD.ApplicationServices;

using Autodesk.AutoCAD.DatabaseServices;

using Autodesk.AutoCAD.EditorInput;

using Autodesk.AutoCAD.Geometry;

using Autodesk.AutoCAD.PlottingServices;

using System.Collections.Specialized;

namespace PlottingApplication

{

  public class PlottingCommands

  {

    static public string[] ChooseDeviceAndMedia()

    {

      Document doc =

        Application.DocumentManager.MdiActiveDocument;

      Editor ed = doc.Editor;

      // Assign default return values

      string devname = "", medname = "";

      PlotSettingsValidator psv =

        PlotSettingsValidator.Current;

      // Let's first select the device

      StringCollection devlist =

        psv.GetPlotDeviceList();

      for (int i = 0; i < devlist.Count; i++)

      {

        ed.WriteMessage(

          "\n{0} {1}",

          i + 1,

          devlist[i]

        );

      }

      PromptIntegerOptions opts =

        new PromptIntegerOptions(

          "\nEnter number of device to select: "

        );

      opts.LowerLimit = 1;

      opts.UpperLimit = devlist.Count;

      PromptIntegerResult pir =

        ed.GetInteger(opts);

      if (pir.Status == PromptStatus.OK)

      {

        devname = devlist[pir.Value - 1];

        ed.WriteMessage(

          "\nSelected: {0}\n",

          devname

        );

        // Now let's select the media

        PlotSettings ps = new PlotSettings(true);

        using (ps)

        {

          // We should refresh the lists,

          // in case setting the device impacts

          // the available media

          psv.SetPlotConfigurationName(

            ps,

            devname,

            null

          );

          psv.RefreshLists(ps);

          StringCollection medlist =

            psv.GetCanonicalMediaNameList(ps);

          for (int i = 0; i < medlist.Count; i++)

          {

            ed.WriteMessage(

              "\n{0} {1}",

              i + 1,

              medlist[i]

            );

          }

          opts.Message =

            "\nEnter number of media to select: ";

          opts.LowerLimit = 1;

          opts.UpperLimit = medlist.Count;

          pir = ed.GetInteger(opts);

          if (pir.Status == PromptStatus.OK)

          {

            medname = medlist[pir.Value - 1];

            ed.WriteMessage(

              "\nSelected: {0}\n",

              medname

            );

          }

        }

      }

      return new string[2] { devname, medname };

    }

    [CommandMethod("mplot")]

    static public void MultiSheetPlot()

    {

      Document doc =

        Application.DocumentManager.MdiActiveDocument;

      Editor ed = doc.Editor;

      Database db = doc.Database;

      Transaction tr =

        db.TransactionManager.StartTransaction();

      using (tr)

      {

        BlockTable bt =

          (BlockTable)tr.GetObject(

            db.BlockTableId,

            OpenMode.ForRead

          );

        PlotInfo pi = new PlotInfo();

        PlotInfoValidator piv =

          new PlotInfoValidator();

        piv.MediaMatchingPolicy =

          MatchingPolicy.MatchEnabled;

        // A PlotEngine does the actual plotting

        // (can also create one for Preview)

        if (PlotFactory.ProcessPlotState ==

            ProcessPlotState.NotPlotting)

        {

          string[] devmed = ChooseDeviceAndMedia();

          // Only proceed if we have values for both

          if (devmed[0] != "" && devmed[1] != "")

          {

            string devname = devmed[0];

            string medname = devmed[1];

            PlotEngine pe =

              PlotFactory.CreatePublishEngine();

            using (pe)

            {

              // Collect all the paperspace layouts

              // for plotting

              ObjectIdCollection layoutsToPlot =

                new ObjectIdCollection();

              foreach (ObjectId btrId in bt)

              {

                BlockTableRecord btr =

                  (BlockTableRecord)tr.GetObject(

                    btrId,

                    OpenMode.ForRead

                  );

                if (btr.IsLayout &&

                    btr.Name.ToUpper() !=

                      BlockTableRecord.ModelSpace.ToUpper())

                {

                  layoutsToPlot.Add(btrId);

                }

              }

              // Create a Progress Dialog to provide info

              // and allow thej user to cancel

              PlotProgressDialog ppd =

                new PlotProgressDialog(

                  false,

                  layoutsToPlot.Count,

                  true

                );

              using (ppd)

              {

                int numSheet = 1;

                foreach (ObjectId btrId in layoutsToPlot)

                {

                  BlockTableRecord btr =

                    (BlockTableRecord)tr.GetObject(

                      btrId,

                      OpenMode.ForRead

                    );

                  Layout lo =

                    (Layout)tr.GetObject(

                      btr.LayoutId,

                      OpenMode.ForRead

                    );

                  // 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 DWFx PC3, as

                  // this supports multiple sheets

                  psv.SetPlotConfigurationName(

                    ps,

                    devname,

                    medname

                  );

                  // We need a PlotInfo object

                  // linked to the layout

                  pi.Layout = btr.LayoutId;

                  // Make the layout we're plotting current

                  LayoutManager.Current.CurrentLayout =

                    lo.LayoutName;

                  // We need to link the PlotInfo to the

                  // PlotSettings and then validate it

                  pi.OverrideSettings = ps;

                  piv.Validate(pi);

                  if (numSheet == 1)

                  {

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

                    ppd.OnBeginPlot();

                    ppd.IsVisible = true;

                    pe.BeginPlot(ppd, null);

                    // We'll be plotting a single document

                    pe.BeginDocument(

                      pi,

                      doc.Name,

                      null,

                      1,

                      true, // Let's plot to file

                      "c:\\test-multi-sheet"

                    );

                  }

                  // Which may contains multiple sheets

                  ppd.set_PlotMsgString(

                    PlotMessageIndex.SheetName,

                    doc.Name.Substring(

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

                    ) +

                    " - sheet " + numSheet.ToString() +

                    " of " + layoutsToPlot.Count.ToString()

                  );

                  ppd.OnBeginSheet();

                  ppd.LowerSheetProgressRange = 0;

                  ppd.UpperSheetProgressRange = 100;

                  ppd.SheetProgressPos = 0;

                  PlotPageInfo ppi = new PlotPageInfo();

                  pe.BeginPage(

                    ppi,

                    pi,

                    (numSheet == layoutsToPlot.Count),

                    null

                  );

                  pe.BeginGenerateGraphics(null);

                  ppd.SheetProgressPos = 50;

                  pe.EndGenerateGraphics(null);

                  // Finish the sheet

                  pe.EndPage(null);

                  ppd.SheetProgressPos = 100;

                  ppd.OnEndSheet();

                  numSheet++;

                  ppd.PlotProgressPos +=

                    (100 / layoutsToPlot.Count);

                }

                // 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."

          );

        }

      }

    }

  }

}

Here's what I see at the command-line when I run the MPLOT command on my system (items 7-18 below are network printers in various Autodesk offices):

Command: MPLOT

1 None

2 SnagIt 8

3 PDF-XChange 3.0

4 Microsoft XPS Document Writer

5 Microsoft Office Live Meeting Document Writer

6 Adobe PDF

7 \\adscctps1\cctprn000

8 \\adsneups2\neuprn304

9 \\adsneups2\neuprn306

10 \\adsneups2\neuprn307

11 \\adsneups2\neuprn317

12 \\banhpa001\banprn001

13 \\beihpa001\BEIPRN002

14 \\beihpa001\BEIPRN003

15 \\farhpa001\FARPRN101

16 \\pra-pc61237\Xerox WorkCentre Pro 35 PCL6

17 \\tokhpa001\tokprn401

18 \\tokhpa001\tokprn402

19 Default Windows System Printer.pc3

20 DWF6 ePlot.pc3

21 DWFx ePlot (XPS Compatible).pc3

22 DWG To PDF.pc3

23 PublishToWeb JPG.pc3

24 PublishToWeb PNG.pc3

Enter number of device to select: 22

Selected: DWG To PDF.pc3

1 ISO_expand_A0_(841.00_x_1189.00_MM)

2 ISO_A0_(841.00_x_1189.00_MM)

3 ISO_expand_A1_(841.00_x_594.00_MM)

4 ISO_expand_A1_(594.00_x_841.00_MM)

5 ISO_A1_(841.00_x_594.00_MM)

6 ISO_A1_(594.00_x_841.00_MM)

7 ISO_expand_A2_(594.00_x_420.00_MM)

8 ISO_expand_A2_(420.00_x_594.00_MM)

9 ISO_A2_(594.00_x_420.00_MM)

10 ISO_A2_(420.00_x_594.00_MM)

11 ISO_expand_A3_(420.00_x_297.00_MM)

12 ISO_expand_A3_(297.00_x_420.00_MM)

13 ISO_A3_(420.00_x_297.00_MM)

14 ISO_A3_(297.00_x_420.00_MM)

15 ISO_expand_A4_(297.00_x_210.00_MM)

16 ISO_expand_A4_(210.00_x_297.00_MM)

17 ISO_A4_(297.00_x_210.00_MM)

18 ISO_A4_(210.00_x_297.00_MM)

19 ARCH_expand_E1_(30.00_x_42.00_Inches)

20 ARCH_E1_(30.00_x_42.00_Inches)

21 ARCH_expand_E_(36.00_x_48.00_Inches)

22 ARCH_E_(36.00_x_48.00_Inches)

23 ARCH_expand_D_(36.00_x_24.00_Inches)

24 ARCH_expand_D_(24.00_x_36.00_Inches)

25 ARCH_D_(36.00_x_24.00_Inches)

26 ARCH_D_(24.00_x_36.00_Inches)

27 ARCH_expand_C_(24.00_x_18.00_Inches)

28 ARCH_expand_C_(18.00_x_24.00_Inches)

29 ARCH_C_(24.00_x_18.00_Inches)

30 ARCH_C_(18.00_x_24.00_Inches)

31 ANSI_expand_E_(34.00_x_44.00_Inches)

32 ANSI_E_(34.00_x_44.00_Inches)

33 ANSI_expand_D_(34.00_x_22.00_Inches)

34 ANSI_expand_D_(22.00_x_34.00_Inches)

35 ANSI_D_(34.00_x_22.00_Inches)

36 ANSI_D_(22.00_x_34.00_Inches)

37 ANSI_expand_C_(22.00_x_17.00_Inches)

38 ANSI_expand_C_(17.00_x_22.00_Inches)

39 ANSI_C_(22.00_x_17.00_Inches)

40 ANSI_C_(17.00_x_22.00_Inches)

41 ANSI_expand_B_(17.00_x_11.00_Inches)

42 ANSI_expand_B_(11.00_x_17.00_Inches)

43 ANSI_B_(17.00_x_11.00_Inches)

44 ANSI_B_(11.00_x_17.00_Inches)

45 ANSI_expand_A_(11.00_x_8.50_Inches)

46 ANSI_expand_A_(8.50_x_11.00_Inches)

47 ANSI_A_(11.00_x_8.50_Inches)

48 ANSI_A_(8.50_x_11.00_Inches)

Enter number of media to select: 35

Selected: ANSI_D_(34.00_x_22.00_Inches)

Effective plotting area:  15.29 wide by 20.60 high

Effective plotting area:  13.29 wide by 17.31 high

Plotting viewport 2.

Plotting viewport 1.

Regenerating layout.

Regenerating model.

Effective plotting area:  15.69 wide by 20.60 high

Effective plotting area:  15.69 wide by 20.59 high

Plotting viewport 2.

Plotting viewport 1.

Regenerating layout.

Regenerating model.

Effective plotting area:  15.69 wide by 20.60 high

Effective plotting area:  15.69 wide by 20.59 high

Plotting viewport 2.

Plotting viewport 1.

Regenerating layout.

Regenerating model.

Effective plotting area:  15.69 wide by 20.60 high

Effective plotting area:  14.07 wide by 18.34 high

Plotting viewport 2.

Plotting viewport 1.

Regenerating layout.

Regenerating model.

25 responses to “Allowing selection of an AutoCAD plot device and media name using .NET”

  1. Definitely helps, but why am i getting single page dwfs? the layout loop i am doing is the same as yours.

    I can get a dsd publish to do multiple page dwfs, though.

    Overall, your site and the .net discussion group has helped a lot, i would say i have learned 40 to 60 % of the api from them.

  2. As I mentioned in the original multi-sheet post, I believe the DWF6 driver is not actually multi-sheet. Which is why I chose the DWFx driver to demonstrate the technique.

    The Publish API may be the way to go, if you need to create multi-page DWF6 files (I haven't looked into it myself, as yet).

    Kean

  3. How does one get the plotter name.
    Your example gives the Device name (.pc3)
    I was looking for something like the page setup manager gives.
    eg.
    Device name: HP4500.PC3
    Plotter: HP Desginjet 4500

  4. Kean Walmsley Avatar

    You should be able to get this via the PlotConfig's Comment property. The device would need to be loaded first, from what I can tell, but then the PlotConfigManager should provide access via the CurrentConfig.

    Good luck,

    Kean

  5. Thanks Kean,

    Unfortunately if the device is not avaliable it takes quite a few seconds to load the info.

    AutoCAD’s page setup manager does not appear to have to load the device in order to get the info.

  6. Kean Walmsley Avatar

    I suspect AutoCAD just does it at a different time. I don't know of a magic way to get around this delay, I'm afraid.

    Kean

  7. Hi Kean,

    Reactivating this topic.. Hope you read it, and maybe can help me.

    I'm working on a App to plot in PLT, PDF or DWF. The choice is made by user selection (Windows Form + Radio Button).

    I'm having problem with the MediaName.
    Although I've manually included the medias manually in the .PC3 file (for the three devices), things still don't work..
    For PLT (using HP-750C), thats OK, but I had to use your piece of code to list medianames, because the name I've created is not the same. I've created someting like: A0, A1, A0L, etc... But in medianame listing it apears like: UserDefinedMetric (900.00 x 2500.00MM), UserDefinedMetric (900.00 x 2000.00MM), etc...

    For DWF, no matter the medianame, it gives me an "eInvalidInput", and breaks...

    For PDF, although the custom sizes i've created, even in medianame listing, it just don't appear...

    If I set the BACKGROUNDPLOT=0, it doesn't plot... If set to 2, then it takes long, but generates the files...

    Hope you can help me...

    Thank you very much!

    Felipe,
    SP-Brazil

  8. Hi Felipe,

    The kind of troubleshooting you need is beyond what I can provide, I'm afraid. The ADN team will be able to help, if you're a member, otherwise I suggest trying the the discussion groups.

    Regards,

    Kean

  9. Thanks Kean,

    An workaround that I choose using is plotting via `doc.SendStringToExecute(command "._plot" "Y" ... ... )`

    The only issue I've found was that both PDF and DWF are "auto-plot-to-file", but not the PLT via HP750C.pc3. So I've set a global variable "bool autoplottofile", so that depending of the device i'm using, the command will have an "parameter" diference.

    But no problems with delay, medianames, etc..

    Hope this helps..

    Thanks!

  10. Kean,
    Is there a way to tell if the device the user picks requires you to print to file? The pe.BeginDocument function throws an exception if you choose a file device like a PDF, and you don't give it a filename. I could catch the error at that point and prompt for a file name from the user, but I was hoping there was a way to tell before that point.

  11. Chris,

    Please submit your question to the ADN team, if you're a member, or otherwise the AutoCAD .NET Discussion Group.

    Regards,

    Kean

  12. Kean,
    I've tried to add some code for adding a new custom paper size with no succes. Is this really so dificult to do this ?

  13. Algoedt,

    I haven't tried this myself, and it's unfortunately beyond the scope of this particular post (as you're aware).

    I suggest posting your question to the ADN team, if you're a member, or otherwise the AutoCAD .NET Discussion Group.

    Regards,

    Kean

  14. I have the same Algoedt's problem. I would like to create a custom paper size befoure printing. I try to wite to the Adn team but unfortunately no answer yet. Does anyone have any news about it? Or same ideas?

  15. I need this one too,how to add a new custom paper size and set the printing margin?

  16. Hi kean,

    Firstly, thanks for your help and sharing your insight into this.
    now to my question, would you happen to know why the media list does not display custom paper names that are present inside a printer's setting?
    The media list contains for example:
    11 User122
    12 User121
    13 User120
    14 User119
    15 User82
    16 User70

    however, these are all paper names that are being renamed. Other default paper sizes are named just fine.
    Any suggestion would be immensely welcomed 🙂

    1. Try to use.GetLocaleMediaName.

      public string GetLocaleMediaName(
      PlotSettings plotSet,
      string canonicalName
      );

  17. Hi Hassan,

    Sorry - I don't know why this is the case. I suggest posting your question via ADN or the AutoCAD .NET Discussion Group.

    Regards,

    Kean

  18. Kean, please tell how set orientation of layout to plot.

  19. Andre,

    It's been a while (wow, 5 years!) since I looked at this post, but off the top of my head I would say that decision is based on the media chosen (look at options 17 and 18 for the two orientations for A4, for instance).

    If that's not what you're looking for, please post your question via ADN or the AutoCAD .NET Discussion Group.

    Regards,

    Kean

  20. Hello Kean, I now is a very old post.
    If you can not help me, I will use the discussion group, but when a choose a real plotting device it only creats the file, this sample just work for plotting to files?

  21. Hello Gdiael,

    As it stands, yes, but there's a flag in BeginDocument() that specifies whether it should be to a file or not (at least that's the comment in the code).

    Regards,

    Kean

  22. Thank you very much, you save me one more time!

  23. Great stuff Kean. I inherited a program that generates a drawing and it happens to be blowing up at this very point: acPlSetVdr.SetPlotConfigurationName(acPlSet, "DWG To PDF.pc3", "UserDefinedImperial (11.00 x 8.50Inches)"); I did not see anything like "UserDefinedImperial (11.00 x 8.50Inches)" in the media type section of your discussion--have you seen anything like this done before?

    1. No, I haven't. I suggest setting a breakpoint and seeing what page sizes you have. Otherwise you should post to the AutoCAD .NET forum - someone there should be able to help.

      Kean

Leave a Reply to Chris Cancel reply

Your email address will not be published. Required fields are marked *