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: