Thursday, March 14, 2013

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):

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:

1privatestaticvoid Application_BeginDoubleClick(

2object sender, BeginDoubleClickEventArgs e)

3 {

4 _customCmd = null;

5 _selectedEntId = ObjectId.Null;

6

7//Get entity which user double-clicked on

8Editor ed=Application.DocumentManager.MdiActiveDocument.Editor;

9PromptSelectionResult res = ed.SelectImplied();

10if (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

16if (ids.Length == 1)

17 {

18//Find mapped custom command name

19string cmd = _customCommands.GetCustomCommand(ids[0]);

20if (!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

28if (System.Convert.ToInt32(

29Application.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 }

35else

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

41return;

42 }

43 }

44else

45 {

46 ed.WriteMessage(

47"\nNo custom command is defined agaist the selected entity.");

48 }

49 }

50 }

51else

52 {

53 ed.WriteMessage("\nNo entity or more than 1 entities selected.");

54 }

55 }

Here is updated code in the Application_BeginDoubleClick event handler:

1privatestaticvoid Application_BeginDoubleClick(

2object sender, BeginDoubleClickEventArgs e)

3 {

4 _customCmd = null;

5 _selectedEntId = ObjectId.Null;

6

7//Get entity which user double-clicked on

8Editor ed=Application.DocumentManager.MdiActiveDocument.Editor;

9 PromptSelectionResult res = ed.SelectAtPickBox(e.Location);

10if (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

16if (ids.Length == 1)

17 {

18//Find mapped custom command name

19string cmd = _customCommands.GetCustomCommand(ids[0]);

20if (!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

28if (System.Convert.ToInt32(

29Application.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 }

35else

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

41return;

42 }

43 }

44else

45 {

46 ed.WriteMessage(

47"\nNo custom command is defined agaist the selected entity.");

48 }

49 }

50 }

51else

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.

Followers

About Me

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.