Kích hoạt ITool tùy chỉnh từ biểu mẫu mà không cần thêm nó vào thanh công cụ ArcMap AddIn?


11

Tôi đang làm việc với một bổ trợ cho ArcMap 10.0 có thêm thanh công cụ cho ArcMap. Một OpenModelessDialogCommandnút lệnh ( ) trên thanh công cụ đó sẽ mở hộp thoại WinForms không chế độ, từ đó MyToolcó thể kích hoạt một công cụ ( ) để chọn một tính năng trên bản đồ.

My Config.esriaddinxchứa các khai báo lệnh và thanh công cụ:

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

Những gì tôi đang gặp vấn đề là kích hoạt MyTooltrong biểu mẫu. Tất cả những gì tôi tìm thấy trên internet là các mẫu mã dọc theo dòng:

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

Tuy nhiên, điều này rõ ràng đòi hỏi phải MyToolthực sự xuất hiện trong một thanh lệnh (ví dụ: thanh công cụ) của bổ trợ của tôi. Nhưng đó không phải là trường hợp. Vì vậy, tôi đã thử điều này tiếp theo:

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

Tôi thậm chí đã xem xét thêm một hình vô hình AxToolbarControlvào biểu mẫu của mình và thêm một nút cho MyToolnó; nhưng sau đó tôi gặp vấn đề về cách kết nối thanh công cụ đó (thông qua SetBuddyControl) với bản đồ của tài liệu đã mở. Tôi không muốn công cụ hoạt động riêng biệt AxMapControl, tôi muốn nó hoạt động trực tiếp với bản đồ chính được hiển thị trong ArcMap.

Câu hỏi:
Làm cách nào để kích hoạt một công cụ tùy chỉnh không được thêm vào bất kỳ thanh công cụ nào (hoặc thanh lệnh khác, cho vấn đề đó)?


Nếu bạn nghĩ rằng câu trả lời của tôi sẽ có hiệu quả với bạn nếu thanh lệnh hoạt động như quảng cáo, có thể thêm thẻ "bug" vào câu hỏi của bạn. Giặt bẩn hiển thị ở nơi công cộng thường là động lực tốt cho một nhà cung cấp để sửa lỗi.
Kirk Kuykendall

@Kirk, tôi sẽ làm điều đó, nhưng tôi không thể - Tôi chưa có đủ thứ hạng ở đây để tạo thẻ mới và bugdường như chưa tồn tại; xin vui lòng tự chỉnh sửa các thẻ.
stakx

Câu trả lời:


7

Điều này làm việc cho tôi bằng ArcGIS 10 SP1. Công cụ tùy chỉnh của tôi không có trên thanh công cụ:

    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 Nếu điều này hoạt động, điều này chắc chắn đơn giản hơn câu trả lời tôi đã đăng. Tôi khá chắc chắn rằng tôi đã thử nó nhưng kể từ khi cài đặt SP1, vì vậy có lẽ đó là một yếu tố.
Kirk Kuykendall

Câu trả lời của lbross đã giúp tôi rất nhiều. Sau đó, tôi đã tìm thấy gần như cùng một giải pháp trong công cụ tìm đoạn trích ArcGis: 'Tuyên bố - Sử dụng Công cụ trong Windows Form.snippet' (Tôi đang sử dụng C #) Tôi không thể bỏ phiếu trả lời vì tôi quá ít tiếng tăm.
dpalmetz

Tôi không thể bỏ phiếu hoặc thêm nhận xét vì tôi không có đủ danh tiếng, nhưng câu trả lời của lbross đối với tôi trong ArcGIS 10.2. Tôi đã tạo một ITool mà không có thanh công cụ và gọi nó từ nút Windows Víctor
vaparermo

3

Tôi chưa bao giờ thử điều này, nhưng có vẻ như nó sẽ hoạt động: Ở dạng không mod của bạn có hai biến thành viên, biến thứ nhất (m_Tool) tham chiếu ITool của bạn và thứ hai (m_Application) tham chiếu IApplication. Trong hàm tạo cho biểu mẫu không mod của bạn, hãy khởi tạo ITool và gọi OnCreate , chuyển tham chiếu IApplication.

Trên biểu mẫu không mod của bạn có một nút mà khi nhấp vào sẽ đặt m_Application. Hiện tạiTool = m_Tool. Ngoài ra, thay vì thực hiện một hộp thoại không chế độ, tôi khuyên bạn nên sử dụng cửa sổ có thể gắn được có lẽ bằng cách sử dụng WPF trong đó .

Cập nhật Trong nỗ lực chuộc lỗi để đăng câu trả lời khập khiễng này, tôi đã cố gắng hack một cái gì đó cùng nhau. Có vẻ như bạn sẽ có thể tự động tạo một thanh công cụ, ẩn nó, thêm công cụ vào nó (lấy ICommandItem để đặt thành CurrentTool), sau đó xóa thanh công cụ mà không cần người dùng biết công cụ này trên thanh công cụ. Tuy nhiên, ICommandBar.Dock và ICommandItem.Delete dường như không hoạt động đối với các toobar động. IMHO đây là một lỗi.

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
Điều này sẽ không hoạt động, vì thuộc tính CurrentTool mong đợi một ICommandItem. Tham chiếu ICommandItem không thể được tạo trực tiếp, nhưng chỉ có thể được truy xuất thông qua ICommandBars.
Petr Krebs

Hoàn toàn đúng về currenttool, nhưng ICommandbar.Add tạo ICommandItem từ UID. Vấn đề sau đó trở thành làm thế nào để thoát khỏi thanh lệnh sau khi nó không còn cần thiết (hoặc ít nhất là ẩn nó).
Kirk Kuykendall

wow, cảm ơn vì đã thêm một ví dụ mã làm việc trong bản cập nhật của bạn. Thật xấu hổ khi cả hai đều Dockkhông Deletehoạt động, nhưng đó là một khởi đầu tốt. Tôi sẽ xem xét Deletevấn đề hơn nữa, tôi nghĩ.
stakx

Thật là một ý tưởng thú vị, tôi chắc chắn sẽ cố gắng xây dựng từ đó. Btw Tôi cũng tin rằng hành vi bạn mô tả là một lỗi.
Petr Krebs

Cuối cùng tôi đã sử dụng một giải pháp khác (trong số những thứ khác, bằng cách biến công cụ của tôi thành Singleton để tôi có thể dễ dàng tham khảo về nó; CommandBars.Findvấn đề đột nhiên tự giải quyết, vì một số lý do không rõ), nhưng tôi đưa ra câu trả lời này đánh dấu bởi vì đây có lẽ là những gì tôi sẽ làm
stakx

3

Tôi không biết tại sao bạn cần thêm công cụ vào thanh công cụ. Bởi vì, tôi đã làm việc với một số thứ tương tự và tôi không tìm thấy bất kỳ nhu cầu nào để thêm nó vào thanh công cụ.

Trong trường hợp của tôi, khi người dùng nhấp vào nút trong cửa sổ có thể gắn được, một công cụ sẽ kích hoạt. Để thực hiện công việc này, lớp công cụ của tôi trông như sau:

  • Id công cụ của tôi là: "ArcMap_SelectionTool"
  • Tên lớp công cụ của tôi là: "SelectionTool"
  • Giữ một trường tĩnh của loại công cụ trong lớp công cụ

    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
    }

Vì vậy, bất cứ khi nào tôi cần khởi tạo công cụ này, tôi gọi nó theo cách sau:

        var toolInstance = SelectionTool.Instance;

Sau khi làm việc với công cụ, tôi cần thoát ví dụ công cụ. Thế là tôi gọi SelectionTool.ExitToolInstance()phương thức.

Thủ tục này hoạt động tốt cho tôi.


1

Tôi thường giải quyết điều này bằng cách tạo lệnh (OpenModlessDialogCommand trong trường hợp của bạn) cũng là một công cụ ( ITool). Khi bấm vào lệnh, tôi mở biểu mẫu. Sau đó tôi cũng có thể kích hoạt nó như một công cụ bất cứ lúc nào.

Nếu công cụ bạn muốn kích hoạt không phải là của riêng bạn, bạn có thể chuyển tiếp các cuộc gọi từ ITool (được triển khai như trên) sang phiên bản công cụ khác.


0

Nếu bạn có quyền truy cập vào đối tượng bản đồ, nhiều công cụ có thể được chạy bằng cách thực hiện cuộc gọi đến onCreate gửi ví dụ như đối tượng MapControl để nối nó lên bản đồ. Sau đó, chỉ chạy phương thức onClick.

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

Không hoạt động trên tất cả các công cụ ESRI vì một số cần phải thêm vào thanh công cụ.


Làm thế nào tôi có thể tham chiếu đến một đối tượng bản đồ như vậy? Tất cả những gì tôi có thể nhận được là một IMapgiao diện thông qua IMxDocument, nhưng rõ ràng điều đó không giống nhau, phải không?
stakx

Chỉnh sửa: ở Desktop đó là IApplication đó là đối tượng móc: help.arcgis.com/en/sdk/10.0/arcobjects_net/conceptualhelp/...
MathiasWestin

xin lỗi, tôi đã thử nó nó không hoạt động. Vấn đề ở đây là công cụ được tạo, nhưng không bao giờ được kích hoạt. Thứ hai, tôi vẫn không thấy làm thế nào tôi có thể có được một MapControlđối tượng (nếu tôi thực sự cần một thứ) thông qua IApplicationhoặc bất kỳ đối tượng nào có thể tiếp cận từ đó.
stakx

Bạn nên chuyển giao IApplication cho OnCreate khi thực hiện việc này trong Desktop, nếu tôi không đọc sai tài liệu. Gửi trong một đối tượng MapControl hoạt động cho tôi trong Engine.
MathiasWestin

có vẻ đúng là bạn sẽ chuyển một IApplicationđối tượng đến OnCreate- nhưng điều đó không đủ (ít nhất là không phải cho công cụ tùy chỉnh của tôi), bởi vì công cụ không được kích hoạt bởi OnCreatevà do đó sẽ không nhận được bất kỳ sự kiện đầu vào nào.
stakx
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.