Attivare ITool personalizzato dal modulo senza aggiungerlo alla barra degli strumenti ArcIn Add Add?


11

Sto lavorando a un componente aggiuntivo per ArcMap 10.0 che aggiunge una barra degli strumenti ad ArcMap. Un OpenModelessDialogCommandpulsante command ( ) su quella barra degli strumenti apre una finestra di dialogo WinForms non modale, da cui è MyToolpossibile attivare uno strumento ( ) per selezionare, ad esempio, una funzione sulla mappa.

My Config.esriaddinxcontiene queste dichiarazioni di comandi e barre degli strumenti:

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

Ciò con cui ho problemi è l'attivazione MyToolnel modulo. Tutto quello che ho trovato su Internet sono esempi di codice sulla falsariga di:

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

Tuttavia, ciò a quanto pare richiede che venga MyTooleffettivamente visualizzato in una barra dei comandi (ad es. Barra degli strumenti) del mio componente aggiuntivo. Ma non è così. Quindi, ho provato questo dopo:

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

Ho anche cercato di aggiungere un invisibile AxToolbarControlal mio modulo e aggiungere un pulsante per MyToollì; ma poi sto incontrando problemi su come collegare quella barra degli strumenti (tramite SetBuddyControl) alla mappa del documento aperto. Non voglio che lo strumento funzioni in modo separato AxMapControl, voglio che funzioni direttamente con la mappa principale mostrata in ArcMap.

Domanda:
Come posso attivare uno strumento personalizzato che non viene aggiunto a nessuna barra degli strumenti (o altra barra dei comandi, per quella materia)?


Se pensi che la mia risposta funzionerebbe per te se la barra dei comandi funzionasse come pubblicizzato, forse aggiungi un tag "bug" alla tua domanda. La biancheria sporca mostrata in pubblico è spesso una buona motivazione per un fornitore per correggere un bug.
Kirk Kuykendall,

@Kirk, stavo per farlo, ma non posso - Non ho abbastanza rango qui per creare nuovi tag e bugnon sembra esistere ancora; non esitate a modificare i tag da soli.
stakx,

Risposte:


7

Questo ha funzionato per me usando ArcGIS 10 SP1. Il mio strumento personalizzato non si trova su una barra degli strumenti:

    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 Se funziona, questo è sicuramente più semplice della risposta che ho pubblicato. Sono abbastanza sicuro di averlo provato, ma da allora ho installato SP1, quindi forse è stato un fattore.
Kirk Kuykendall,

La risposta di lbross mi ha aiutato molto. Successivamente ho trovato quasi la stessa soluzione nel cercatore di frammenti di ArcGis: "Dichiarazioni - Usa uno strumento in un frammento di Windows Form" (sto usando C #) Non posso votare la risposta perché ho una reputazione troppo bassa.
dpalmetz,

Non posso votare o aggiungere commenti perché non ho abbastanza reputazione, ma la risposta di lbross funziona per me in ArcGIS 10.2. Ho creato un ITool senza barra degli strumenti e l'ho chiamato da un pulsante Windows Víctor
vaparicio

3

Non l'ho mai provato, ma sembra che dovrebbe funzionare: nella tua forma non modale hai due variabili membro, la prima (m_Tool) che fa riferimento a ITool e la seconda (m_Application) che fa riferimento a IApplication. Nel costruttore del modulo non modale, fai istanziare ITool e chiama OnCreate , passando un riferimento IApplication.

Sul tuo modulo non modale hai un pulsante che, quando si fa clic, imposta m_Application. CurrentTool = m_Tool. Inoltre, invece di fare una finestra di dialogo non modale, consiglierei di usare una finestra agganciabile, magari usando WPF al suo interno .

Aggiornamento Nel tentativo di espiare per aver pubblicato questa risposta scadente, ho cercato di hackerare qualcosa insieme. Sembra che dovresti essere in grado di creare dinamicamente una barra degli strumenti, nasconderla, aggiungere lo strumento ad essa (ottenere un ICommandItem da impostare su CurrentTool), quindi eliminare la barra degli strumenti senza che l'utente abbia mai saputo che lo strumento era su una barra degli strumenti. Tuttavia, ICommandBar.Dock e ICommandItem.Delete non sembrano funzionare con toobar dinamici. IMHO questo è un bug.

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
Questo non funzionerà, poiché la proprietà CurrentTool prevede un ICommandItem. I riferimenti ICommandItem non possono essere creati direttamente, ma possono essere recuperati solo tramite ICommandBars.
Petr Krebs,

Esattamente a proposito di currenttool, ma ICommandbar.Add crea un ICommandItem da un UID. Il problema diventa quindi come sbarazzarsi della barra dei comandi dopo che non è più necessario (o almeno nasconderlo).
Kirk Kuykendall l'

wow, grazie per aver aggiunto un esempio di codice funzionante nel tuo aggiornamento. E 'un peccato che né DockDeleteil lavoro, ma è un buon inizio. Esaminerò Deleteulteriormente il problema, penso.
stakx

che idea interessante, proverò sicuramente a elaborarlo. Tra l'altro credo anche che il comportamento che descrivi sia un bug.
Petr Krebs

Ho finito per usare una soluzione diversa (tra le altre cose, rendendo il mio strumento un Singleton in modo da poter facilmente ottenere un riferimento ad esso; il CommandBars.Findproblema si è improvvisamente risolto da solo, per qualche motivo sconosciuto), ma sto dando a questa risposta il segno di spunta segno perché questo è probabilmente quello che avrei fatto.
stakx,

3

Non so perché è necessario aggiungere lo strumento in una barra degli strumenti. Perché, ho lavorato con qualcosa di simile e non ho trovato alcun bisogno di aggiungerlo nella barra degli strumenti.

Nel mio caso, quando l'utente fa clic su un pulsante nella finestra agganciabile, si attiva uno strumento. Per eseguire questo lavoro, la mia classe di strumenti ha il seguente aspetto:

  • Il mio ID strumento è: "ArcMap_SelectionTool"
  • Il nome della mia classe di strumenti è: "SelectionTool"
  • Mantenere un campo statico di tipo utensile nella classe utensile

    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
    }

Quindi, ogni volta che devo istanziare questo strumento, lo chiamo nel modo seguente:

        var toolInstance = SelectionTool.Instance;

Dopo aver lavorato con lo strumento, devo uscire dall'istanza dello strumento. Quindi chiamo SelectionTool.ExitToolInstance()metodo.

Questa procedura funziona bene per me.


1

Di solito lo risolvo rendendo il comando (OpenModelessDialogCommand nel tuo caso) anche uno strumento ( ITool). Facendo clic sul comando, apro il modulo. Quindi posso anche attivarlo come strumento in qualsiasi momento.

Se lo strumento che si desidera attivare non è il proprio, è possibile inoltrare le chiamate dal proprio ITool (implementato come sopra) all'altra istanza dello strumento.


0

Se si ha accesso all'oggetto mappa, è possibile eseguire molti strumenti eseguendo una chiamata a onCreate inviando ad esempio l'oggetto MapControl per collegarlo alla mappa. Successivamente è solo per eseguire il metodo onClick.

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

Non lavorare su tutti gli strumenti ESRI perché alcuni devono essere aggiunti a una barra degli strumenti.


Come posso ottenere un riferimento a tale oggetto mappa? Tutto quello che riesco a ottenere è IMapun'interfaccia IMxDocument, ma chiaramente non è la stessa cosa, vero?
stakx,

Modifica: in Desktop è l'IApplication che è l'oggetto hook: help.arcgis.com/en/sdk/10.0/arcobjects_net/conceptualhelp/…
MathiasWestin

scusa, ci ho provato; non funziona. Il problema qui è che lo strumento viene creato, ma non viene mai attivato. Secondo, non vedo ancora come riuscire a ottenere un MapControloggetto (se ne ho davvero bisogno) attraverso IApplicationo qualsiasi oggetto raggiungibile da lì.
stakx,

Dovresti passare IApplication a OnCreate quando lo fai in Desktop, se non sto leggendo male la documentazione. L'invio in un oggetto MapControl funziona per me in Engine.
MathiasWestin,

sembra corretto che passiate un IApplicationoggetto a OnCreate- ma questo non è sufficiente (almeno non per il mio strumento personalizzato), perché lo strumento non viene attivato da OnCreate, e quindi non riceverà alcun evento di input.
stakx,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.