In this previous post, we looked at some code to do a programmatic snapshot of AutoCAD's modelspace, saving the results to an image file.
From the discussion that followed, I realised that the code had an undesired (and unnecessary) side-effect of creating a new 3D GS View and leaving the modelspace with that view active. GS Views in AutoCAD 2007 have grey backgrounds by default, and so this change can be quite disturbing for users. The only reason we created the GS View in the first place (if one didn't already exist), was to use it to query the view position/target/up vector/field width and height and apply it to our new view. Thankfully it seems this can also be determined directly from the viewport.
So rather than calling GetGSView() and using the returned view to get that information, we now simply call SetViewFromViewport() specifying the viewport number held in CVPORT, and the graphics system manager for that document handles the rest.
Here's the updated C# code, which appears to achieve the same goals without the side-effect. Check line 124 for the new code, a few extraneous lines around it having been removed:
1 using Autodesk.AutoCAD.ApplicationServices;
2 using Autodesk.AutoCAD.DatabaseServices;
3 using Autodesk.AutoCAD.EditorInput;
4 using Autodesk.AutoCAD.GraphicsInterface;
5 using Autodesk.AutoCAD.GraphicsSystem;
6 using Autodesk.AutoCAD.Runtime;
7 using Autodesk.AutoCAD.Interop;
8 using System.Drawing;
9
10 namespace OffscreenImageCreation
11 {
12 public class Commands
13 {
14 [CommandMethod("OSS")]
15 static public void OffscreenSnapshot()
16 {
17 CreateSphere();
18 SnapshotToFile(
19 "c:\\sphere-Wireframe2D.png",
20 VisualStyleType.Wireframe2D
21 );
22 SnapshotToFile(
23 "c:\\sphere-Hidden.png",
24 VisualStyleType.Hidden
25 );
26 SnapshotToFile(
27 "c:\\sphere-Basic.png",
28 VisualStyleType.Basic
29 );
30 SnapshotToFile(
31 "c:\\sphere-ColorChange.png",
32 VisualStyleType.ColorChange
33 );
34 SnapshotToFile(
35 "c:\\sphere-Conceptual.png",
36 VisualStyleType.Conceptual
37 );
38 SnapshotToFile(
39 "c:\\sphere-Flat.png",
40 VisualStyleType.Flat
41 );
42 SnapshotToFile(
43 "c:\\sphere-Gouraud.png",
44 VisualStyleType.Gouraud
45 );
46 SnapshotToFile(
47 "c:\\sphere-Realistic.png",
48 VisualStyleType.Realistic
49 );
50 }
51
52 static public void CreateSphere()
53 {
54 Document doc =
55 Application.DocumentManager.MdiActiveDocument;
56 Database db = doc.Database;
57 Editor ed = doc.Editor;
58
59 Transaction tr =
60 doc.TransactionManager.StartTransaction();
61 using (tr)
62 {
63 BlockTable bt =
64 (BlockTable)tr.GetObject(
65 db.BlockTableId,
66 OpenMode.ForRead
67 );
68 BlockTableRecord btr =
69 (BlockTableRecord)tr.GetObject(
70 bt[BlockTableRecord.ModelSpace],
71 OpenMode.ForWrite
72 );
73 Solid3d sol = new Solid3d();
74 sol.CreateSphere(10.0);
75
76 const string matname =
77 "Sitework.Paving - Surfacing.Riverstone.Mortared";
78 DBDictionary matdict =
79 (DBDictionary)tr.GetObject(
80 db.MaterialDictionaryId,
81 OpenMode.ForRead
82 );
83 if (matdict.Contains(matname))
84 {
85 sol.Material = matname;
86 }
87 else
88 {
89 ed.WriteMessage(
90 "\nMaterial (" + matname + ") not found" +
91 " - sphere will be rendered without it.",
92 matname
93 );
94 }
95 btr.AppendEntity(sol);
96
97 tr.AddNewlyCreatedDBObject(sol, true);
98 tr.Commit();
99 }
100 AcadApplication acadApp =
101 (AcadApplication)Application.AcadApplication;
102 acadApp.ZoomExtents();
103 }
104
105 static public void SnapshotToFile(
106 string filename,
107 VisualStyleType vst
108 )
109 {
110 Document doc =
111 Application.DocumentManager.MdiActiveDocument;
112 Editor ed = doc.Editor;
113 Database db = doc.Database;
114 Manager gsm = doc.GraphicsManager;
115
116 // Get some AutoCAD system variables
117 int vpn =
118 System.Convert.ToInt32(
119 Application.GetSystemVariable("CVPORT")
120 );
121
122 using (View view = new View())
123 {
124 gsm.SetViewFromViewport(view, vpn);
125
126 // Set the visual style to the one passed in
127 view.VisualStyle = new VisualStyle(vst);
128
129 Device dev =
130 gsm.CreateAutoCADOffScreenDevice();
131 using (dev)
132 {
133 dev.OnSize(gsm.DisplaySize);
134
135 // Set the render type and the background color
136 dev.DeviceRenderType = RendererType.Default;
137 dev.BackgroundColor = Color.White;
138
139 // Add the view to the device and update it
140 dev.Add(view);
141 dev.Update();
142
143 using (Model model = gsm.CreateAutoCADModel())
144 {
145 Transaction tr =
146 db.TransactionManager.StartTransaction();
147 using (tr)
148 {
149 // Add the modelspace to the view
150 // It's a container but also a drawable
151 BlockTable bt =
152 (BlockTable)tr.GetObject(
153 db.BlockTableId,
154 OpenMode.ForRead
155 );
156 BlockTableRecord btr =
157 (BlockTableRecord)tr.GetObject(
158 bt[BlockTableRecord.ModelSpace],
159 OpenMode.ForRead
160 );
161 view.Add(btr, model);
162 tr.Commit();
163 }
164 // Take the snapshot
165 Rectangle rect = view.Viewport;
166 using (Bitmap bitmap = view.GetSnapshot(rect))
167 {
168 bitmap.Save(filename);
169 ed.WriteMessage(
170 "\nSnapshot image saved to: " +
171 filename
172 );
173 // Clean up
174 view.EraseAll();
175 dev.Erase(view);
176 }
177 }
178 }
179 }
180 }
181 }
182 }
You can also download the .cs file from here.