Tuesday, 29 May 2012

ArcObject.. customize ArcMap interface

Adakah anda seorang programmer?? Kalau bukan programmer pun tak apa, tapi berminat tak nak ubah sikit-sikit interface ArcMap anda, maybe nak buat custom menu ke, custom button ke. Kali ini saya akan terangkan serba sedikit mengenai konsep customize interface di dalam ArcGIS.

Sebelum itu saya bagi dulu pengenalan serba sedikit tentang ArcObject. Perisian ArcGIS Desktop anda dibina on top of ArcObject dimana ArcObject ni terdiri dari beberapa set of classes yang ditulis oleh programmer ESRI menggunakan pengaturcaraan C++. Bagaimana ianya disimpan di dalam ArcGIS? Ianya disimpan di dalam fail-fail DLL apabila anda install ArcGIS Desktop anda. Kalau sesiapa yang pernah belajar Object Oriented Programming tentu lebih mudah faham tentang apa yang saya maksudkan ni. 

Bagaimana kita nak programkan ArcGIS desktop kita menggunakan ArcObject classes ini? Anda boleh menggunakan pelbagai bahasa pengaturcaraan, antaranya VB, VBA, C++, C# dan .NET. Bermula dari versi ArcGIS 10, ESRI mencadangkan agar persekitaran .NET digunakan kerana mereka tidak akan support VB/VBA apabila versi 10.1 muncul kelak. Tetapi untuk memudahkan anda memahami konsep customization ArcObject, saya akan menggunakan contoh menggunakan VBA kerana VBA Editor memang telah sedia ada di dalam ArcMap versi ArcGIS10 dan juga versi 9.x.

Untuk buka VBA Editor ni, anda klik sahaja pada menu Customize > VBA Macros > Visual Basic Editor di dalam ArcMap.


Penerangan mengenai komponen-komponen di dalam VBA Editor adalah seperti di bawah.

Di dalam contoh ini, saya akan membina satu form yang berfungsi untuk melaksanakan proses carian nama sungai di atas peta saya. Untuk membina form di dalam VBA Editor, right click di dalam ruangan Project (rujuk rajah di atas untuk ruangan Project), kemudian pilih sahaja Insert > UserForm.
Kaedah membina Form

Secara default VBA Editor akan menamakan form anda sebagai UserForm1. Kemudian saya drag control ComboBox masuk ke dalam form saya. Ini akan bertindak sebagai dropdown box di dalam form saya yang akan menyenaraikan nama-nama sungai. Saya drag juga control CommandButton yang akan mencari nama sungai yang saya kehendaki di dalam ComboBox. Saya namakan CommandButton saya ini sebagai CARI.

                                         
                            Click/Drag control ComboBox dan CommandButton ke dalam form.
Kemudian saya double click di atas form saya untuk memaparkan ruangan Procedure. Seterusnya saya klik kepada Initialize (rujuk rajah di bawah).

Double click form dan pastikan anda tukar kepada Event Initialize pada Procedure.
Kemudian saya masukkan kod berikut di bawah ruangan Private Sub UserForm_Initialize()

    Dim pMxDoc As IMxDocument
    Dim PFLayer As IFeatureLayer
    Dim pFc As IFeatureClass
    Dim pFeat As IFeature    
    Dim i As Integer

    Set pMxDoc = ThisDocument
    For i = 0 To pMxDoc.FocusMap.LayerCount - 1
            If (UCase(pMxDoc.FocusMap.Layer(i).Name) = UCase("Sungai")) Then
                    Set PFLayer = pMxDoc.FocusMap.Layer(i)
                    Exit For
            End If
    Next
    Set pFc = PFLayer.FeatureClass
    
    'sort nama sungai
    Dim pTableSort As ITableSort
    Set pTableSort = New TableSort
    pTableSort.Fields = "NAME"
    pTableSort.Ascending("NAME") = True
    Set pTableSort.Table = pFc
    pTableSort.Sort Nothing
           
    'Return a cursor for all the features
    Dim pFCur As IFeatureCursor
    Set pFCur = pTableSort.Rows
    Set pFeat = pFCur.NextFeature
    
    Dim namaExists As Boolean
    namaExists = False

    Do Until pFeat Is Nothing
          nama = pFeat.Value(pFeat.Fields.FindField("NAME"))
        
          'Check for duplicate name
          For i = 0 To ComboBox1.ListCount - 1
                 If nama = ComboBox1.List(i) Then
                       namaExists = True
                 Else: End If
          Next i
          
          Select Case namaExists
                  Case False
                          ComboBox1.AddItem nama
                  Case Else
          End Select
          namaExists = False
          
          Set pFeat = pFCur.NextFeature
    Loop
    
    ComboBox1.ListIndex = 0

OK, selesai coding untuk memapar nama sungai ke dalam combobox form saya. Sekarang saya akan masukkan pula coding untuk mencari nama sungai sekiranya pengguna klik butang CARI pada form saya. Kaedah ini samalah seperti bila kita laksanakan proses carian menggunakan kaedah Select by Attributes di dalam ArcMap. Untuk masukkan coding tu, saya double click pada CommandButton CARI, seterusnya procedure CommandButton1_Click akan dipaparkan. 

Double click CommandButton CARI untuk mendapatkan procedure
Seterusnya saya masukkan coding berikut di bawah ruangan Private Sub CommandButton1_Click()

    Dim pDoc As IMxDocument
    Dim pMap As IMap
    Dim pLayer As IFeatureLayer
    Dim pFc As IFeatureClass
    Dim pQf As IQueryFilter
    Dim pSelSet As ISelectionSet
    Dim pFSel As IFeatureSelection
    
    Set pDoc = ThisDocument
    Set pMap = pDoc.FocusMap
    
    For i = 0 To pMap.LayerCount - 1
        If UCase(pMap.Layer(i).Name) = UCase("Sungai") Then
                Set pLayer = pMap.Layer(i)
                Exit For
        End If
    Next
    Set pFc = pLayer.FeatureClass
    
    'Create the query filter
    Set pQf = New QueryFilter
     pQf.WhereClause = "NAME = '" & ComboBox1.Value & "'"

    'Get the features that meet the where clause
    Set pSelSet = pFc.Select(pQf, esriSelectionTypeIDSet, esriSelectionOptionNormal,          
    Nothing)
    
    'Apply the selection
    Set pFSel = pLayer
    Set pFSel.SelectionSet = pSelSet
    pDoc.ActiveView.Refresh

Kemudian, saya aktifkan kembali form saya dan klik sahaja butang Run di dalam VBA Editor.

Klik Run untuk run form anda

Sebaik sahaja saya klik Run, form saya akan dipaparkan di dalam ArcMap. Senarai nama-nama sungai akan dapat saya lihat apabila saya klik combobox di dalam form tersebut.


Dalam contoh ini, saya memilih nama Sungai Langat. Apabila saya klik butang CARI, Sungai Langat akan ditunjukkan di atas peta saya seperti rajah di bawah.


Contoh yang saya tunjukkan ini adalah menggunakan bahasa pengaturcaraan VBA. Sekiranya anda ingin menggunakan persekitaran .NET, anda boleh programkan di dalam Microsoft Visual Studio menggunakan samada VB.Net ataupun C#.Net.

So macamana? Menarik tak? Anda boleh mencuba coding di atas untuk disesuaikan dengan data anda. Cuma perlu gantikan sahaja perkataan "Sungai" dengan nama layer anda di dalam ArcMap dan gantikan "NAME" dengan nama field yang ingin anda query di dalam layer anda. Selamat mencuba.



4 comments: