ArcMapアドインツールバーに追加せずにフォームからカスタムIToolをアクティブにしますか?


11

ツールバーをArcMapに追加するArcMap 10.0のアドインに取り組んでいます。OpenModelessDialogCommandそのツールバーの1つのコマンド()ボタンは、モードレス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ボタンビクトルからそれを呼ばれる
vaparicio

3

私はこれを試したことはありませんが、動作するはずです:モードレスフォームには2つのメンバー変数があります。最初の(m_Tool)はIToolを参照し、2番目(m_Application)はIApplicationを参照します。モードレスフォームのコンストラクターで、IToolをインスタンス化し、OnCreateを呼び出して、IApplication参照を渡します

モードレスフォームにはボタンがあり、クリックするとm_Applicationが設定されます。CurrentTool = m_Tool。また、モードレスダイアログを実行する代わりに、おそらくその中でWPF使用してドッキング可能なウィンドウを使用することをお勧めします。

更新 この下手な答えを投稿することをaうために、私は何かを一緒にハックしようとしました。ツールバーを動的に作成し、非表示にし、ツールを追加し(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はUIDからICommandItemを作成します。問題は、コマンドバーが不要になった(または少なくとも非表示にした)後、コマンドバーを削除する方法になります。
カーククイケンドール

更新に実際のコード例を追加していただきありがとうございます。仕事でもDockなければDelete仕事でもないのは残念ですが、良いスタートです。私はこのDelete問題をさらに詳しく調べます。
stakx

なんて面白いアイディアなのか、私は間違いなくそこから詳しく説明しようと思います。ちなみに、あなたが説明する動作はバグだと思います。
ペトルクレブス

私は別のソリューションを使用することになりました(とりわけ、ツールをシングルトンにして、簡単に参照できるようにしました; CommandBars.Find何らかの理由で問題が突然解決しました)が、この答えをチェックしていますこれはおそらく私がしたことだからです。
stakx

3

ツールをツールバーに追加する必要がある理由がわかりません。なぜなら、私はいくつかの類似したものを扱ってきたので、ツールバーに追加する必要性を見つけていないからです。

私の場合、ユーザーがドッキング可能なウィンドウのボタンをクリックすると、ツールがアクティブになります。この作業を実行するために、私のツールクラスは次のようになります。

  • 私のツールIDは:「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

マップオブジェクトにアクセスできる場合、たとえばMapControlオブジェクトを送信してマップに接続するonCreateを呼び出すことにより、多くのツールを実行できます。その後、onClickメソッドを実行するだけです。

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

一部のツールはツールバーに追加する必要があるため、すべてのESRIツールで動作しないでください。


このようなマップオブジェクトへの参照を取得するにはどうすればよいですか?私が得ることができるのは、IMapを介したインターフェースIMxDocumentだけですが、明らかにそれは同じではありませんか?
stakx

編集:それはフックオブジェクトであるIApplicationのデスクトップに:help.arcgis.com/en/sdk/10.0/arcobjects_net/conceptualhelp/...
MathiasWestin

申し訳ありませんが、私はこれを試しました。機能しません。ここでの問題は、ツールが作成されますが、アクティブ化されないことです。第二に、MapControlオブジェクト(実際に必要な場合)を取得しIApplicationたり、そこから到達可能なオブジェクトを取得する方法がまだわかりません。
stakx

ドキュメントを読み間違えていなければ、デスクトップでこれを行うときに、IApplicationをOnCreateに渡す必要があります。MapControlオブジェクトを送信すると、Engineで機能します。
マティアスウェスティン

IApplicationオブジェクトを渡すことは正しいようですがOnCreate、ツールはによってアクティブ化されずOnCreate、したがって入力イベントを受け取らないため、これは十分ではありません(少なくとも私のカスタムツールでは)。
stakx
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.