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.

Subscribe via RSS
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.
Posted by: Jason | October 09, 2007 at 08:43 PM
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
Posted by: Kean | October 09, 2007 at 10:32 PM
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
Posted by: Jordan | July 08, 2008 at 05:00 AM
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
Posted by: Kean | July 08, 2008 at 09:15 AM
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.
Posted by: Jordan | July 09, 2008 at 03:31 AM
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
Posted by: Kean | July 09, 2008 at 08:35 AM
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
Posted by: Felipe | April 14, 2009 at 03:50 PM
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
Posted by: Kean Walmsley | April 14, 2009 at 05:37 PM
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!
Posted by: Felipe | April 15, 2009 at 02:28 AM