¿Activar ITool personalizado desde el formulario sin agregarlo a la barra de herramientas de ArcMap AddIn?

11

Estoy trabajando en un complemento para ArcMap 10.0 que agrega una barra de herramientas a ArcMap. Un OpenModelessDialogCommandbotón de comando ( ) en esa barra de herramientas abre un cuadro de diálogo WinForms sin modo, desde el cual MyToolse puede activar una herramienta ( ) para, por ejemplo, seleccionar una función en el mapa.

My Config.esriaddinxcontiene estas declaraciones de comandos y barras de herramientas:

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

Lo que tengo problemas es activar MyToolen el formulario. Todo lo que he encontrado en Internet son ejemplos de código a lo largo de las líneas de:

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

Sin embargo, esto aparentemente requiere que MyToolrealmente aparezca en una barra de comandos (por ejemplo, barra de herramientas) de mi complemento. Pero ese no es el caso. Entonces, probé esto a continuación:

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

Incluso he buscado agregar un invisible AxToolbarControla mi formulario y agregar un botón para MyToolallí; pero luego me encuentro con problemas sobre cómo conectar esa barra de herramientas (vía SetBuddyControl) al mapa del documento abierto. No quiero que la herramienta funcione por separado AxMapControl, quiero que funcione directamente con el mapa principal que se muestra en ArcMap.

Pregunta:
¿Cómo activo una herramienta personalizada que no se agrega a ninguna barra de herramientas (u otra barra de comandos, para el caso)?

stakx
fuente
Si cree que mi respuesta funcionaría para usted si la barra de comandos funcionara como se anuncia, quizás agregue una etiqueta de "error" a su pregunta. La ropa sucia que se muestra en público suele ser una buena motivación para que un proveedor repare un error.
Kirk Kuykendall
@ Kirk, iba a hacer eso, pero no puedo, no tengo suficiente rango aquí para crear nuevas etiquetas, y bugparece que todavía no existe; por favor, siéntase libre de editar las etiquetas usted mismo.
stakx

Respuestas:

7

Esto funcionó para mí usando ArcGIS 10 SP1. Mi herramienta personalizada no está en una barra de herramientas:

    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
fuente
1
+1 Si esto funciona, seguro que es más simple que la respuesta que publiqué. Estoy bastante seguro de que lo intenté, pero desde entonces instalé SP1, así que tal vez fue un factor.
Kirk Kuykendall
La respuesta de lbross me ayudó mucho. Más tarde, encontré casi la misma solución en el buscador de fragmentos de ArcGis: 'Declaraciones: use una herramienta en un Windows Form.snippet' (estoy usando C #) No puedo votar la respuesta porque tengo muy poca reputación.
dpalmetz
No puedo votar ni agregar comentarios porque no tengo suficiente reputación, pero la respuesta de lbross me funciona en ArcGIS 10.2. Creé un ITool sin una barra de herramientas y lo llamé desde un botón de Windows Víctor
vaparicio
3

Nunca he intentado esto, pero parece que debería funcionar: en su forma no modal, tenga dos variables miembro, la primera (m_Tool) haciendo referencia a su ITool y la segunda (m_Application) haciendo referencia a la aplicación IA. En el constructor de su forma no modal, haga que cree una instancia de ITool y llame a OnCreate , pasando una referencia de aplicación IA.

En su forma sin modo, tenga un botón que, cuando se hace clic, establece m_Application. CurrentTool = m_Tool. Además, en lugar de hacer un diálogo sin modo, recomendaría usar una ventana acoplable, quizás usando WPF dentro de ella .

Actualización En un intento de expiar por publicar esta respuesta tonta, he intentado piratear algo juntos. Parece que debería poder crear dinámicamente una barra de herramientas, ocultarla, agregarle la herramienta (obtener un ICommandItem para configurar CurrentTool) y luego eliminar la barra de herramientas sin que el usuario sepa que la herramienta estaba en una barra de herramientas. Sin embargo, ICommandBar.Dock e ICommandItem.Delete no parecen funcionar para las barras dinámicas. En mi humilde opinión esto es un error.

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
fuente
1
Esto no funcionará, ya que la propiedad CurrentTool espera un ICommandItem. Las referencias ICommandItem no se pueden crear directamente, pero solo se pueden recuperar a través de ICommandBars.
Petr Krebs
Muy bien sobre currenttool, pero ICommandbar.Add crea un ICommandItem desde un UID. El problema se convierte en cómo deshacerse de la barra de comandos después de que ya no sea necesaria (o al menos ocultarla).
Kirk Kuykendall
wow, gracias por agregar un ejemplo de código de trabajo en su actualización. Es una pena que Dockni Deletefuncione, pero es un buen comienzo. Seguiré investigando el Deletetema, creo.
stakx
qué idea interesante, definitivamente intentaré elaborar a partir de eso. Por cierto, también creo que el comportamiento que describe es un error.
Petr Krebs
Terminé usando una solución diferente (entre otras cosas, haciendo de mi herramienta un Singleton para que pueda obtener fácilmente una referencia; el CommandBars.Findproblema se resolvió de repente, por alguna razón desconocida), pero le doy a esta respuesta la señal marca porque esto es probablemente lo que habría hecho.
stakx
3

No sé por qué necesita agregar la herramienta en una barra de herramientas. Porque, he trabajado con algo similar y no he encontrado la necesidad de agregarlo en la barra de herramientas.

En mi caso, cuando el usuario hace clic en un botón en la ventana acoplable, se activa una herramienta. Para realizar este trabajo, mi clase de herramienta tiene el siguiente aspecto:

  • Mi ID de herramienta es: "ArcMap_SelectionTool"
  • El nombre de mi clase de herramienta es: "SelectionTool"
  • Mantenga un campo estático de tipo de herramienta en la clase de herramienta

    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
    }

Entonces, cada vez que necesito crear una instancia de esta herramienta, la llamo de la siguiente manera:

        var toolInstance = SelectionTool.Instance;

Después de trabajar con la herramienta, necesito salir de la instancia de la herramienta. Entonces llamo SelectionTool.ExitToolInstance()método.

Este procedimiento funciona bien para mí.

Emi
fuente
1

Por lo general, resuelvo esto haciendo que el comando (OpenModelessDialogCommand en su caso) también sea una herramienta ( ITool). Al hacer clic en el comando, abro el formulario. Entonces también puedo activarlo como herramienta en cualquier momento.

Si la herramienta que desea activar no es la suya, puede retransmitir llamadas desde su ITool (implementado como se indicó anteriormente) a la otra instancia de la herramienta.

Petr Krebs
fuente
0

Si tiene acceso al objeto de mapa, se pueden ejecutar muchas herramientas llamando a onCreate enviando, por ejemplo, el objeto MapControl para conectarlo al mapa. Después de eso es solo para ejecutar el método onClick.

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

No trabaje en todas las herramientas de ESRI porque algunas deben agregarse a una barra de herramientas.

MathiasWestin
fuente
¿Cómo obtendría una referencia a dicho objeto de mapa? Todo lo que puedo parecer es una IMapinterfaz IMxDocument, pero claramente eso no es lo mismo, ¿verdad?
stakx
Editar: en Desktop, la aplicación IA es el objeto de enlace
MathiasWestin
lo siento, intenté esto; No funciona. El problema aquí es que la herramienta se crea, pero nunca se activa. En segundo lugar, todavía no veo cómo podría MapControlatravesar un objeto (si es que realmente necesito uno) IApplicationo cualquier objeto accesible desde allí.
stakx
Debería pasar la aplicación IA a OnCreate al hacer esto en el escritorio, si no estoy leyendo mal la documentación. Enviar un objeto MapControl funciona para mí en Engine.
MathiasWestin
parece correcto que pasaría un IApplicationobjeto OnCreate, pero eso no es suficiente (al menos no para mi herramienta personalizada), porque la herramienta no se activa OnCreatey, por lo tanto, no recibirá ningún evento de entrada.
stakx