Showing Current Selection in a Modeless Form
Showing Current Selection in a Modeless Form
There is a question post in the AutoCAD .NET discussion forum here. I happened to have a similar requirement in one of my recent development projects. So, instead of post a reply in the discussion forum there, I though it would be easier to post a relatively simple and run-able project for the benefit of all readers.
The project is fairly easy and is comprised of 3 classes.
Class CurrentSelectionWatcher:
using System;
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.EditorInput;
using CadApp = Autodesk.AutoCAD.ApplicationServices.Application;
namespace ShowSelectionChange
{
public class CurrentSelectionWatcher
{
private frmSelection _view = null;
private bool _show = false;
private Document _curDoc = null;
public CurrentSelectionWatcher()
{
_curDoc = CadApp.DocumentManager.MdiActiveDocument;
if (_curDoc != null)
{
SetView();
_curDoc.ImpliedSelectionChanged +=
Document_ImpliedSelectionChanged;
}
CadApp.DocumentManager.DocumentBecameCurrent +=
DocumentManager_DocumentBecameCurrent;
}
public bool IsShown
{
get { return _show; }
}
private void Document_ImpliedSelectionChanged(
object sender, EventArgs e)
{
SetView();
}
private void DocumentManager_DocumentBecameCurrent(
object sender, DocumentCollectionEventArgs e)
{
if (_curDoc!=null)
{
_curDoc.ImpliedSelectionChanged -=
Document_ImpliedSelectionChanged;
}
if (e.Document!=null)
{
if (e.Document != _curDoc)
{
ClearView();
SetView();
_curDoc = e.Document;
_curDoc.ImpliedSelectionChanged +=
Document_ImpliedSelectionChanged;
}
}
}
public void Show()
{
_view = new frmSelection();
_view.VisibleChanged += _view_VisibleChanged;
CadApp.ShowModelessDialog(_view);
_show = true;
}
private void _view_VisibleChanged(object sender, EventArgs e)
{
if (!_view.Visible)
{
_view.Dispose();
_view = null;
_show = false;
}
}
#region private methods
private void ClearView()
{
_view.ClearView();
}
private void SetView()
{
if (!_show) return;
if (!_curDoc.IsActive) return;
var res = _curDoc.Editor.SelectImplied();
if (res.Status==PromptStatus.OK)
{
_view.SetSelection(res.Value.GetObjectIds());
}
else
{
_view.ClearView();
}
}
#endregion
}
}
Then a Windows.Form class frmSelection:

This form contains a ListView, a Button and a Label.
Here is the code-behind:
using System;
using System.Windows.Forms;
using Autodesk.AutoCAD.DatabaseServices;
namespace ShowSelectionChange
{
public partial class frmSelection : Form
{
public frmSelection()
{
InitializeComponent();
ClearView();
}
public void ClearView()
{
lvSelection.Items.Clear();
lblCount.Text = "Selected: 0";
}
public void SetSelection(ObjectId[] entIds)
{
ClearView();
foreach (var id in entIds)
{
var item = new ListViewItem(id.ToString());
item.SubItems.Add(id.ObjectClass.DxfName);
item.Selected = false;
lvSelection.Items.Add(item);
}
lblCount.Text = "Selected: " +
lvSelection.Items.Count.ToString();
}
private void btnClose_Click(object sender, EventArgs e)
{
Visible = false;
}
}
}
And finally, here the the CommandClass that runs the code:
using Autodesk.AutoCAD.Runtime;
[assembly: CommandClass(typeof(ShowSelectionChange.Commands))]
namespace ShowSelectionChange
{
public class Commands
{
private static CurrentSelectionWatcher _selectionCounter = null;
[CommandMethod("WatchSelection", CommandFlags.Session)]
public static void DoSessionCommand()
{
if (_selectionCounter==null)
{
_selectionCounter = new CurrentSelectionWatcher();
}
if (!_selectionCounter.IsShown) _selectionCounter.Show();
}
}
}
Here is a video clip shows how the code works.
Obviously, I can make the floating form as static and only show/hide it instead of creating new instance/disposing. Of course the modeless form can be substituted by a PaletteSet easily.
P.S. When I copied the code a few hours ago, I missed a couple of lines, which actually makes the execution appear having a bug. The missing lines has been added (in red). I also missed the link to the video clip.
Extra Code
In the following discussion on the topic in AutoCAD .NET API forum, the OP asked if I could show sample code with a PaletteSet. So, here are some extra codee, working in this manner:
- When only one entity is selected/highlighted, and the entity is a lightweight polyline, a floating PaletteSet with single palette shows the polylines information;
- When more than one entities are selected, or no entity is selected, the PaletteSet hides automatically.
The codes are as following.
First, I created another selection watching class CurrentSelectionWatcherA.cs:
using System;
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.EditorInput;
using CadApp = Autodesk.AutoCAD.ApplicationServices.Application;
using Autodesk.AutoCAD.DatabaseServices;
namespace ShowSelectionChange
{
public class CurrentSelectionWatcherA
{
private MyPolylinePaletteSet _ps = null;
private Document _curDoc = null;
public CurrentSelectionWatcherA()
{
_ps = new MyPolylinePaletteSet();
_curDoc = CadApp.DocumentManager.MdiActiveDocument;
if (_curDoc != null)
{
SetView();
_curDoc.ImpliedSelectionChanged +=
Document_ImpliedSelectionChanged;
}
CadApp.DocumentManager.DocumentBecameCurrent +=
DocumentManager_DocumentBecameCurrent;
}
private void Document_ImpliedSelectionChanged(
object sender, EventArgs e)
{
SetView();
}
private void DocumentManager_DocumentBecameCurrent(
object sender, DocumentCollectionEventArgs e)
{
if (_curDoc!=null)
{
_curDoc.ImpliedSelectionChanged -=
Document_ImpliedSelectionChanged;
}
if (e.Document!=null)
{
if (e.Document != _curDoc)
{
SetView();
_curDoc = e.Document;
_curDoc.ImpliedSelectionChanged +=
Document_ImpliedSelectionChanged;
}
}
}
#region private methods
private void SetView()
{
if (!_curDoc.IsActive)
{
_ps.Visible = false;
return;
}
ObjectId polyId = ObjectId.Null;
var res = _curDoc.Editor.SelectImplied();
if (res.Status==PromptStatus.OK)
{
if (res.Value.Count==1)
{
var id = res.Value[0].ObjectId;
if (id.ObjectClass.DxfName.ToUpper()=="LWPOLYLINE")
{
polyId = id;
}
}
}
if (polyId.IsNull)
{
_ps.Visible = false;
}
else
{
_ps.ShowPolyline(polyId);
_ps.Visible = true;
}
}
#endregion
}
}
Secondly, here is the PaletteSet class MyPolylinePaletteSet.cs:
using System;
using System.Drawing;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.Windows;
namespace ShowSelectionChange
{
public class MyPolylinePaletteSet : PaletteSet
{
private PolylinePalette _palette = null;
public MyPolylinePaletteSet():
base("My Polyline","",new Guid("D07DBD90-4D4C-44DB-A6C4-3CC030BD0520"))
{
Style = PaletteSetStyles.UsePaletteNameAsTitleForSingle;
DockEnabled = DockSides.None;
Dock = DockSides.None;
Size = new Size(300, 200);
MinimumSize = new Size(300, 200);
_palette = new Polylivisit link download