1. 程式人生 > >ArcEngine10.2設計與開發課程學習(作業二)——基本應用程式生成,右擊選單實現:顯示、移除和開啟屬性表功能

ArcEngine10.2設計與開發課程學習(作業二)——基本應用程式生成,右擊選單實現:顯示、移除和開啟屬性表功能

前言:這裡是我的筆記本

目錄:

  • 準備工作——工具方法等
  • 程式碼

 

首先說明一下第一個作業,這是第二個的連結:https://pan.baidu.com/s/1NziPHoMEJx0vc8DCNrX-dA提取碼:qpee 看的時候希望能夠靜下心來看,不要著急,不然略過了資訊可能後面程式碼看不懂,我的初衷是希望能夠通過以下準備工作和理論講解加深對我窗體工作的理解,急不得,有問題可留言啊,我儘量回覆,畢竟程式碼內容有很多問題,還有錯別字啥的hh,別介意。

  • 程式碼為同學我的所有程式碼,但是完成度並非100%,一些小的改動和功能新增可以自行增補,而且帶有個人習慣,所以重在屬性功能;另外,同學我用的是10.2 + VS2012的環境,不同的版本應該有差異,雖然我這裡測試無誤,但是我不能保證其他人賦值貼上過去後也能正常執行;
  • 還有一點想強調一下,在開始寫程式碼之前,準備工作不能落下,包括使用,嵌入操作,控制元件的命名,屬性的設定,新增mapcontrol,lincensecontrol等等,可以省去一些不必要的麻煩。

第一個文章寫的很爛,對於沒有C#和窗體基礎的同學可能較為吃力,但這個沒辦法啦,這是我的筆記本而已。大早爬起來終於把第二個寫好了,現在寫點總結。第一個作業的基礎之後大致熟悉了窗體的基本操作,基本空間的使用,基本設定等等,如果沒有,可以找一些視訊或者自己看看書熟悉一下。

第二個作業實現的功能

EX03 * 關係編寫程式,顯示地圖座標,工具條命令提示資訊,並移除圖層。

  1. 在狀態列顯示地圖中滑鼠當前位置的座標資訊(地圖控制元件的的的OnMouseMove)。
  2. 在狀態列顯示工具條命令的提示資訊(ToolbarControl的的的OnMouseMove,的的HitTest)。

在TOCControl的圖層上按滑鼠右鍵,移除該圖層(TOCControl的onmousedown事件事件,的的HitTest)

生成初始介面(帶工具條);

  1. 滑鼠移動顯示座標和工具狀態資訊;
  2. 右擊選單實現;
  3. 右擊選單中刪除圖層功能和AttributeTable開啟功能。
    功能
    標題

     


本次作業使用到的工具和方法,需瞭解,不若不易理解後續程式碼:

  1. arcEngine控制元件:MapControl,ToolbarControl,TOCControl(目錄樹),LicenseControl,中間兩個不能夠單獨使用,必須與夥伴控制元件一起使用,所以在使用時我們需要將它們繫結到mapControl或頁面...... .ToolbarControl繫結之後,我們就可以通過工具條對“夥伴控制元件”進行訪問操作;同理,TOCControl可以用來顯示“夥伴”的地圖,圖層,符號系統等內容的互動式檢視→當在TOC中刪除,隱藏圖層時,地圖控制元件中也會相應移除,不可見。
  2. 基本控制元件的常用屬性,由於初始不熟悉,這裡補充一下很多都是可以望文生義的屬性,同時點選之後會有相應的功能描述,如下圖所示:常用的碼頭,設定控制元件在窗體中的位置,文字文字顯示等。
  3. 本次我用了stateStrip控制元件和的ContextMenuStrip,toolStripContainer,textBox中(可以直接在左側工具欄搜尋),也可以使用其他控制元件實現相同的功能,看個人習慣。至於這些功能基本的使用,可自行百度。這幾個控制元件都比較搞,為了顯示好還需要這幾個設定位於頂層或者底層才行,忘記了,總之不要把地圖控制元件下部分蓋住。

  • 引用的類庫:

使用ESRI.ArcGIS.esriSystem;必須
使用ESRI.ArcGIS.Carto;必須
使用ESRI.ArcGIS.Controls;
使用ESRI.ArcGIS.SystemUI;
使用ESRI.ArcGIS.Geodatabase; //必須

非全部必須,具體使用可隨時新增,這裡地理資料庫初始可能找不到,按下圖所示方法查詢即可:

  • 說明函式https://blog.csdn.net/haizhongliangji/article/details/43955627
  • public void HitTest(int X,int Y,ref esriTOCControlItem ItemType,ref IBasicMap BasicMap,ref ILayer 

    Layer,ref object Unk,ref object Data);
    各引數的含義如下:
    X,Y:滑鼠點選的座標;
    ITemType:esriTOCControlItem列舉常量
    BasicMap:繫結MapControl的IBasicMap介面
    層:被點選的圖層
    Unk:TOCControl的LegendGroup物件
    資料:LegendClass在LegendGroup中的索引
    .esriTOCControlItem列舉常量用於描述TocControl上的專案的型別,其定義如下:
    esriTOCControlItemNone 0沒有物件
    esriTOCControlItemMap 1地圖物件
    esriTOCControlItemLayer 2圖層物件
    esriTOCControlItemHeading 3物件的標題
    esriTOCControlItemLegendClass 4 LegendClass物件

這裡我個人理解的為繫結TOC和地圖控制元件後通過該函式來判斷滑鼠所處的位置,還有其他的功能但本次未用到。

C#幾個經常用到的字串擷取,因為顯示的欄位型別還有一些單位,比如Meters會是esriMeters,Polyline則為esriGeometryPolyline,所以我用到了字元創擷取功能:https://www.cnblogs.com /lykbk/archive/2012/06/28/lyk1232132.html

如圖1所示,取字串的前我個字元

(1)string str1 = str.Substring(0,i);

(2)string str1 = str.Remove(i,str.Length -i);

2,去掉字串的前我個字元

string str1 = str.Remove(0,i);

string str1 = str.SubString(i);

3,從右邊開始取我個字元:

string str1 = str.SubString(str.Length -i);

string str1 = str.Remove(0,str.Length -i);

如圖4所示,從右邊開始去掉我個字元:

string str1 = str.Substring(0,str.Length -i);

string str1 = str.Remove(str.Length-i,i);

5,如果字串中有“abc”則替換成“ABC”
   str = str.Replace(“abc”,“ABC”);

6,C#擷取字串最後一個字元的問題!!!!!!!!!!!!!!!!!!!!

str1.Substring(str1.LastIndexOf( “”)+ 1);

7,C#擷取字串最後一個字元

k = k.Substring(k.Length-1,1);


還有就是基本窗體怎麼生成的問題,就是自帶工具條的那個,這裡就不多此一舉了,這裡看http://zhihu.esrichina.com.cn/?/article/535與兩種方法,我參考的的是它的第二種方式;這位前輩知乎上的教程不錯,有6章,都可以看看。但是有些程式碼拿過來還是有錯HH,需要自己除錯

生成之後新增工具如果不能使用(灰色的)需要注意,TolllBarControl繫結地圖控制元件新增工具應該選擇nevigatemap裡的好像是這個才會生效,有的是針對頁......這個同學我也還沒去了解

http://zhihu.esrichina.com.cn/article/537這的英文右擊選單生成的方法,也是上面前輩的

還有選擇控制元件時如果覆蓋點不到,可以右擊選擇,就像圖層一樣也可以直接點下方的控制元件名稱。


準備工作時很重要的,下面基本開始羅列程式碼了,再次宣告,僅供參考!!!程式碼是使用CSDN編輯器C#選項,應該可複製。

程式碼

這是筆者的介面,下面是各個部分的程式碼,因為部分自行改了控制元件的名稱屬性,可能不一致。

1,滑鼠移動在地圖上時,顯示相關資訊

        private void axMapControl1_OnMouseMove(object sender, ESRI.ArcGIS.Controls.IMapControlEvents2_OnMouseMoveEvent e)
        {
            string path = axMapControl1.DocumentFilename;
            mapx.Text = "X:" + e.mapX.ToString("0.00");
            mapy.Text = "Y:" + e.mapY.ToString("0.00");
            //或者toolStripStatusLabel1.Text = Math.Round(e.mapX, 2).ToString();
            mapunits.Text = this.axMapControl1.MapUnits.ToString().Remove(0,4);
            //string str1 = str.Remove(0, i);
            //string str1 = str.SubString(i);

            textBox1.Text = "比例尺   1:" + ((long)this.axMapControl1.MapScale).ToString();
        }

2,滑鼠移動至工具條工具時,顯示工具資訊(索引初始索引為-1)

        private void axToolbarControl1_OnMouseMove(object sender, ESRI.ArcGIS.Controls.IToolbarControlEvents_OnMouseMoveEvent e)
        {
             //取得滑鼠所在工具的索引號
            int index = axToolbarControl1.HitTest(e.x, e.y, false);
            if (index != -1)
            {
                toolinfo.Text = axToolbarControl1.GetItem(index).Command.Message;
            }
          //toolinfo為我自己改的控制元件名,原來是statelable1,就是那個statestrip的子選單
            else
            {
                toolinfo.Text = "就緒";
            }
        }

3,右擊選單的實現,全域性變數的設定就是因為前面講到的幾控制元件之間的關聯關係

        //右擊選單的實現
        public ILayer pLayer;
        private void axTOCControl1_OnMouseDown(object sender, ITOCControlEvents_OnMouseDownEvent e)
        {
            esriTOCControlItem pItem = new esriTOCControlItem();
            pLayer = new FeatureLayerClass();
            IBasicMap pBasicMap = new MapClass();
            object pUnk = new object();
            object pData = new object();
            //例項化HITtest中的後五個引數
            axTOCControl1.HitTest(e.x, e.y, ref pItem, ref pBasicMap, ref pLayer, ref pUnk, ref pData); //呼叫函式

            if (e.button == 2 && pItem == esriTOCControlItem.esriTOCControlItemLayer)
            //e.button=2代表滑鼠右擊,=1則是單擊左鍵,pItem=...表示圖層
            {
                contextMenuStrip1.Show(axTOCControl1, new Point(e.x, e.y));
            }//如果點選的是圖層,則彈出右擊選單
        }

4,圖層移除功能實現

        private void removeLayerToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (axMapControl1.LayerCount > 0)
            {
                if (pLayer != null)
                {
                    axMapControl1.Map.DeleteLayer(pLayer);
                }
            }
        }

5,屬性表功能實現,需要在這個專案裡新建一個窗體,感覺比較複雜,直接擺出供參考

        //屬性表窗體連線並顯示
        private void openAtriiToolStripMenuItem_Click(object sender, EventArgs e)
        {
            AttributeTable pAttributeTable = new AttributeTable(pLayer as IFeatureLayer);
            pAttributeTable.Show();
        }

5.1,的dataGridView控制元件需要用於顯示屬性表,同時還需要設定屬性時全域性顯示,沒記錯應該是AutoSizeColumnsMode,行兩個,下面是程式碼,詳情略

public partial class AttributeTable : Form
    {
        private IFeatureLayer pFeatureLayer = null;
        public AttributeTable(IFeatureLayer _FeatureLayer)
        {
            InitializeComponent();
            pFeatureLayer = _FeatureLayer;
        }

        private void AttributeTable_Load(object sender, EventArgs e)
        {
            
            IFields pFields;  
            pFields = pFeatureLayer.FeatureClass.Fields;//連線屬性表的列

            dataGridView1.ColumnCount = pFields.FieldCount;
            for (int i = 0; i < pFields.FieldCount; i++)
            {
                string fldName = pFields.get_Field(i).Name;//欄位名
                dataGridView1.Columns[i].Name = fldName;
                dataGridView1.Columns[i].ValueType = Type.GetType(ParseFieldType(pFields.get_Field(i).Type));
                //列名和值型別
            }

            IFeatureCursor pFeatureCursor;//定義遊標/指標
            pFeatureCursor = pFeatureLayer.FeatureClass.Search(null, false);

            IFeature pFeature;
            pFeature = pFeatureCursor.NextFeature();

            while (pFeature != null)
            {
                string[] fldValue = new string[pFields.FieldCount];
                for (int i = 0; i < pFields.FieldCount; i++)
                {
                    string fldName;
                    fldName = pFields.get_Field(i).Name;
                    //下程式碼判斷是數值型別還是幾何型別欄位
                    if (fldName == pFeatureLayer.FeatureClass.ShapeFieldName)
                    {
                        fldValue[i] = pFeature.Shape.GeometryType.ToString().Remove(0,12);
                    }
                    else
                        fldValue[i] = pFeature.get_Value(i).ToString();
                }
                dataGridView1.Rows.Add(fldValue);//寫入行值
                pFeature = pFeatureCursor.NextFeature();
            }

        }
        private string ParseFieldType(esriFieldType TableFieldType)
        {
            switch (TableFieldType)
            {
                case esriFieldType.esriFieldTypeBlob:
                    return "System.String";
                case esriFieldType.esriFieldTypeDate:
                    return "System.DateTime";
                case esriFieldType.esriFieldTypeDouble:
                    return "System.Double";
                case esriFieldType.esriFieldTypeGeometry:
                    return "System.String";
                case esriFieldType.esriFieldTypeGlobalID:
                    return "System.String";
                case esriFieldType.esriFieldTypeGUID:
                    return "System.String";
                case esriFieldType.esriFieldTypeInteger:
                    return "System.Int32";
                case esriFieldType.esriFieldTypeOID:
                    return "System.String";
                case esriFieldType.esriFieldTypeRaster:
                    return "System.String";
                case esriFieldType.esriFieldTypeSingle:
                    return "System.Single";
                case esriFieldType.esriFieldTypeSmallInteger:
                    return "System.Int32";
                case esriFieldType.esriFieldTypeString:
                    return "System.String";
                default:
                    return "System.String";
            }
        }
    }

程式碼就到這裡結束了,但是可能還是會遇到很多問題,我也深有體會HH感謝你看完了,有需要的留言,我可以奉上我的EXE檔案 - 可執行程式,部落格可以修改這點是真的好用,當筆記本不錯,下面是我的效果圖(這個比例尺是可以直接新增的工具,我一開始沒找到,就懶得改了,添加了比例尺工具就可以把我這裡的關程式碼去除了):

吃飯去,加關注交流hhhhhhhhhhhhhhh