เปิดใช้งาน ITool ที่กำหนดเองจากแบบฟอร์มโดยไม่ต้องเพิ่มลงในแถบเครื่องมือ ArcMap AddIn?


11

ฉันกำลังทำงานกับ Add-in สำหรับ ArcMap 10.0 ที่เพิ่มแถบเครื่องมือให้กับ ArcMap OpenModelessDialogCommandปุ่มคำสั่ง ( ) หนึ่งปุ่มบนแถบเครื่องมือนั้นจะเปิดกล่องโต้ตอบ 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นี้ปรากฏอยู่ในแถบคำสั่ง (เช่นแถบเครื่องมือ) ของ Add-in ของฉัน แต่นั่นไม่ใช่กรณี ดังนั้นฉันได้ลองสิ่งต่อไปนี้แล้ว:

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

ฉันได้มองหาการเพิ่มสิ่งที่มองไม่เห็นAxToolbarControlในแบบฟอร์มของฉันและเพิ่มปุ่มสำหรับสิ่งMyToolนั้น แต่แล้วฉันพบปัญหาเกี่ยวกับวิธีการเชื่อมต่อแถบเครื่องมือนั้น (ผ่านSetBuddyControl) เข้ากับแผนที่ของเอกสารที่เปิดอยู่ ฉันไม่ต้องการให้เครื่องมือทำงานแยกกันAxMapControlฉันต้องการให้มันทำงานโดยตรงกับแผนที่หลักที่แสดงใน ArcMap

คำถาม:
ฉันจะเปิดใช้งานเครื่องมือแบบกำหนดเองที่ไม่ได้เพิ่มลงในแถบเครื่องมือใด ๆ (หรือแถบคำสั่งอื่นสำหรับเรื่องนั้นได้อย่างไร)


หากคุณคิดว่าคำตอบของฉันจะใช้งานได้หาก commandbar ทำงานตามที่โฆษณาไว้อาจเพิ่มแท็ก "ข้อบกพร่อง" ในคำถามของคุณ ผ้าสกปรกที่ปรากฏในที่สาธารณะมักเป็นแรงจูงใจที่ดีสำหรับผู้ขายในการแก้ไขข้อบกพร่อง
Kirk Kuykendall

@ 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 ไว้แล้วดังนั้นอาจเป็นปัจจัย
Kirk Kuykendall

คำตอบของ lbross ช่วยฉันได้มาก ต่อมาฉันพบวิธีแก้ปัญหาเดียวกันในเครื่องมือค้นหาตัวอย่าง ArcGis: 'งบ - ใช้เครื่องมือใน Windows Form.snippet' (ฉันใช้ C #) ฉันไม่สามารถโหวตคำตอบได้เพราะฉันมีชื่อเสียงน้อยเกินไป
dpalmetz

ฉันไม่สามารถลงคะแนนหรือเพิ่มความคิดเห็นได้เพราะฉันไม่มีชื่อเสียงเพียงพอ แต่คำตอบของ lbross นั้นเหมาะกับฉันใน ArcGIS 10.2 ฉันสร้าง ITool โดยไม่ใช้แถบเครื่องมือและเรียกมันจากปุ่ม Windows Víctor
vaparicio

3

ฉันไม่เคยลองสิ่งนี้ แต่ดูเหมือนว่ามันจะทำงานได้: ในรูปแบบที่ไม่มีการเปลี่ยนแปลงของคุณมีตัวแปรสมาชิกสองตัวตัวแรก (m_Tool) ที่อ้างอิง ITool ของคุณและตัวที่สอง (m_Application) ที่อ้างอิง IApplication ใน Constructor สำหรับแบบฟอร์ม modeless ของคุณให้สร้างอินสแตนซ์ ITool และเรียกOnCreateผ่านการอ้างอิง IApplication

ในรูปแบบที่ไม่ใช้งานของคุณมีปุ่มที่เมื่อคลิกชุด m_Application CurrentTool = m_Tool นอกจากนี้แทนการทำโต้ตอบสร้างผมขอแนะนำให้ใช้หน้าต่าง dockable อาจจะใช้ใช้ WPF ภายใน

อัปเดต ในความพยายามที่จะชดเชยการโพสต์คำตอบที่อ่อนแอนี้ฉันพยายามแฮ็กข้อมูลด้วยกัน ดูเหมือนว่าคุณควรจะสามารถสร้างแถบเครื่องมือแบบไดนามิกซ่อนมันเพิ่มเครื่องมือลงไป (รับ ICommandItem เพื่อตั้งค่าเป็น CurrentTool) จากนั้นลบแถบเครื่องมือโดยที่ผู้ใช้ไม่เคยรู้ว่าเครื่องมืออยู่บนแถบเครื่องมือ อย่างไรก็ตาม ICommandBar.Dock และ ICommandItem.Delete ดูเหมือนจะไม่ทำงานสำหรับ toobars แบบไดนามิก IMHO นี่เป็นข้อผิดพลาด

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 เท่านั้น
Petr Krebs

ค่อนข้างถูกต้องเกี่ยวกับ currenttool แต่ ICommandbar.Add สร้าง ICommandItem จาก UID ปัญหาก็จะกลายเป็นวิธีการกำจัด commandbar หลังจากที่มันไม่จำเป็นอีกต่อไป (หรือซ่อนอย่างน้อย)
Kirk Kuykendall

ว้าวขอบคุณที่เพิ่มตัวอย่างโค้ดที่ใช้งานได้ในการอัปเดตของคุณ มันเป็นความอัปยศที่ค่าDockมิได้Deleteทำงาน แต่มันเป็นจุดเริ่มต้นที่ดี ฉันจะตรวจสอบDeleteปัญหาต่อไปฉันคิดว่า
stakx

เป็นความคิดที่น่าสนใจอะไรฉันจะพยายามทำอย่างละเอียด Btw ฉันเชื่อว่าพฤติกรรมที่คุณอธิบายเป็นข้อผิดพลาด
Petr Krebs

ฉันลงเอยด้วยการใช้วิธีแก้ไขปัญหาที่แตกต่างกัน (เหนือสิ่งอื่นใดโดยการทำให้เครื่องมือของฉันเป็นแบบซิงเกิลเพื่อให้ฉันสามารถอ้างอิงได้อย่างง่ายดายCommandBars.Findปัญหาก็แก้ไขตัวเองด้วยเหตุผลที่ไม่ทราบสาเหตุ) แต่ฉันให้คำตอบเห็บนี้ ทำเครื่องหมายเพราะอาจเป็นสิ่งที่ฉันจะทำ
stakx

3

ฉันไม่รู้ว่าทำไมคุณต้องเพิ่มเครื่องมือในแถบเครื่องมือ เพราะฉันทำงานกับสิ่งที่คล้ายกันและฉันไม่ต้องการเพิ่มมันเข้าไปในแถบเครื่องมือ

ในกรณีของฉันเมื่อผู้ใช้คลิกที่ปุ่มในหน้าต่างที่ถอดออกได้เครื่องมือจะเปิดใช้งาน ในการทำงานนี้คลาสเครื่องมือของฉันมีลักษณะดังนี้:

  • รหัสเครื่องมือของฉันคือ: "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 ที่จะเชื่อมโยงมันเข้ากับแผนที่ หลังจากนั้นเพียงเพื่อเรียกใช้เมธอด 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
MathiasWestin

ดูเหมือนว่าถูกต้องที่คุณจะส่งIApplicationวัตถุไปOnCreate- แต่ไม่เพียงพอ (อย่างน้อยไม่ใช่เครื่องมือที่กำหนดเองของฉัน) เนื่องจากเครื่องมือไม่ได้เปิดใช้งานโดยOnCreateและจะไม่ได้รับเหตุการณ์อินพุตใด ๆ
stakx
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.