Tuesday, February 15, 2022

Using Transient Graphics to Prompt User on Screen

I have been quite busy these days that I have not post an article for quite a while. Today, as I often do, based on my interaction in a discussion thread in the .NET forum, I put together some code quickly as the result of the discussion. To save time to repeat the topic that was discussed, please refer the link to the discussion there to see what the code is about. I only post the code and a companion video clip that shows the code execution result.

First a class TransientPrompt:

using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.GraphicsInterface;
using Autodesk.AutoCAD.Geometry;
using System;
 
namespace TransintTextPrompt
{
    public class TransientPrompt : IDisposable
    {
        private readonly Document _dwg;
        private DBText _txtEntity = null;
        private string _promptText = "";
        private bool _enabled = false;
 
        private TransientManager tsManager = TransientManager.CurrentTransientManager;
 
        public TransientPrompt(Document dwgstring initialText)
        {
            _dwg = dwg;
            _promptText = initialText;
        }
 
        public void Enable(bool enable)
        {
            _enabled = enable;
            if (_enabled)
            {
                _dwg.ViewChanged += ViewChanged;
                if (_txtEntity != null) _txtEntity.Dispose();
                _txtEntity = new DBText();
                _txtEntity.SetDatabaseDefaults();
                _txtEntity.HorizontalMode = TextHorizontalMode.TextCenter;
                _txtEntity.VerticalMode = TextVerticalMode.TextVerticalMid;
                _txtEntity.TextString = _promptText;
                _txtEntity.ColorIndex = 1;
                CreateTransient();
            }
            else
            {
                _dwg.ViewChanged -= ViewChanged;
                ClearTransient();
                if (_txtEntity != null) _txtEntity.Dispose();
            }
        }
 
        public void SetPromptText(string prompt)
        {
            _promptText = prompt;
            if (_txtEntity!=null)
            {
                ClearTransient();
                CreateTransient();
            }
        }
        
        public void Dispose()
        {
            if (_txtEntity != null)
            {
                tsManager.EraseTransient(_txtEntity, new IntegerCollection());
                _txtEntity.Dispose();
            }
        }
 
        #region private methods
 
        private void ViewChanged(object sender, EventArgs e)
        {
            if (!_enabled) return;
            ClearTransient();
            CreateTransient();
        }
 
        private void DrawingTransient()
        {
            if (_txtEntity!=null)
            {
                tsManager.AddTransient(_txtEntity, TransientDrawingMode.DirectShortTerm, 128, new IntegerCollection());
            }
        }
        private void ClearTransient()
        {
            if (_txtEntity!=null)
            {
                tsManager.EraseTransient(_txtEntity, new IntegerCollection());
            }
        }
 
        private void GetViewSize(out double heightout double widthout Point3d center)
        {
            center = (Point3d)Application.GetSystemVariable("VIEWCTR");
            height = (double)Application.GetSystemVariable("VIEWSIZE");
            var screen = (Point2d)Application.GetSystemVariable("SCREENSIZE");
            width = screen.X / screen.Y * height;
        }
 
        private void GetTextLocation(out Point3d textPositionout double textHeight)
        {
            GetViewSize(out double viewHeightout double viewWidthout Point3d viewCenter);
            textPosition = new Point3d(viewCenter.X - (viewWidth / 2.0) * .70, viewCenter.Y + (viewHeight / 2.0) * .70, 0.0);
            textHeight = viewHeight / 10.0;
        }
 
        private void CreateTransient()
        {
            GetTextLocation(out Point3d posout double h);
            _txtEntity.Height = h;
            _txtEntity.Position = pos;
            _txtEntity.TextString = _promptText;
 
            DrawingTransient();
        }
 
        #endregion 
    }
}

Then the CommandClass/Method where the TransientPrompt class is used:

using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Runtime;
using CadApp = Autodesk.AutoCAD.ApplicationServices.Application;
 
[assembly: CommandClass(typeof(TransintTextPrompt.MyCommands))]
 
namespace TransintTextPrompt
{
    public class MyCommands 
    {
        [CommandMethod("TestTransient")]
        public static void RunCommand()
        {
            var dwg = CadApp.DocumentManager.MdiActiveDocument;
            var ed = dwg.Editor;
            int count = 0;
            using (var transient=new TransientPrompt(dwg, count.ToString()))
            {
                transient.Enable(true);
 
                while(true)
                {
                    var res = ed.GetEntity("\nSelect an ENTITY:");
                    if (res.Status== PromptStatus.OK)
                    {
                        count++;
                        transient.SetPromptText(count.ToString());
                    }
                    else
                    {
                        break;
                    }
                }
 
                transient.Enable(false);
            }
        }
    }
}

The code is fairly simple and self-descriptive. See the video clip showing the code execution effect:





1 comment:

Unknown said...


This is perfect Yuan... Congratulations once again.

Followers

About Me

My photo
After graduating from university, I worked as civil engineer for more than 10 years. It was AutoCAD use that led me to the path of computer programming. Although I now do more generic business software development, such as enterprise system, timesheet, billing, web services..., AutoCAD related programming is always interesting me and I still get AutoCAD programming tasks assigned to me from time to time. So, AutoCAD goes, I go.