Update AutoCAD Display

Update AutoCAD Display

SENL1362
Advisor Advisor
4,000 Views
8 Replies
Message 1 of 9

Update AutoCAD Display

SENL1362
Advisor
Advisor

I cannot get the AutoCAD display to get updated during the execution of a command.

There are two cases for which i like the display to get updated:

1. When changing the current layer, the  ribbon must show the new current while the command is executed.

    See the sample below. The command may be called from Palette or WPF controll.

2. After changing the Document Display Size but before taking a snapshot.

 

I've tried different update calls, document and session context, windows messages etc. but the display always gets updated after the command is finished.

I've found one sollution and that's issue an other command using SendStringToExecute but this result in an other issue,  synchronisation.

 

The update problem occurs in all versions of AutoCAD up to 2017.

 

Any other suggestions or is this simply not possible.

Thanks in advance for any help.

 

using System;
using System.Threading;
using System.Reflection;
using System.Drawing;
using System.Windows.Forms;
using frmApp = System.Windows.Forms.Application;

using Autodesk.AutoCAD.Runtime;
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;

using AcadApp = Autodesk.AutoCAD.ApplicationServices.Application;

[assembly: CommandClass(typeof(TestAcadUpdate.Class1))]

namespace TestAcadUpdate
{
    public class Class1
    {

        /// <summary>
        /// Update Ribbon to display the new Current Layer BEFORE the end of this command,
        ///   without a user interaction (ed.GetXXX),
        ///   and (if possible) without Session mode
        /// </summary>
        [CommandMethod("TestUCLD", CommandFlags.Session )]
        public static void UpdateCurrentLayerDisplay()
        {
            Document doc = null;
            Editor ed = null;
            Database db = null;

            try
            {
                doc = AcadApp.DocumentManager.MdiActiveDocument;
                ed = doc.Editor;
                db = doc.Database;

                //LockDocument because of Session Mode
                var docLck = default(DocumentLock);
                using (docLck = doc.LockDocument())
                {
                    var tr = default(Transaction);
                    using (tr = db.TransactionManager.StartTransaction())
                    {
                        //Change CurrentLayer to "0"
                        db.Clayer = db.LayerZero;

                        //var lt = (LayerTable)tr.GetObject(db.LayerTableId, OpenMode.ForRead);
                        var layer0 = (LayerTableRecord)tr.GetObject(db.LayerZero, OpenMode.ForWrite);
                        //Force a graphics update
                        layer0.IsOff = layer0.IsOff;
                        ed.ApplyCurDwgLayerTableChanges();

                        tr.Commit();
                    }
                    doc.TransactionManager.EnableGraphicsFlush(true);
                    doc.TransactionManager.QueueForGraphicsFlush();
                }
                //I'll like the Ribbon to display the new CurrentLayer NOW
                ed.UpdateScreen();
                ed.Regen();
                AcadApp.UpdateScreen();
                Autodesk.AutoCAD.Internal.Utils.FlushGraphics();

                //This doesn't work either, and is not what i'll want 
                //string esc = null;
                //esc += '\x03';
                //doc.SendStringToExecute(esc, true, false, false);
                //PromptPointResult ppr = ed.GetPoint("\n Give me a Point: ");
                //if (ppr.Status != PromptStatus.OK)
                //    return;

                var cp = Cursor.Position;
                Cursor.Position = new Point(cp.X, cp.Y);
                frmApp.DoEvents();

                //Simulate other drawing and calculation activities
                for (int i = 0; i < 10; i++)
                    Thread.Sleep(1000);
            }
            catch (System.Exception ex)
            {
                if (ed != null)
                    ed.WriteMessage("\n Error {0}: {1} " , MethodBase.GetCurrentMethod().Name, ex.Message);
                else
                    MessageBox.Show(ex.Message, MethodBase.GetCurrentMethod().Name, MessageBoxButtons.OK);
            }
        }
    }
}

 

0 Likes
Accepted solutions (1)
4,001 Views
8 Replies
Replies (8)
Message 2 of 9

SENL1362
Advisor
Advisor

This is a the other sample: Create a Preview of an altered Document Window

Attached you'll find screenshots of a sample drawing, wrong bitmap, required bitmap as well as the code used to generate the bitmaps.

 

using System;
using System.IO;
using System.Threading;
using System.Reflection;
using System.Drawing;
using System.Drawing.Imaging;
using System.Windows.Forms;
using frmApp = System.Windows.Forms.Application;

using Autodesk.AutoCAD.Runtime;
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;

using AcadApp = Autodesk.AutoCAD.ApplicationServices.Application;


[assembly: CommandClass(typeof(TestAcadUpdate.Class1))]

namespace TestAcadUpdate
{
    public class Class1
    {

        /// <summary>
        /// 1. Change Size of Drawing Window
        /// 2. Create Preview (bmp)
        /// </summary>
        [CommandMethod("TestUDW", CommandFlags.Session)]
        public static void UpdateDocumentWindow()
        {
            Document doc = null;
            Editor ed = null;
            Database db = null;

            string bmPathname = null;
            try
            {
                doc = AcadApp.DocumentManager.MdiActiveDocument;
                ed = doc.Editor;
                db = doc.Database;

                bmPathname = System.IO.Path.Combine(System.IO.Path.GetDirectoryName(doc.Name), System.IO.Path.GetFileNameWithoutExtension(doc.Name) + ".bmp");
                if (!doc.IsNamedDrawing)
                    bmPathname = System.IO.Path.Combine(Path.GetTempPath(), System.IO.Path.GetFileNameWithoutExtension(doc.Name) + ".bmp");


                //Resize Document Window which changes the NrOfPixels off the Bitmap.
                var wSize = new double[] { 400, 400 };
                doc.Window.WindowState = Autodesk.AutoCAD.Windows.Window.State.Normal;

                System.Windows.Size szDoc = new System.Windows.Size(wSize[0], wSize[1]);
                var appWinSize = AcadApp.MainWindow.DeviceIndependentSize;
                System.Windows.Point ptDoc = new System.Windows.Point(0.5 * (appWinSize.Width - szDoc.Width), 0.5 * (appWinSize.Height - szDoc.Height));

                //AutoCAD recalculates the View, but the update is postponed until the end of the command.
                doc.Window.DeviceIndependentLocation = ptDoc;
                doc.Window.DeviceIndependentSize = szDoc;

                doc.Window.WindowState = Autodesk.AutoCAD.Windows.Window.State.Normal;

                dynamic acadApp = AcadApp.AcadApplication;
                acadApp.ZoomExtents();


                //LockDocument because of Session Mode
                var docLck = default(DocumentLock);
                using (docLck = doc.LockDocument())
                {
                    var tr = default(Transaction);
                    using (tr = db.TransactionManager.StartTransaction())
                    {
                        if (!db.TileMode)
                            db.TileMode = true;

                        AcadApp.SetSystemVariable("LWDISPLAY", 1);
                        AcadApp.SetSystemVariable("UCSICON", 0);

                        var bgCol = System.Drawing.Color.White;
                        var fgCol = System.Drawing.Color.Black;
                        var acadPref = (dynamic)AcadApp.Preferences;
                        acadPref.Display.GraphicsWinModelBackgrndColor = bgCol;

                        ed.UpdateTiledViewportsInDatabase();

                        var size = doc.Window.DeviceIndependentSize;
                        using (var bmp = doc.CapturePreviewImage(Convert.ToUInt32(size.Width), Convert.ToUInt32(size.Height)))
                        {
                            var bwBmp = ConvertToBlackWhite(bmp, bgCol, fgCol);

                            if (File.Exists(bmPathname))
                                File.Delete(bmPathname);
                            bwBmp.Save(bmPathname, ImageFormat.Bmp);
                        }
                        tr.Commit();
                    }
                }
             }
            catch (System.Exception ex)
            {
                if (ed != null)
                    ed.WriteMessage("\n Error {0}: {1} ", MethodBase.GetCurrentMethod().Name, ex.Message);
                else
                    MessageBox.Show(ex.Message, MethodBase.GetCurrentMethod().Name, MessageBoxButtons.OK);
            }
        }


        //Developed by: Kean Walmsley: http://through-the-interface.typepad.com/through_the_interface/2009/11/novembers-plugin-of-the-month-screenshot.html
        public static Bitmap ConvertToBlackWhite(Bitmap src, System.Drawing.Color bgcol, System.Drawing.Color fgcol)
        {
            Bitmap bmp = new Bitmap(src.Width, src.Height);
            for (int y = 0; y < bmp.Height; y++)
            {
                for (int x = 0; x < bmp.Width; x++)
                {
                    System.Drawing.Color c = src.GetPixel(x, y);
                    if (!SameColors(c, bgcol))
                        c = fgcol;
                    bmp.SetPixel(x, y, c);
                }
            }
            return bmp;
        }

        //Developed by: Kean Walmsley: http://through-the-interface.typepad.com/through_the_interface/2009/11/novembers-plugin-of-the-month-screenshot.html
        private static bool SameColors(System.Drawing.Color a, System.Drawing.Color b)
        {
            // Ignore Alpha channel, just compare RGB
            return (a.R == b.R && a.G == b.G && a.B == b.B);
        }

 }
}

 

0 Likes
Message 3 of 9

Virupaksha_aithal
Autodesk Support
Autodesk Support

Hi,

 

does the blog http://through-the-interface.typepad.com/through_the_interface/2016/01/locking-and-unlocking-autocad... helps? Make sure you call ApplyCurDwgLayerTableChanges after committing the Transaction.



Virupaksha Aithal KM
Developer Technical Services
Autodesk Developer Network

0 Likes
Message 4 of 9

SENL1362
Advisor
Advisor

Hello Virupaksha,

Thanks for the reply but this does not solve this issue.

The screen (and Ribbon Layer state) gets only updated after the command has finished.

 

Below the updated code(ed.Apply... after the Commit), simmilar like suggested by Kean.

 

Any other suggestions?

 

 

                //LockDocument because of Session Mode
                var docLck = default(DocumentLock);
                using (docLck = doc.LockDocument())
                {
                    var tr = default(Transaction);
                    using (tr = db.TransactionManager.StartTransaction())
                    {
                        //Change CurrentLayer to "0"
                        db.Clayer = db.LayerZero;

                        //var lt = (LayerTable)tr.GetObject(db.LayerTableId, OpenMode.ForRead);
                        var layer0 = (LayerTableRecord)tr.GetObject(db.LayerZero, OpenMode.ForWrite);
                        //Force a graphics update
                        layer0.IsLocked = true;
                        layer0.IsLocked = false;
                        layer0.IsOff = layer0.IsOff;

                        tr.Commit();
                    }
                    //I'll like the Ribbon to display the new CurrentLayer NOW
                    ed.ApplyCurDwgLayerTableChanges();
                    ed.Regen();
0 Likes
Message 5 of 9

Virupaksha_aithal
Autodesk Support
Autodesk Support

Hi,

 

Looks like there is no API at present to update the ribbon during command execution



Virupaksha Aithal KM
Developer Technical Services
Autodesk Developer Network

0 Likes
Message 6 of 9

SENL1362
Advisor
Advisor
Hello Virupaksha,
Thank you for youre response.
What about the second sample, TestUDW, where an update of the Drawing Window is required.
0 Likes
Message 7 of 9

Virupaksha_aithal
Autodesk Support
Autodesk Support
Accepted solution

Hi,

 

Looks like AutoCAD is not updating the size internally till the command end. so you may need to think of splitting your logic to two commands. one to set the size and other command to create image like

 

 [CommandMethod("TestUDW", CommandFlags.Session)]
        public static void UpdateDocumentWindow()
        {
            Document doc = AcadApp.DocumentManager.MdiActiveDocument;
            Editor ed = doc.Editor;
            try
            {

                dynamic doc1 = doc.GetAcadDocument();
                doc1.Width = 400;
                doc1.Height = 400;

                doc.SendStringToExecute("capImage ", true, false, true);
            }
            catch (System.Exception ex)
            {
                if (ed != null)
                    ed.WriteMessage("\n Error {0}: {1} ", MethodBase.GetCurrentMethod().Name, ex.Message);
                else
                    MessageBox.Show(ex.Message, MethodBase.GetCurrentMethod().Name, MessageBoxButtons.OK);
            }
        }

        [CommandMethod("capImage")]
        public static void capImage()
        {
            dynamic acadApp = AcadApp.AcadApplication;
            acadApp.ZoomExtents();
         
            Document doc = AcadApp.DocumentManager.MdiActiveDocument;

            var bgCol = System.Drawing.Color.White;
            var fgCol = System.Drawing.Color.Black;
            var size = doc.Window.DeviceIndependentSize;

            string bmPathname = null;
            bmPathname = System.IO.Path.Combine(System.IO.Path.GetDirectoryName(doc.Name), System.IO.Path.GetFileNameWithoutExtension(doc.Name) + ".bmp");
            if (!doc.IsNamedDrawing)
                bmPathname = System.IO.Path.Combine(Path.GetTempPath(), System.IO.Path.GetFileNameWithoutExtension(doc.Name) + ".bmp");

            using (var bmp = doc.CapturePreviewImage(Convert.ToUInt32(size.Width), Convert.ToUInt32(size.Height)))
            {
             
                if (File.Exists(bmPathname))
                    File.Delete(bmPathname);

                bmp.Save(bmPathname, ImageFormat.Bmp);
            }
        }


Virupaksha Aithal KM
Developer Technical Services
Autodesk Developer Network

0 Likes
Message 8 of 9

SENL1362
Advisor
Advisor
Thank you for youre attention and this solution.
0 Likes
Message 9 of 9

Medithaibet
Contributor
Contributor

After the test, a problem was discovered.
It turns out that this function only takes effect in the model space.

 

How can I use this command to operate within the layout? It won't read the contents within the layout to update the images. How should I modify it to make it effective for operating on the current space?

Think you!

0 Likes