Активувати власну ITool з форми, не додаючи її на панель інструментів ArcMap AddIn?


11

Я працюю над надбудовою для ArcMap 10.0, яка додає панель інструментів до ArcMap. Одна OpenModelessDialogCommandкнопка команд ( ) на цій панелі інструментів відкриває діалогове вікно діалогу WinForms, з якого MyToolможна активувати інструмент ( ), щоб, наприклад, вибрати функцію на карті.

Мій Config.esriaddinxмістить такі декларації команд та панелі інструментів:

<Commands>
  <!-- this is the command that opens the modeless WinForms form, from where
       MyTool is available: -->
  <Button id="OpenModelessFormCommand" ... />
  <!-- MyTool is not directly referenced in any toolbar defined in this file: -->
  <Tool id="MyTool" class="MyTool" ... />
</Commands>
<Toolbars>
  <Toolbar ...>
    <Items>
      <Button refID="OpenModelessFormCommand" />
    </Items>
  </Toolbar>
</Toolbars>

З чим у мене виникають проблеми - активізація MyToolу формі. Все, що я знайшов в Інтернеті, - це зразки коду відповідно до:

// get a reference to an instance of MyTool:
ICommandItem myTool = ArcMap.Application.Document.CommandBars.Find("MyTool");
 // activate MyTool: 
ArcMap.Application.CurrentTool = myTool;

Однак це, мабуть, вимагає, щоб воно MyToolфактично з’явилося на командній панелі (наприклад, панелі інструментів) мого додатка. Але це не так. Отже, я спробував це наступне:

ITool myTool = new MyTool();
ArcMap.Application.CurrentTool = myTool;  // Type mismatch! An ICommandItem is expected.

Я навіть розглядав, як додав невидиму AxToolbarControlформу і додав там кнопку MyTool; але потім у мене виникають проблеми, як підключити цю панель інструментів (через SetBuddyControl) до карти відкритого документа. Я не хочу, щоб інструмент функціонував окремо AxMapControl, я хочу, щоб він працював безпосередньо з основною картою, показаною в ArcMap.

Запитання:
Як активувати спеціальний інструмент, який не додається до будь-якої панелі інструментів (або іншої панелі команд для цього питання)?


Якщо ви думаєте, що моя відповідь спрацювала б для вас, якби командна панель працювала так, як рекламується, можливо, додайте тег "помилка" до свого питання. Брудне прання, яке показується на публіці, часто є хорошою мотивацією для продавця виправити помилку.
Кірк Куйкендалл

@Kirk, я збирався це зробити, але не можу - у мене тут недостатньо рангових позицій для створення нових тегів і bug, здається, ще не існує; будь ласка, сміливо редагуйте теги самостійно.
stakx

Відповіді:


7

Це працювало для мене за допомогою ArcGIS 10 SP1. Мій спеціальний інструмент не знаходиться на панелі інструментів:

    Dim UIDCls As ESRI.ArcGIS.esriSystem.UID = New ESRI.ArcGIS.esriSystem.UIDClass()
    ' id property of menu from Config.esriaddinx document
    UIDCls.Value = "ClassLibraryAddin_MyTool"
    Dim document As ESRI.ArcGIS.Framework.IDocument = My.ArcMap.Document
    Dim commandItem As ESRI.ArcGIS.Framework.ICommandItem = TryCast(document.CommandBars.Find(UIDCls), ESRI.ArcGIS.Framework.ICommandItem)
    If commandItem Is Nothing Then
        Exit Sub
    End If
    My.ArcMap.Application.CurrentTool = commandItem

1
+1 Якщо це працює, це впевнено простіше, ніж відповідь, яку я опублікував. Я впевнений, що я спробував це, але з тих пір встановив SP1, тому, можливо, це було фактором.
Кірк Куйкендалл

Відповідь lbross мені дуже допомогла. Пізніше я знайшов майже те саме рішення у пошуку фрагментів ArcGis: "Заяви - Використовуйте інструмент у Windows Form.snippet" (я використовую C #) Я не можу проголосувати за відповідь, бо маю занадто меншу репутацію.
dpalmetz

Я не можу голосувати чи додавати коментарі, бо не маю достатньої репутації, але відповідь lbross працює для мене в ArcGIS 10.2. Я створив ITool без панелі інструментів і викликав його за допомогою кнопки Windows Víctor
vaparicio

3

Я ніколи цього не пробував, але здається, що це має спрацювати: У вашій безмодульній формі є дві змінні члена, перша (m_Tool), що посилається на ваш ITool, а друга (m_Application), що посилається на IApplication. У конструкторі для вашої безмодерної форми запропонуйте інстанціювати ITool та викликати OnCreate , передаючи посилання на IApplication.

На безмоєтній формі є кнопка, яка при натисканні встановлює m_Application. CurrentTool = m_Tool. Крім того, замість того, щоб робити діалогове вікно без режиму, я б рекомендував використовувати вікно, що може бути доклейно, можливо, використовуючи WPF у ньому .

Оновлення У спробі спокутувати публікацію цієї кульгавої відповіді я намагався щось зламати разом. Здається, ви повинні мати можливість динамічно створити панель інструментів, приховати її, додати інструмент до неї (отримавши ICommandItem для встановлення CurrentTool), а потім видалити панель інструментів, не знаючи, що користувач ніколи не знає, що інструмент знаходиться на панелі інструментів. Однак ICommandBar.Dock та ICommandItem.Delete, здається, не працюють для динамічних тобар. ІМХО це помилка.

protected override void OnClick()
{
    UID uid = new UIDClass();
    uid.Value = "Microsoft_ArcMapAddin1_Tool1";
    var bar = ArcMap.Application.Document.CommandBars.Create("mybar", esriCmdBarType.esriCmdBarTypeToolbar)
        as ICommandBar;

    // bug, dock doesn't work ...
    bar.Dock(esriDockFlags.esriDockHide);
    bar.Add(uid);

    var itm = bar.Find(uid);
    if (itm != null)
    {
        ArcMap.Application.CurrentTool = itm;
        // bug, delete doesn't work either
        ((ICommandItem)bar).Delete(); 
    }
}

1
Це не буде працювати, оскільки властивість CurrentTool очікує ICommandItem. Посилання ICommandItem не можна створювати безпосередньо, а їх можна отримати лише через ICommandBars.
Петро Кребс

Цілком вірно щодо currenttool, але ICommandbar.Add створює ICommandItem з UID. Потім проблемою стає те, як позбутися панелі команд після того, як вона більше не потрібна (або принаймні приховує її).
Кірк Куйкендалл

Нічого, дякую за додавання робочого прикладу коду у ваше оновлення. Прикро, що Dockні Deleteробота, але це хороший старт. DeleteДалі я розгляну це питання, думаю.
stakx

яка цікава ідея, я обов'язково спробую розробити з цього. До речі, я також вважаю, що поведінка, яку ви описуєте, є помилкою.
Петро Кребс

Я в кінцевому підсумку використовував інше рішення (серед іншого, зробивши свій інструмент Сінглтоном, щоб я міг легко отримати посилання на нього; CommandBars.Findпроблема раптом вирішилася сама з незрозумілої причини), але я даю цю відповідь галочкою позначити, тому що це, мабуть, те, що я зробив би.
stakx

3

Я не знаю, чому потрібно додати інструмент на панелі інструментів. Тому що я працював з якоюсь подібною річчю, і не знаходжу необхідності додавати її на панелі інструментів.

У моєму випадку, коли користувач натискає кнопку у вікні доклейки, активується інструмент. Для виконання цієї роботи мій клас інструментів виглядає наступним чином:

  • Мій ідентифікатор інструмента: "ArcMap_SelectionTool"
  • Назва мого класу інструментів: "SelectionTool"
  • Зберігайте статичне поле типу інструменту в класі інструменту

    private static ICommandItem _selectionTool;
    private static SelectionTool _instance;
    public static SelectionTool Instance
    {
        get
        {
            if (_instance == null)
            {
                var selectionToolUID = new UID();
                selectionToolUID.Value = "ArcMap_SelectionTool";
                _selectionTool = ArcMap.Application.Document.CommandBars.Find(selectionToolUID, false, false);
                if (_selectionTool == null)
                {
                    MessageBox.Show("Selection tool is not found.");
                    return null;
                }
            }
            if (_selectionTool != null)
                ArcMap.Application.CurrentTool = _selectionTool;
            return _instance;
        }
    }
    
    public static void ExitToolInstance()
    {
        if (_instance != null)
            ArcMap.Application.CurrentTool = null;
    }
    
    public SelectionTool()
    {
        _instance = this;
    }
    
    protected override void OnMouseDown(MouseEventArgs arg)
    {
        if (arg.Button != MouseButtons.Left)
            return;
        //Do Work
    }

Отже, коли мені потрібно створити цей інструмент, я називаю його наступним чином:

        var toolInstance = SelectionTool.Instance;

Після роботи з інструментом мені потрібно вийти з екземпляра інструмента. Тому я називаю SelectionTool.ExitToolInstance()метод.

Ця процедура для мене прекрасно працює.


1

Я зазвичай вирішую це, роблячи команду (OpenModelessDialogCommand у вашому випадку) також інструментом ( ITool). Натиснувши на команду, я відкриваю форму. Тоді я також можу в будь-який момент його активувати як інструмент.

Якщо інструмент, який ви хочете активувати, не є вашим власним, ви можете ретранслювати виклики зі свого ITool (реалізованого як вище) іншому екземпляру інструменту.


0

Якщо у вас є доступ до об’єкта карти, багато інструментів можна запустити, зателефонувавши до onCreate, надсилаючи, наприклад об’єкт MapControl, щоб підключити його до карти. Після цього залишається лише запустити метод onClick.

tool.OnCreate(control.Object)
tool.OnClick()

Не працюйте над усіма інструментами ESRI, оскільки їх потрібно додати до панелі інструментів.


Як я можу отримати посилання на такий об’єкт на карті? Все, що я можу колись отримати, це IMapінтерфейс IMxDocument, але очевидно, що це не те саме, чи не так?
stakx

Редагувати: на робочому столі це об'єкт гака
IApplication

вибачте, я спробував це; це не працює. Проблема тут полягає в тому, що інструмент створюється, але ніколи не активується. По-друге, я досі не бачу, як я міг би отримати MapControlоб'єкт (якщо він насправді потрібен взагалі) через IApplicationбудь-який об'єкт, з якого можна дістатися звідти.
stakx

Ви повинні передати IApplication до OnCreate, роблячи це на Desktop, якщо я не перечитаю документацію. Надсилання в об’єкт MapControl працює для мене в Engine.
MathiasWestin

здається правильним, що ви передатимете IApplicationоб’єкт OnCreate- але цього недостатньо (принаймні, не для мого користувальницького інструменту), оскільки інструмент не активується OnCreate, і тому не отримає жодних подій введення.
stakx
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.