.NET

.NET

Reply
Valued Contributor
KevinMacDonald
Posts: 85
Registered: ‎12-15-2012
Message 1 of 9 (1,362 Views)
Accepted Solution

Redrawing the screen during execution of a Command Method

1362 Views, 8 Replies
12-19-2012 01:22 PM

I would like to be able to have the screen refresh periodically to show the new objects I have added as a command method proceeds to execute. I am hoping to be able to achieve a kind of simple animation by doing this, and also to show progress while a computationally intensive operation is under way. Is there a way that I can do this? 

 

I have tried using AcadApp.DocumentManager.MdiActiveDocument..Editor.Regen() and also .Editor.UpdateScreen(), but it only seems to work once and not multiple times. Do I have to commit the transaction and then .Regen()? 

 

Thanks!

Inventor 2013

You can post some code snippets showing more precisely what it is you've tried that isn't working.

 

You need to use the TransactionManager of the Document object, not the TransactionManager of the Database, and you need to commit the transaction in order for AutoCAD to update changes to the display, in addition to calling EnableGraphicsFlush() and QueueForGraphicsFlush()

 

If you're using Transient graphics, you can try one of Kean's hacks that is supposed to force AutoCAD to process any pending window messages (I haven't tried this so I can't vouch for it):

 


// Using System.Windows.Forms; // Using System.Drawing; Point p = Cursor.Position; Cursor.Position = new Point(p.X, p.Y);

 

Another thing yhou can try is calling the undocumented Autodesk.AutoCAD.Internal.Utils.FlushGraphics() method.

 

If you're modifying objects in the database, you will need to commit the transaction in which the changes were made to those objects You can use nested transactions to periodically update graphics without making the individual changes in each nested transaction undoable.

 

 

*Expert Elite*
_gile
Posts: 2,133
Registered: ‎04-29-2006
Message 2 of 9 (1,346 Views)

Re : Redrawing the screen during execution of a Command Method

12-19-2012 10:13 PM in reply to: KevinMacDonald

Hi,

 

Look at the TransactionManager.QueueForGraphicsFlush() method.

.

Gilles Chanteau
Valued Contributor
KevinMacDonald
Posts: 85
Registered: ‎12-15-2012
Message 3 of 9 (1,333 Views)

Re : Redrawing the screen during execution of a Command Method

12-20-2012 07:59 AM in reply to: _gile

I tried calling TransactionManager.Database.QueueForGraphicsFlush(), and also tried calling Editor.Regen() immediately after it, but when I run my command the screen only ever redraws after the entire command is complete. So, the visual effect for a command that takes several seconds and is drawing a lot to the screen is that there is a pause of several seconds, followed by everything showing up at once.

 

Is there perhaps some other command to tell the system to process events? Transients seem to do this. But I don't really want to draw transients. I just want actual entities to appear as a command progresses.

 

Thanks!

Inventor 2013
Valued Contributor
KevinMacDonald
Posts: 85
Registered: ‎12-15-2012
Message 4 of 9 (1,329 Views)

Re : Redrawing the screen during execution of a Command Method

12-20-2012 09:23 AM in reply to: KevinMacDonald

What I even notice with the Transient object is that if the command is busy doing something, even calling TransientManager.CurrentTransientManager.UpdateTransient() does not update the screen until after the command function has exited. There seems to be no way to force the current view to update while a command is executing. What this seems to imply is that if I want to truly show the progress of something being drawn I need spin up a transient, allow the command to exit, and then draw everything using the Transient object. That seems like a lot of extra work, because really I just want to commit real objects to the database and refresh the screen as I go. 

 

Any idea are appreciated! 

Inventor 2013
*Expert Elite*
_gile
Posts: 2,133
Registered: ‎04-29-2006
Message 5 of 9 (1,319 Views)

Re : Redrawing the screen during execution of a Command Method

12-20-2012 12:33 PM in reply to: KevinMacDonald

Perhaps I misunderstand what you want to do but this is working for me:

 

        [CommandMethod("Test")]
        public void Test()
        {
            Document doc = AcAp.DocumentManager.MdiActiveDocument;
            Database db = doc.Database;
            Editor ed = doc.Editor;
            PromptResult pr = ed.GetString("\nEnter a string: ");
            if (pr.Status != PromptStatus.OK)
                return;
            string str = pr.StringResult;
            Matrix3d ucs = ed.CurrentUserCoordinateSystem;
            PromptPointOptions options = new PromptPointOptions("\nInsertion point: ");
            options.AllowNone = true;
            PromptPointResult ppr;
            using (Transaction tr = db.TransactionManager.StartTransaction())
            {
                BlockTableRecord space =
                    (BlockTableRecord)tr.GetObject(db.CurrentSpaceId, OpenMode.ForWrite);
                while (true)
                {
                    ppr = ed.GetPoint(options);
                    if (ppr.Status != PromptStatus.OK)
                        break;
                    DBText text = new DBText();
                    text.TextString = str;
                    text.Position = ppr.Value.TransformBy(ucs);
                    space.AppendEntity(text);
                    tr.AddNewlyCreatedDBObject(text, true);
                    db.TransactionManager.QueueForGraphicsFlush();
                }
                tr.Commit();
            }
        }

 

Gilles Chanteau
Valued Contributor
KevinMacDonald
Posts: 85
Registered: ‎12-15-2012
Message 6 of 9 (1,315 Views)

Re : Redrawing the screen during execution of a Command Method

12-20-2012 12:45 PM in reply to: _gile

Yes I understand. I believe that works for you because in each pass through your loop you pause for user input. Pausing for user input returns control to Autocad so the user can specify the next point. At that moment it is possible for Autocad to refresh the screen. But imagine if you were not pausing for user input, but were instead computing the next point via some mathematical procedure. What you would see is that all your lines appear at once. This doesn't happen simply because the lines are being drawn really fast; it happens because Autocad does not have the opportunity to redraw the screen. So, let's say you were drawing 100 lines in your command and the procedure was complex enough that it took 1/10 of a second to figure out the end points of each line. You would observe that Autocad freezes for about 10 seconds and then all 100 lines would appear at once instead of sequentially.

 

The only method I've seen for truly drawing things dynamically is using Transients as shown here. Perhaps that's the only way to do it.  In this method control does return to Autocad (the command method exits), but the Transient continues to run in the background by means of Windows Messages being fired.  

Inventor 2013
Valued Mentor
DiningPhilosopher
Posts: 370
Registered: ‎05-06-2012
Message 7 of 9 (1,291 Views)

Re : Redrawing the screen during execution of a Command Method

12-22-2012 02:24 AM in reply to: _gile

Hi Gile.

 

The reason your code works is because it acquires user input in the loop, which causes AutoCAD to update the display.

 

In fact, there is an undocumented method in Autodesk.AutoCAD.Internal.Utils that seems to be precisely for that purpose, called FlushGraphics(), and all it does is call acutPrompt().

Valued Mentor
DiningPhilosopher
Posts: 370
Registered: ‎05-06-2012
Message 8 of 9 (1,289 Views)

Re : Redrawing the screen during execution of a Command Method

12-22-2012 02:40 AM in reply to: KevinMacDonald

You can post some code snippets showing more precisely what it is you've tried that isn't working.

 

You need to use the TransactionManager of the Document object, not the TransactionManager of the Database, and you need to commit the transaction in order for AutoCAD to update changes to the display, in addition to calling EnableGraphicsFlush() and QueueForGraphicsFlush()

 

If you're using Transient graphics, you can try one of Kean's hacks that is supposed to force AutoCAD to process any pending window messages (I haven't tried this so I can't vouch for it):

 


// Using System.Windows.Forms; // Using System.Drawing; Point p = Cursor.Position; Cursor.Position = new Point(p.X, p.Y);

 

Another thing yhou can try is calling the undocumented Autodesk.AutoCAD.Internal.Utils.FlushGraphics() method.

 

If you're modifying objects in the database, you will need to commit the transaction in which the changes were made to those objects You can use nested transactions to periodically update graphics without making the individual changes in each nested transaction undoable.

 

 

Valued Contributor
KevinMacDonald
Posts: 85
Registered: ‎12-15-2012
Message 9 of 9 (1,265 Views)

Re : Redrawing the screen during execution of a Command Method

12-24-2012 11:01 PM in reply to: DiningPhilosopher

Thank you! That worked. The final answer was, I had to do everything suggested above. I committed the transaction periodically, and upon the commit my C# code looks like

 

_document.TransactionManager.EnableGraphicsFlush(true);
_document.TransactionManager.QueueForGraphicsFlush();
Autodesk.AutoCAD.Internal.Utils.FlushGraphics();
_transaction.Commit();
_transaction.Dispose();

 

where _document and _transaction are just the usual Autocad objects I assigned to member variables of a utility class.

Inventor 2013
Post to the Community

Have questions about Autodesk products? Ask the community.

New Post
Announcements
Do you have 60 seconds to spare? The Autodesk Community Team is revamping our site ranking system and we want your feedback! Please click here to launch the 5 question survey. As always your input is greatly appreciated.