Aktywujesz niestandardowy ITool z formularza bez dodawania go do paska narzędzi ArcMap AddIn?

11

Pracuję nad dodatkiem do ArcMap 10.0, który dodaje pasek narzędzi do ArcMap. Jeden OpenModelessDialogCommandprzycisk polecenia ( ) na tym pasku narzędzi otwiera niemodalne okno dialogowe WinForm, w którym MyToolmożna aktywować narzędzie ( ) w celu np. Wybrania elementu na mapie.

My Config.esriaddinxzawiera następujące deklaracje poleceń i pasków narzędzi:

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

Mam problem z aktywacją MyToolw formularzu. Wszystko, co znalazłem w Internecie, to próbki kodu w stylu:

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

Jednak najwyraźniej wymaga to, aby MyToolfaktycznie pojawił się na pasku poleceń (np. Pasku narzędzi) mojego dodatku. Ale tak nie jest. Wypróbowałem to następnie:

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

Nawet zastanawiałem się nad dodaniem niewidzialnego AxToolbarControldo mojego formularza i dodaniem do niego przycisku MyTool; ale potem mam problemy z podłączeniem tego paska narzędzi (poprzez SetBuddyControl) do mapy otwartego dokumentu. Nie chcę, aby narzędzie działało osobno AxMapControl, chcę, aby działało bezpośrednio z główną mapą pokazaną w ArcMap.

Pytanie:
Jak aktywować niestandardowe narzędzie, które nie zostało dodane do żadnego paska narzędzi (lub innego paska poleceń, jeśli o to chodzi)?

stakx
źródło
Jeśli uważasz, że moja odpowiedź zadziałałaby dla Ciebie, gdyby pasek poleceń działał zgodnie z reklamą, być może dodaj tag „błąd” do pytania. Brudne pranie pokazywane publicznie jest często dobrą motywacją dla sprzedawcy do naprawienia błędu.
Kirk Kuykendall
@Kirk, zamierzałem to zrobić, ale nie mogę - nie mam tutaj wystarczającej rangi, aby tworzyć nowe tagi, i bugwydaje się, że jeszcze nie istnieje; możesz samodzielnie edytować tagi.
stakx

Odpowiedzi:

7

To działało dla mnie przy użyciu ArcGIS 10 SP1. Moje niestandardowe narzędzie nie znajduje się na pasku narzędzi:

    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
lbross
źródło
1
+1 Jeśli to zadziała, to z pewnością jest prostsze niż odpowiedź, którą opublikowałem. Jestem pewien, że próbowałem, ale od tamtej pory zainstalowałem SP1, więc może to był czynnik.
Kirk Kuykendall
Odpowiedź Lbrossa bardzo mi pomogła. Później znalazłem prawie to samo rozwiązanie w wyszukiwarce fragmentów ArcGis: „Instrukcje - Używaj narzędzia w Windows Form.snippet” (używam C #) Nie mogę głosować na odpowiedź, ponieważ mam zbyt małą reputację.
dpalmetz
Nie mogę głosować ani dodawać komentarzy, ponieważ nie mam wystarczającej reputacji, ale odpowiedź lbross działa dla mnie w ArcGIS 10.2. Stworzyłem ITool bez paska narzędzi i nazwałem go przyciskiem Windows Víctor
vaparicio
3

Nigdy tego nie próbowałem, ale wydaje się, że powinno to działać: w twojej niemodalnej formie mają dwie zmienne składowe, pierwsza (m_Tool) odwołuje się do Twojego ITool, a druga (m_Application) odwołuje się do IApplication. W konstruktorze formularza bez formy poproś go o utworzenie instancji ITool i wywołanie OnCreate , przekazując odwołanie do aplikacji IApplication.

W formularzu bez wzoru znajduje się przycisk, który po kliknięciu ustawia m_Application. CurrentTool = m_Tool. Ponadto, zamiast robić niemodalne okno dialogowe, zaleciłbym użycie dokowalnego okna, być może przy użyciu WPF w nim .

Aktualizacja Próbując odpokutować za opublikowanie tej kiepskiej odpowiedzi, próbowałem zhakować coś razem. Wygląda na to, że powinieneś być w stanie dynamicznie utworzyć pasek narzędzi, ukryć go, dodać do niego narzędzie (ustawienie ICommandItem na wartość CurrentTool), a następnie usunąć pasek narzędzi bez wiedzy użytkownika, że ​​narzędzie było na pasku narzędzi. Jednak ICommandBar.Dock i ICommandItem.Delete nie działają w przypadku dynamicznych paska narzędzi. IMHO to błąd.

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(); 
    }
}
Kirk Kuykendall
źródło
1
To nie zadziała, ponieważ właściwość CurrentTool oczekuje wartości ICommandItem. Odniesień ICommandItem nie można utworzyć bezpośrednio, ale można je pobrać tylko za pomocą ICommandBars.
Petr Krebs,
Całkiem słusznie o currenttool, ale ICommandbar.Add tworzy ICommandItem z UID. Problemem staje się wtedy, jak pozbyć się paska poleceń, gdy nie jest już potrzebny (lub przynajmniej go ukrywa).
Kirk Kuykendall,
Wow, dzięki za dodanie działającego przykładu kodu do twojej aktualizacji. Szkoda, że ​​ani Docknie Deletedziałają, ale to dobry początek. Myślę, że przyjrzę się temu Deletezagadnieniu dalej.
stakx 11.03.11
co za ciekawy pomysł, zdecydowanie spróbuję to rozwinąć. Przy okazji uważam, że opisywane zachowanie jest błędem.
Petr Krebs,
Skończyło się na innym rozwiązaniu (między innymi przez uczynienie z mojego narzędzia singletonu, dzięki czemu mogę łatwo znaleźć odniesienie do niego; CommandBars.Findproblem nagle rozwiązał się z niewiadomego powodu), ale daję odpowiedź tak znak, bo to prawdopodobnie zrobiłbym.
stakx
3

Nie wiem, dlaczego musisz dodać to narzędzie na pasku narzędzi. Ponieważ pracowałem z podobną rzeczą i nie muszę dodawać jej na pasku narzędzi.

W moim przypadku, gdy użytkownik kliknie przycisk w oknie dokowalnym, narzędzie aktywuje się. Aby wykonać tę pracę, moja klasa narzędzi wygląda następująco:

  • Mój identyfikator narzędzia to: „ArcMap_SelectionTool”
  • Moja nazwa klasy narzędzi to: „SelectionTool”
  • Zachowaj statyczne pole typu narzędzia w klasie narzędzi

    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
    }

Dlatego za każdym razem, gdy muszę utworzyć instancję tego narzędzia, nazywam to w następujący sposób:

        var toolInstance = SelectionTool.Instance;

Po pracy z narzędziem muszę wyjść z instancji narzędzia. Więc wywołuję SelectionTool.ExitToolInstance()metodę.

Ta procedura działa dla mnie dobrze.

Emi
źródło
1

Zwykle rozwiązuję to, czyniąc polecenie (w twoim przypadku OpenModelessDialogCommand) również narzędziem ( ITool). Po kliknięciu polecenia otwieram formularz. Następnie mogę aktywować go jako narzędzie w dowolnym momencie.

Jeśli narzędzie, które chcesz aktywować, nie jest twoje, możesz przekazywać połączenia z Twojego IToola (zaimplementowanego jak wyżej) do innego wystąpienia narzędzia.

Petr Krebs
źródło
0

Jeśli masz dostęp do obiektu mapy, wiele narzędzi można uruchomić, wywołując funkcję onCreate, wysyłając na przykład obiekt MapControl w celu podłączenia go do mapy. Następnie wystarczy uruchomić metodę onClick.

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

Nie działa na wszystkich narzędziach ESRI, ponieważ niektóre wymagają dodania do paska narzędzi.

MathiasWestin
źródło
Jak uzyskać odniesienie do takiego obiektu mapy? Wydaje mi się, że mogę tylko uzyskać IMapinterfejs IMxDocument, ale najwyraźniej to nie to samo, prawda?
stakx
Edycja: na pulpicie to aplikacja, która jest obiektem przechwytującym
MathiasWestin
przepraszam, próbowałem tego; to nie działa. Problem polega na tym, że narzędzie zostaje utworzone, ale nigdy nie jest aktywowane. Po drugie, wciąż nie widzę, jak mógłbym dostać MapControlprzedmiot (jeśli w ogóle go potrzebuję) IApplicationlub jakikolwiek obiekt stamtąd dostępny.
stakx 11.03.11
Powinieneś przekazać IApplication do OnCreate, robiąc to na pulpicie, jeśli nie popełniam błędu w interpretacji dokumentacji. Wysyłanie w obiekcie MapControl działa dla mnie w silniku.
MathiasWestin
wydaje się poprawne, że przekażesz IApplicationobiekt OnCreate- ale to nie wystarczy (przynajmniej nie w przypadku mojego niestandardowego narzędzia), ponieważ narzędzie nie jest aktywowane przez OnCreate, a zatem nie odbiera żadnych zdarzeń wejściowych.
stakx