Hi expert,
I'm working on ACM (ACA has the same issue). What I did is to call Autodesk.AutoCAD.GraphicsInterface.TransientManager.AddTransient to draw some transient graphics in model space, then if I switch to layout or set the TILEMODE to 0, I want to erase these graphics. what should I do?
Currently, I hook up the Application.SystemVariableChanging event to erase these graphics. If the visual style is "2D Wireframe", this method works fine. But if the visual style is NOT the "2D wireframe", for example it is the "Conceptual", the tranisent graphics can not be erased!
After some investigation, I found the Document.ViewChanged will be called before SystemVariableChaning if the visual style is NOT the "2D wireframe". In other words, the order of events is not the same if the visual style is different. And it seems I have to erase the transient graphics before the Document.ViewChanged event. But I don't know where can I do it.
Thanks,
Klein
// I create a very simple example to show the issue, please see the following code.
// Test steps:
// 1. New a drawing
// 2. use netload command to load this assembly.
// 4. input "GraphTest" command
// 5. Switch to the paper space and then switch back to the model space
//
// If the visual style is the "2D Wireframe", the transient graphics will be erased successfully
// But if the visual style is NOT the "2D Wireframe", the transient graphics cannot be erased.
------------------------------
using System;
using System.Collections.Generic;
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.Colors;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Geometry;
using Autodesk.AutoCAD.GraphicsInterface;
using Autodesk.AutoCAD.Runtime;
namespace TransientGraphics
{
public class Commands
{
// list used to hold the transient graphics
private static List<Drawable> m_drawables = new List<Drawable>();
[CommandMethod("GraphTest")]
public static void TransientGraphicsCmd()
{
// hook up event
Application.SystemVariableChanging += new Autodesk.AutoCAD.ApplicationServices.SystemVariableChangingEventHandler(Application_SystemVariableChanging);
// create the transient graphics and then add the transient
MyLineTransient transient = new MyLineTransient();
TransientManager.CurrentTransientManager.AddTransient(transient, TransientDrawingMode.DirectShortTerm, 128, new IntegerCollection());
// save it in the list
m_drawables.Add(transient);
}
// erase these transient graphics when switching to paper space???
static void Application_SystemVariableChanging(object sender, Autodesk.AutoCAD.ApplicationServices.SystemVariableChangingEventArgs e)
{
if (e.Name == /*MSG0*/"TILEMODE")
{
// If current tilemode is "1", the new tilemode is "0". At that situation, we need to clear transient graphics
short nValue = (short)Application.TryGetSystemVariable(/*MSG0*/"TILEMODE");
if (nValue == 1) // Check OLD value
{
ClearTransGraphics(m_drawables);
}
}
}
private static void ClearTransGraphics(List<Drawable> drawables)
{
foreach (Drawable d in drawables)
{
bool transientRemoved = TransientManager.CurrentTransientManager.EraseTransient(d, new IntegerCollection());
if (!transientRemoved)
{
System.Diagnostics.Debug.Assert(transientRemoved);
}
//d.Dispose();
}
drawables.Clear();
}
}
//////////////////////////////////////////////////////////////////////////
internal sealed class MyLineTransient : Transient
{
static readonly Vector3d UnitNormal = new Vector3d(0, 0, 1);
internal EntityColor Color = new EntityColor(255, 0, 0);
public MyLineTransient()
{}
protected override int SubSetAttributes(DrawableTraits traits)
{
return (int)DrawableAttributes.None;
}
protected override bool SubWorldDraw(WorldDraw wd)
{
wd.Geometry.PushPositionTransform(PositionBehavior.World, Point2d.Origin);
return false;
}
Point3dCollection PathPoints
{
get
{
// Test points
Point3dCollection points = new Point3dCollection();
Point3d first = new Point3d(0, 10, 0);
Point3d second = new Point3d(50, 10, 0);
Point3d third = new Point3d(50, 60, 0);
points.Add(first);
points.Add(second);
points.Add(third);
return points;
}
}
protected override void SubViewportDraw(ViewportDraw vd)
{
for (int i = 0; i < PathPoints.Count - 1; ++i)
{
Point3d startPoint = PathPoints[i];
Point3d endPoint = PathPoints[i + 1];
CreatePolyline(vd, startPoint, endPoint);
}
}
private void CreatePolyline(ViewportDraw vd, Point3d startPoint, Point3d endPoint)
{
Point3dCollection vertices = new Point3dCollection() { startPoint, endPoint };
EntityColor oldColor = vd.SubEntityTraits.TrueColor;
LineWeight oldLineWeight = vd.SubEntityTraits.LineWeight;
vd.SubEntityTraits.TrueColor = Color;
vd.SubEntityTraits.LineWeight = Autodesk.AutoCAD.DatabaseServices.LineWeight.LineWeight018;
vd.Geometry.Polyline(vertices, UnitNormal, IntPtr.Zero);
vd.SubEntityTraits.TrueColor = oldColor;
vd.SubEntityTraits.LineWeight = oldLineWeight;
}
}
}
Hi Klein,
Can you try using the "Editor.UpdateTiledViewportsFromDatabase()" from the layoutswitched event callback ?.
Here is the modified sample code :
<code>
// list used to hold the transient graphics
privatestaticList<Drawable> m_drawables = newList<Drawable>();
[CommandMethod("GraphTest")]
publicstaticvoid TransientGraphicsCmd()
{
// Set the visual style to "Realistic"
// Just to be sure I dont try all this with "2d Wireframe" 🙂
SetVisualStyle();
TransientGraphics.MyLineTransient transient = new TransientGraphics.MyLineTransient();
TransientManager.CurrentTransientManager.AddTransient(transient, TransientDrawingMode.DirectShortTerm, 128, newIntegerCollection());
LayoutManager.Current.LayoutSwitched += newLayoutEventHandler(Current_LayoutSwitched);
m_drawables.Add(transient);
}
staticvoid Current_LayoutSwitched(object sender, LayoutEventArgs e)
{
if(e.Name.Equals("Model"))
{
ClearTransGraphics(m_drawables);
Editor ed = Application.DocumentManager.MdiActiveDocument.Editor;
ed.UpdateTiledViewportsFromDatabase();
}
}
privatestaticvoid ClearTransGraphics(List<Drawable> drawables)
{
foreach (Drawable d in drawables)
{
bool transientRemoved = TransientManager.CurrentTransientManager.EraseTransient(d, newIntegerCollection());
if (!transientRemoved)
{
System.Diagnostics.Debug.Assert(transientRemoved);
}
}
drawables.Clear();
}
privatestaticvoid SetVisualStyle()
{
Editor ed = Application.DocumentManager.MdiActiveDocument.Editor;
Database db = HostApplicationServices.WorkingDatabase;
using(Transaction tr = db.TransactionManager.StartTransaction())
{
ViewportTable vt = (ViewportTable)tr.GetObject(db.ViewportTableId, OpenMode.ForRead);
ViewportTableRecord vtr = (ViewportTableRecord)tr.GetObject(vt["*Active"], OpenMode.ForWrite);
DBDictionary dict = (DBDictionary)tr.GetObject(db.VisualStyleDictionaryId, OpenMode.ForRead);
vtr.VisualStyleId = dict.GetAt("Realistic");
tr.Commit();
}
ed.UpdateTiledViewportsFromDatabase();
}
</code>
Hi Klein,
Just wanted to inform you that there is also a separate AutoCAD .Net API forum within the AutoCAD discussion groups. Since it was a .Net API related question, it fits in that more correctly.
Thanks so much for your reply, Balaji.
UpdateTiledViewportsFromDatabase() can update the view only when switching back to Model space again, so I can see a fliker (the transient graphics disappear).
Can't find what you're looking for? Ask the community or share your knowledge.