Benutzerdefiniertes ITool aus dem Formular aktivieren, ohne es der ArcMap AddIn-Symbolleiste hinzuzufügen?

11

Ich arbeite an einem Add-In für ArcMap 10.0, das ArcMap eine Symbolleiste hinzufügt. Eine Befehlsschaltfläche ( OpenModelessDialogCommand) in dieser Symbolleiste öffnet ein modellloses WinForms-Dialogfeld, in dem ein tool ( MyTool) aktiviert werden kann, um z. B. ein Feature auf der Karte auszuwählen.

My Config.esriaddinxenthält die folgenden Befehls- und Symbolleistendeklarationen:

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

Ich habe Probleme damit, MyTooldas Formular zu aktivieren . Alles, was ich im Internet gefunden habe, sind Codebeispiele wie:

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

Dies erfordert jedoch anscheinend, dass MyTooltatsächlich in einer Befehlsleiste (z. B. Symbolleiste) meines Add-Ins angezeigt wird. Das ist aber nicht der Fall. Also habe ich das als nächstes versucht:

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

Ich habe sogar versucht AxToolbarControl, meinem Formular ein Unsichtbares hinzuzufügen und dort eine Schaltfläche hinzuzufügen MyTool. Aber dann habe ich Probleme beim Verbinden dieser Symbolleiste (über SetBuddyControl) mit der Karte des geöffneten Dokuments. Ich möchte nicht, dass das Tool in einer separaten Funktion funktioniert AxMapControl. Ich möchte, dass es direkt mit der in ArcMap angezeigten Hauptkarte funktioniert.

Frage:
Wie aktiviere ich ein benutzerdefiniertes Werkzeug, das keiner Symbolleiste (oder einer anderen Befehlsleiste) hinzugefügt wurde?

stakx
quelle
Wenn Sie der Meinung sind, dass meine Antwort für Sie funktionieren würde, wenn die Befehlsleiste wie angekündigt funktioniert, fügen Sie Ihrer Frage möglicherweise ein "Bug" -Tag hinzu. In der Öffentlichkeit gezeigte schmutzige Wäsche ist oft eine gute Motivation für einen Verkäufer, einen Fehler zu beheben.
Kirk Kuykendall
@Kirk, ich wollte das tun, aber ich kann nicht - ich habe hier nicht genug Rang, um neue Tags zu erstellen, und es bugscheint noch nicht zu existieren; Bitte zögern Sie nicht, die Tags selbst zu bearbeiten.
Stakx

Antworten:

7

Dies funktionierte bei mir mit ArcGIS 10 SP1. Mein benutzerdefiniertes Tool befindet sich nicht in einer Symbolleiste:

    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
quelle
1
+1 Wenn dies funktioniert, ist dies sicher einfacher als die Antwort, die ich gepostet habe. Ich bin mir ziemlich sicher, dass ich das versucht habe, habe aber seitdem SP1 installiert. Vielleicht war das ein Faktor.
Kirk Kuykendall
Die Antwort von lbross hat mir sehr geholfen. Später fand ich im ArcGis-Snippet-Finder fast dieselbe Lösung: "Anweisungen - Verwenden eines Tools in einem Windows Form.snippet" (ich verwende C #). Ich kann die Antwort nicht abstimmen, da ich zu wenig Ansehen habe.
Dpalmetz
Ich kann nicht abstimmen oder Kommentare hinzufügen, weil ich nicht genug Ruf habe, aber die Antwort von lbross funktioniert in ArcGIS 10.2 für mich. Ich habe ein ITool ohne Symbolleiste erstellt und es über eine Windows-Schaltfläche Víctor
vaparicio
3

Ich habe dies noch nie versucht, aber es scheint, als sollte es funktionieren: In Ihrem modelllosen Formular haben Sie zwei Mitgliedsvariablen, die erste (m_Tool), die auf Ihr ITool verweist, und die zweite (m_Application), die auf die IApplication verweist. Lassen Sie es im Konstruktor für Ihr modellloses Formular das ITool instanziieren und OnCreate aufrufen , indem Sie eine IApplication-Referenz übergeben.

In Ihrem modelllosen Formular befindet sich eine Schaltfläche, die beim Klicken m_Application festlegt. CurrentTool = m_Tool. Anstatt ein modellloses Dialogfeld zu erstellen, würde ich außerdem empfehlen, ein andockbares Fenster zu verwenden, in dem möglicherweise WPF verwendet wird .

Update Bei dem Versuch, diese lahme Antwort zu büßen, habe ich versucht, etwas zusammen zu hacken. Anscheinend sollten Sie in der Lage sein, eine Symbolleiste dynamisch zu erstellen, auszublenden, das Werkzeug hinzuzufügen (ein ICommandItem auf CurrentTool zu setzen) und dann die Symbolleiste zu löschen, ohne dass der Benutzer jemals weiß, dass sich das Werkzeug in einer Symbolleiste befindet. ICommandBar.Dock und ICommandItem.Delete scheinen jedoch nicht für dynamische Toobars zu funktionieren. IMHO ist das ein Fehler.

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
quelle
1
Dies funktioniert nicht, da die CurrentTool-Eigenschaft ein ICommandItem erwartet. ICommandItem-Referenzen können nicht direkt erstellt, sondern nur über ICommandBars abgerufen werden.
Petr Krebs
Ganz richtig zu currenttool, aber ICommandbar.Add erstellt ein ICommandItem aus einer UID. Das Problem wird dann, wie die Befehlsleiste entfernt werden kann, nachdem sie nicht mehr benötigt wird (oder zumindest ausgeblendet wird).
Kirk Kuykendall
wow, danke, dass du ein funktionierendes Codebeispiel in dein Update aufgenommen hast. Es ist eine Schande, dass weder Docknoch Deletearbeiten, aber es ist ein guter Anfang. Ich werde das DeleteThema weiter untersuchen, denke ich.
Stakx
Was für eine interessante Idee, ich werde auf jeden Fall versuchen, darauf einzugehen. Übrigens glaube ich auch, dass das von Ihnen beschriebene Verhalten ein Fehler ist.
Petr Krebs
Am Ende habe ich eine andere Lösung verwendet (unter anderem, indem ich mein Tool zu einem Singleton gemacht habe, damit ich leicht darauf verweisen kann; das CommandBars.FindProblem hat sich aus einem unbekannten Grund plötzlich von selbst gelöst), aber ich gebe dieser Antwort das Häkchen Markieren Sie, weil dies wahrscheinlich das ist, was ich getan hätte.
Stakx
3

Ich weiß nicht, warum Sie das Werkzeug in eine Symbolleiste einfügen müssen. Weil ich mit einer ähnlichen Sache gearbeitet habe und keine Notwendigkeit gefunden habe, sie in der Symbolleiste hinzuzufügen.

In meinem Fall wird ein Tool aktiviert, wenn der Benutzer auf eine Schaltfläche im andockbaren Fenster klickt. Um diese Arbeit auszuführen, sieht meine Werkzeugklasse folgendermaßen aus:

  • Meine Werkzeug-ID lautet: "ArcMap_SelectionTool"
  • Mein Werkzeugklassenname lautet: "SelectionTool"
  • Behalten Sie ein statisches Feld des Werkzeugtyps in der Werkzeugklasse bei

    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
    }

Wenn ich dieses Tool instanziieren muss, rufe ich es folgendermaßen auf:

        var toolInstance = SelectionTool.Instance;

Nachdem ich mit dem Tool gearbeitet habe, muss ich die Tool-Instanz beenden. Also rufe ich SelectionTool.ExitToolInstance()Methode auf.

Dieses Verfahren funktioniert gut für mich.

Emi
quelle
1

Normalerweise löse ich das, indem ich den Befehl (in Ihrem Fall OpenModelessDialogCommand) auch zu einem Tool ( ITool) mache . Wenn ich auf den Befehl klicke, öffne ich das Formular. Dann kann ich es auch jederzeit als Tool aktivieren.

Wenn das Tool, das Sie aktivieren möchten, nicht Ihr eigenes ist, können Sie Aufrufe von Ihrem ITool (wie oben implementiert) an die andere Tool-Instanz weiterleiten.

Petr Krebs
quelle
0

Wenn Sie Zugriff auf das Kartenobjekt haben, können viele Tools ausgeführt werden, indem Sie onCreate aufrufen und beispielsweise das MapControl-Objekt senden, um es mit der Karte zu verbinden. Danach muss nur noch die onClick-Methode ausgeführt werden.

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

Arbeiten Sie nicht mit allen ESRI-Tools, da einige zu einer Symbolleiste hinzugefügt werden müssen.

MathiasWestin
quelle
Wie würde ich einen Verweis auf ein solches Kartenobjekt erhalten? Alles, was ich jemals zu bekommen scheinen kann, ist eine IMapSchnittstelle IMxDocument, aber klar, das ist nicht dasselbe, oder?
Stakx
Bearbeiten: In Desktop ist die IApplication das Hook-Objekt: help.arcgis.com/de/sdk/10.0/arcobjects_net/conceptualhelp/…
MathiasWestin
Entschuldigung, ich habe es versucht. es funktioniert nicht Das Problem hierbei ist, dass das Tool erstellt wird, aber nie aktiviert wird. Zweitens sehe ich immer noch nicht, wie ich ein MapControlObjekt (wenn ich überhaupt eines brauche) durch IApplicationoder ein von dort erreichbares Objekt bekommen könnte.
Stakx
Sie sollten IApplication an OnCreate übergeben, wenn Sie dies in Desktop tun, wenn ich die Dokumentation nicht falsch lese. Das Senden eines MapControl-Objekts funktioniert für mich in Engine.
MathiasWestin
Es scheint richtig, dass Sie ein IApplicationObjekt an übergeben würden OnCreate- aber das reicht nicht aus (zumindest nicht für mein benutzerdefiniertes Tool), da das Tool nicht von aktiviert wird OnCreateund daher keine Eingabeereignisse empfängt.
Stakx