000

Index Labels

Update - Custom Double-Click Action Using Application.BeginDoubleClick Event

.
I posted an article a few months ago on the topic of using Application.BeginDoubleClick event to define our own custom double-click action here.

There a discussion in Autodesk's .NET forum revealed that there is an issue which causes my solution does not work: if the double clicked entity is a BlockReference with attributes in it, the Editor.SelecctImplied() method returns PromptStatus.Error.

I tend to think this is a bug in AutoCAD managed API. Whether it is a bug or not, this is serious blow to the logic of my solution of doing custom double-click action, because BlockReference with attributes in it could be the most targeting entity for custom double-click action when doing AutoCAD custom programming.

Also, I found my logic in that post may not be good enough. For example, user can click any entity or entities to get it or them highlighted and then double-click anywhere in the Editor to get the code in my Application.BeginDoubleClick event handler run and trigger my custom double-click action, because in this case, Editor.SelectImplied() still can get "pickfirst" selection set. This may not be user wants.

So, in order to find workaround for the Blockreference with attributes not working issue and make the custom double-click action more accurate on what entity user is actually double-clicked, I worked out a solution that does not use Editor.SelectImplied() in Application.BeginDoubleClick event handler to find out exactly what entity is double-clicked and then do things accordingly (e.g. trigger my custom double-click action if needed).

The logic is like this:

In the Application.BeginDoubleClick event handler, I get current mouse location, and then get the cursor (the pickbox)'s size. Then I use the pickbox' information to get 4 points representing the 4 corners of the pickbox of the cursor when double-clicking occurs. Once the 4 points are available, I use Editor.SelectCrossingPolygon() method to find entity or entities being double-clicked.

This approach is obviously more accurately reflect what user exactly double-clicked on. Depending on the pickbox's size (set by system variable "PICKBOX", value from 0 to 20 pixel), none (when ""PICKBOX" is set to 0) or more entities could be double-clicked.

With this logic in mind, I created and Editor extension method to return a PromptSelectionResult object, which takes a Point3d input (the cursor's location where double-click occurs):

    1 public static class EditorSelectionExtension
    2 {
    3     public static PromptSelectionResult  SelectAtPickBox(
    4         this Editor ed, Point3d pickBoxCentre)
    5     {
    6         //Get pick box's size on screen
    7         System.Drawing.Point screenPt = ed.PointToScreen(pickBoxCentre, 1);
    8 
    9         //Get pickbox's size. Note, the number obtained from
   10         //system variable "PICKBOX" is actually the half of
   11         //pickbox's width/height
   12         object pBox = Application.GetSystemVariable("PICKBOX");
   13         int pSize = Convert.ToInt32(pBox);
   14 
   15         //Define a Point3dCollection for CrossingWindow selecting
   16         Point3dCollection points = new Point3dCollection();
   17 
   18         System.Drawing.Point p;
   19         Point3d pt;
   20 
   21         p = new System.Drawing.Point(screenPt.X - pSize, screenPt.Y - pSize);
   22         pt = ed.PointToWorld(p, 1);
   23         points.Add(pt);
   24 
   25         p = new System.Drawing.Point(screenPt.X + pSize, screenPt.Y - pSize);
   26         pt = ed.PointToWorld(p, 1);
   27         points.Add(pt);
   28 
   29         p = new System.Drawing.Point(screenPt.X + pSize, screenPt.Y + pSize);
   30         pt = ed.PointToWorld(p, 1);
   31         points.Add(pt);
   32 
   33         p = new System.Drawing.Point(screenPt.X - pSize, screenPt.Y + pSize);
   34         pt = ed.PointToWorld(p, 1);
   35         points.Add(pt);
   36 
   37         return ed.SelectCrossingPolygon(points);
   38     }
   39 }

With this extension method available, I simply modified the portion of code for getting selected entity or entities in Application_BeginDoubeClick() event handler of my original solution. Now, my solution for custom double-click action work as good as the original one on every entity type, including BlockReference with attributes, of course. Here is the original code in the Application_BeginDoubleClick() event handler:

    1 private static void Application_BeginDoubleClick(
    2     object sender, BeginDoubleClickEventArgs e)
    3 {
    4     _customCmd = null;
    5     _selectedEntId = ObjectId.Null;
    6 
    7     //Get entity which user double-clicked on
    8     Editor ed=Application.DocumentManager.MdiActiveDocument.Editor;
    9     PromptSelectionResult res = ed.SelectImplied();
   10     if (res.Status == PromptStatus.OK)
   11     {
   12         ObjectId[] ids = res.Value.GetObjectIds();
   13 
   14         //Only when there is one entity selected, we go ahead to see
   15         //if there is a custom command supposed to target at this entity
   16         if (ids.Length == 1)
   17         {
   18             //Find mapped custom command name
   19             string cmd = _customCommands.GetCustomCommand(ids[0]);
   20             if (!string.IsNullOrEmpty(cmd))
   21             {
   22                 _selectedEntId = ids[0];
   23                 _customCmd = cmd;
   24 
   25                 ed.WriteMessage("\nRun command {0} agianst entity {1}",
   26                     _customCmd, _selectedEntId.ToString());
   27 
   28                 if (System.Convert.ToInt32(
   29                     Application.GetSystemVariable("DBLCLKEDIT")) == 0)
   30                 {
   31                     //Since "Double click editing" is not enabled, we'll
   32                     //go ahead to launch our custom command
   33                     LaunchCustomCommand(ed);
   34                 }
   35                 else
   36                 {
   37                     //Since "Double Click Editing" is enabled, a command
   38                     //defined in CUI/CUIX will be fired. Let the code return
   39                     //and wait the DocumentLockModeChanged and
   40                     //DocumentLockModeChangeVetoed event handlers do their job
   41                     return;
   42                 }
   43             }
   44             else
   45             {
   46                 ed.WriteMessage(
   47                     "\nNo custom command is defined agaist the selected entity.");
   48             }
   49         }
   50     }
   51     else
   52     {
   53         ed.WriteMessage("\nNo entity or more than 1 entities selected.");
   54     }
   55 }

Here is updated code in the Application_BeginDoubleClick event handler:

    1 private static void Application_BeginDoubleClick(
    2     object sender, BeginDoubleClickEventArgs e)
    3 {
    4     _customCmd = null;
    5     _selectedEntId = ObjectId.Null;
    6 
    7     //Get entity which user double-clicked on
    8     Editor ed=Application.DocumentManager.MdiActiveDocument.Editor;
    9     PromptSelectionResult res = ed.SelectAtPickBox(e.Location);
   10     if (res.Status == PromptStatus.OK)
   11     {
   12         ObjectId[] ids = res.Value.GetObjectIds();
   13 
   14         //Only when there is one entity selected, we go ahead to see
   15         //if there is a custom command supposed to target at this entity
   16         if (ids.Length == 1)
   17         {
   18             //Find mapped custom command name
   19             string cmd = _customCommands.GetCustomCommand(ids[0]);
   20             if (!string.IsNullOrEmpty(cmd))
   21             {
   22                 _selectedEntId = ids[0];
   23                 _customCmd = cmd;
   24 
   25                 ed.WriteMessage("\nRun command {0} agianst entity {1}",
   26                     _customCmd, _selectedEntId.ToString());
   27 
   28                 if (System.Convert.ToInt32(
   29                     Application.GetSystemVariable("DBLCLKEDIT")) == 0)
   30                 {
   31                     //Since "Double click editing" is not enabled, we'll
   32                     //go ahead to launch our custom command
   33                     LaunchCustomCommand(ed);
   34                 }
   35                 else
   36                 {
   37                     //Since "Double Click Editing" is enabled, a command
   38                     //defined in CUI/CUIX will be fired. Let the code return
   39                     //and wait the DocumentLockModeChanged and
   40                     //DocumentLockModeChangeVetoed event handlers do their job
   41                     return;
   42                 }
   43             }
   44             else
   45             {
   46                 ed.WriteMessage(
   47                     "\nNo custom command is defined agaist the selected entity.");
   48             }
   49         }
   50     }
   51     else
   52     {
   53         ed.WriteMessage("\nNo entity or more than 1 entities selected.");
   54     }
   55 }

As you can see, once the extension method Editor.SelectAtPickBox() is available, I only changed one line of the code in the original solution.

Now my custom double-click action by-passes the possible AutoCAD .NET API bug that prevents BlockReference with attribute from being selected by Editor.SelectImplied().

To see the whole solution of custom double-click action, go the link provided at the beginning of the article.

Blog Archive

Labels

3D Modeling 3D Sketch Inventor AI Design AI in Manufacturing AI Tools Architecture Artificial Intelligence AutoCAD AutoCAD advice AutoCAD Basics AutoCAD Beginners AutoCAD Civil3D AutoCAD commands AutoCAD efficiency AutoCAD features AutoCAD File Management AutoCAD Layer AutoCAD learning AutoCAD print settings AutoCAD productivity AutoCAD Teaching AutoCAD Techniques AutoCAD tips AutoCAD training. AutoCAD tricks AutoCAD Tutorial AutoCAD workflow AutoCAD Xref Autodesk Autodesk 2025 Autodesk AI Tools Autodesk AutoCAD Autodesk Fusion 360 Autodesk Inventor Autodesk Inventor Frame Generator Autodesk Inventor iLogic Autodesk Recap Autodesk Revit Autodesk Software Autodesk Video Automation Automation Tutorial Basic Commands Basics Beginner Beginner Tips BIM BIM Implementation Block Editor ByLayer CAD comparison CAD Design CAD File Size Reduction CAD line thickness CAD Optimization CAD Productivity CAD software clean CAD file cleaning command Cloud Collaboration command abbreviations Construction Technology Contraints Create resizable blocks CTB STB Data Reference Data Shortcut design software Design Workflow Digital Design Digital Twin Drafting Standards Drawing Automation Dref Dynamic Block Dynamic Block AutoCAD Dynamic Blocks Dynamic doors Dynamic windows eco design editing commands energy efficiency Engineering Engineering Design Engineering Innovation Engineering Technology engineering tools Excel Express Tools External Reference Fast Structural Design Fusion 360 Generative Design green building Grips heavy CAD file Heavy CAD Files iLogic Industry 4.0 Insight Inventor API Inventor Drawing Template Inventor Frame Generator Inventor Graphics Issues Inventor IDW Inventor Tips Keyboard Shortcuts Learn AutoCAD Machine Learning in CAD maintenance command Management Manufacturing Innovation Metal Structure ObjectARX .NET API Organization OVERKILL OVERKILL AutoCAD Palette PDF Plot Style AutoCAD Practice Drawing Printing Quality professional printing Professional Tips PTC Creo PURGE PURGE AutoCAD ReCap reduce CAD file size Resizable Block Revit Revit Best Practices Revit Workflow Ribbon screen shortcut keys Shortcuts Siemens NX Sketch Small Firms Smart Block Smart Factory SolidWorks Steel Structure Design sustainability Sustainable Manufacturing toolbar Tutorial User Interface (UI) Workbook Workspace XLS Xref