среда, 20 марта 2013 г.

Контекстное меню элементов в AutoCAD

Маленький пример на тему работы с контекстным меню элементов в AutoCAD. Показаны способы динамического изменения состава и свойств элементов меню, в зависимости от тех или иных условий (на усмотрение разработчика).

В своём блоге, Kean Walmsley разместил заметку на тему того, как можно добавлять информацию в контекстное меню элементов AutoCAD. Меню регистрируется для объектов определённого типа и если один из типов унаследован от другого, то для него будет отображаться и контекстное меню, заданное для родителя. Если такое поведение не желательно, то можно либо блокировать (делать недоступными) элементы меню, определённые для родительского класса, либо динамически удалять\добавлять нежелательные элементы меню.

Предположим, что нужно определить один дополнительный пункт контекстного меню для объектов вхождений блоков (BlockReference) и один для таблиц (Table). Класс Table унаследован от BlockReference и поэтому, по умолчанию, будет содержать в контекстном меню оба добавленных пункта. Если такое поведение нежелательно, то его можно изменить. Ниже даю код, в котором два варианта решения (ненужный следует закомментировать, по умолчанию закомментирован первый вариант):

  1. Можно не нужные  пункты меню делать недоступными (ненажимаемыми).
  2. Можно динамически изменять состав меню, добавляя\удаляя пункты меню.

   1:  using Autodesk.AutoCAD.ApplicationServices;
   2:  using Autodesk.AutoCAD.DatabaseServices;
   3:  using Autodesk.AutoCAD.EditorInput;
   4:  using Autodesk.AutoCAD.Runtime;
   5:  using Autodesk.AutoCAD.Windows;
   6:  using System;
   7:  using System.Collections;
   8:  using System.Collections.Generic;
   9:  using System.Linq;
  10:   
  11:  namespace ContextMenuApplication {
  12:   
  13:      public class Commands : IExtensionApplication {
  14:   
  15:          public void Initialize() {
  16:              CountMenu.Attach();
  17:          }
  18:          public void Terminate() {
  19:              CountMenu.Detach();
  20:          }
  21:      }
  22:   
  23:      public class CountMenu {
  24:          private static ContextMenuExtension cme;
  25:   
  26:          public static void Attach() {
  27:              cme = new ContextMenuExtension();
  28:              cme.Popup += cme_Popup;
  29:              MenuItem mi = new MenuItem("My BlockReference menu item");
  30:              mi.Click += new EventHandler(PrintBlockRefMsg);
  31:              cme.MenuItems.Add(mi);
  32:              RXClass rxc = Entity.GetClass(typeof(BlockReference));
  33:              Application.AddObjectContextMenuExtension(rxc, cme);
  34:   
  35:              cme = new ContextMenuExtension();
  36:              mi = new MenuItem("My Table menu item");
  37:              mi.Click += new EventHandler(PrintTableMsg);
  38:              cme.MenuItems.Add(mi);
  39:              rxc = Entity.GetClass(typeof(Table));
  40:              Application.AddObjectContextMenuExtension(rxc, cme);
  41:          }
  42:   
  43:          static void cme_Popup(object sender, EventArgs e) {
  44:              ContextMenuExtension cme = (ContextMenuExtension) sender;
  45:              Document doc = Application.DocumentManager.MdiActiveDocument;
  46:              Editor ed = doc.Editor;
  47:              PromptSelectionResult result = ed.GetSelection();
  48:              String className = result.Value.GetObjectIds().First().ObjectClass.Name;
  49:              Boolean isEnadled = className == "AcDbBlockReference";
  50:   
  51:              // Первый вариант: управление доступностью элементов без их удаления/добавления.
  52:              //foreach (MenuItem item in cme.MenuItems)
  53:              //    item.Enabled = isEnadled;
  54:   
  55:              // Второй вариант: динамическое удаление/добавление элементов меню.
  56:              if (isEnadled && cme.MenuItems.Count == 0) {
  57:                  MenuItem mi = new MenuItem("My BlockReference menu item");
  58:                  mi.Click += new EventHandler(PrintBlockRefMsg);
  59:                  cme.MenuItems.Add(mi);
  60:              }
  61:              else if (!isEnadled)
  62:                  foreach (MenuItem item in cme.MenuItems.ToArray()) {
  63:                      item.Click -= new EventHandler(PrintBlockRefMsg);
  64:                      cme.MenuItems.Remove(item);
  65:                  }
  66:   
  67:          }
  68:          public static void Detach() {
  69:              RXClass rxc = Entity.GetClass(typeof(Entity));
  70:              Application.RemoveObjectContextMenuExtension(rxc, cme);
  71:          }
  72:          private static void PrintBlockRefMsg(Object o, EventArgs e) {
  73:              Application.DocumentManager.MdiActiveDocument.Editor.WriteMessage(
  74:                  "Hello from the BlockReference!\n");
  75:          }
  76:   
  77:          private static void PrintTableMsg(Object o, EventArgs e) {
  78:              Application.DocumentManager.MdiActiveDocument.Editor.WriteMessage(
  79:                  "Hello from the Table!\n");
  80:          }
  81:      }
  82:  }



Комментариев нет: