Anda di halaman 1dari 63

Introduction to Custom GIS Application Development for Windows

By: Brian Marchionni

MapWindow GIS Introduction to Custom GIS Application Development for Windows Copyright 2008 Brian Marchionni All Rights Reserved. Department of Geosciences Idaho State University 1776 Science Center Dr. Idaho Falls, ID 83402 USA

Printed in the United States of America The names of companies and products herein are trademarks or registered trademarks of their respective trademark owners. Revision 0.1

Chapter 1: Getting Started with MapWinGIS ..............................7


Exercise 1: Downloading tools ................................................................. 8 Exercise 2: Setting up the Development Environment ............................. 9 Exercise 3: Adding the Map Component to a Form................................. 12 Exercise 4: Adding Data to the Map ....................................................... 13 Exercise 5: Adding Map Controls ............................................................ 16

Chapter 2: Manipulating Symbology .........................................21


Exercise 1: Docking the Map Component ............................................... 22 Exercise 2: Polygon Layer Symbology .................................................... 23 Exercise 3: Point Layer Symbology......................................................... 26 Exercise 4: Line Layer Symbology .......................................................... 29

Chapter 3: Accessing Feature Attributes ...................................31


Exercise 1: Accessing a Single Features Attributes ................................ 32 Exercise 2: Retrieving the Attribute Table from Shapefiles.................... 34

Chapter 4: Getting Started with MapWindow Plug-ins .............37


Exercise 1: Setting up the Visual Basic 2008 for Plug-ins ...................... 38 Exercise 2: Adding Buttons and Menus .................................................. 44 Exercise 3: Adding Data to the Map from a Plug-in................................ 47 Exercise 4: Using the Debugger and Run-Time Editing .......................... 49

Chapter 5: Basic Examples of Plug-ins ......................................51


Exercise 1: Making a Simple Query Tool................................................. 52 Exercise 2: Finding a Polygons Neighbor............................................... 55 Exercise 3: Calculating the Area of a Polygon ........................................ 57

Chapter 6: Advanced Examples of Plug-ins ...............................61

Chapter 1: Getting Started with MapWinGIS


The goal of this tutorial is to familiarize the reader with the MapWinGIS ActiveX Control component and its use in the Microsoft Visual Basic 2008 Express Edition development environment. This tutorial covers setting up the development environment, the map component, and developing a simple mapping application. The techniques highlighted in these exercises can be used to add a mapping component to a more complicated new or existing application. Please note that if you are using a different version of Microsoft Windows the screen shots may appear slightly different here than on your system: this, however, will not hinder your ability to complete the exercises.

Chapter 1: Getting Started with MapWinGIS

Exercise 1: Downloading tools


A. Download and install the latest version of Microsoft Visual Basic 2008 Express Edition (At the time of writing Service Pack 1) from http://www.microsoft.com/express/product/default.aspx Any other development environment that can use an ActiveX control, such a Visual Basic 6 or Visual Basic Application, will work with the MapWinGIS ActiveX component. This tutorial, however, focuses on Microsoft Visual Basic 2008. B. Download and install the latest version of MapWindow GIS from http://www.mapwindow.org Alternatively, if you do not want to install the entire MapWindow GIS desktop application, you can install the MapWinGIS ActiveX Control from the redistributable installer available from: http://www.mapwindow.org/download.php The MapWinGIS ActiveX Control is the mapping engine which powers the desktop application. For the purpose of these tutorials the entire desktop application is needed. However, if you plan to distribute a stand alone application to clients you may elect to install only the MapWinGIS ActiveX Control. More information about including the control with your application is available on the MapWindow website.

Exercise 1: Downloading tools

Exercise 2: Setting up the Development Environment


A. Run Microsoft Visual Basic 2008 Express Edition by clicking Start -> All Programs -> Microsoft Visual Basic 2008 Express Edition Once loaded, the Visual Studio development environment main window will be presented, displaying the Start Page tab. B. Click File -> New Project

C. From the New Project window select Windows Forms Application, enter MyFirstMapApp for the name and then click OK

Chapter 1: Getting Started with MapWinGIS

You will be returned to the main Visual Basic window. Notice that a new tab has formed titled Form1.vb [Design] beside the original Start Page tab. The body of this design tab contains a windows form titled Form1. This is a representation of what the program would look like if you ran it now. To the right of the main tab window you will notice the Solution Explorer panel, and below it, the Properties Panel. D. Click File -> Save All E. Click Save from the Save Project dialog box From now on you will be able to save your work by simply clicking File -> Save All, or by clicking the Save All button on the main tool bar F. Click the Toolbox button on the left hand side of your screen

This causes the Toolbox to pop out. The toolbox contains components that you can drag onto your applications form to add new functionalities. G. Click the sign next to All Windows Forms collapsible menu

This will cause the All Windows Form collapsible menu to expand, revealing components that can be dropped onto a window. The MapWinGIS ActiveX component is absent, however, from this list. If your system has other GIS software installed on it, you may find other mapping components in this list.

10

Exercise 2: Setting up the Development Environment

H. Right click on the All Windows Forms collapsible menu and select Choose Items from the drop down menu.

Depending on how fast your computer is and what software you have installed, it may take several moments for the next window to open and to change tabs. Please be patient: your machine has not locked up. I. Click on the COM Components tab J. Locate the Map Control in the list of COM Components, make sure that it has a check mark to the left of it, and then click OK

If you have other GIS software installed, ensure that you have selected the Map Control with MapWinGIS Components in the column labeled Library.

Chapter 1: Getting Started with MapWinGIS

11

Exercise 3: Adding the Map Component to a Form


A. Locate the Map Control component under the All Windows Forms expandable menu, then left click and drag it to the right, releasing the mouse button once it is over the form. This causes the Toolbox to collapse, allowing the component to be dropped anywhere onto the form in the design window, in this case onto Form1. You should now have a window that looks similar to this.

B. Highlight the Map Component by left clicking on it This changes the properties panel to show the properties of the Map Component. Notice that the Map Component has been named AxMap1. The properties panel allows various aspects of the control to be changed. For example, scrolling down to (Name) under the Design heading allows the user to change the name of the Map Component. C. Left click on the resize boxes of the Map Component and drag it to fill the form. Resize boxes are located on the edges and corners of a component.

12

Exercise 3: Adding the Map Component to a Form

Exercise 4: Adding Data to the Map


Now that there is a Map Component on the form, data needs to be added to it so that the user will have something to view. The MapWinGIS ActiveX component can visualize numerous different GIS data types; in this example we will open a shapefile. When reading code, an underscore _ at the end of a line indicates the line is continued on the next line of print, but when viewed in the development environment it should be written as one continuous line. Sections of code containing (...) indicate areas where code has been omitted but would be present in the development environment. A. Double click the title bar of Form1

This opens a new tab called Form1.vb beside the existing tabs: Form1.vb [Design] and start page. The new tab contains the following code: Public Class Form1 Private Sub Form1_Load(...) Handles MyBase.Load End Sub End Class Any code written between the lines Private Sub Form1_Load... and End Sub is considered to be part of the subroutine Form1_Load. This particular subroutine will be executed when Form1 loads for the first time.

Chapter 1: Getting Started with MapWinGIS

13

B. Dimension a shapefile object by adding the following code to the Form1_Load subroutine Dim myWorldShape As new MapWinGIS.Shapefile Once you have added the line, your project should look like this: Public Class Form1 Private Sub Form1_Load(...) Handles MyBase.Load Dim myWorldShape As New MapWinGIS.Shapefile End Sub End Class This is the first step in adding data to the map. The line of code just added dimensions a new object called myWorldShape of type MapWinGIS.Shapefile, which can be used to open a shapefile and load it into memory. C. Use the myWorldShape object to open a shapefile stored on the local disk by adding the following code below the previous line you added myWorldShape.Open("C:\Program Files\MapWindow\_ Sample projects\world\Shapefiles\world_adm0.shp") This command instructs the myWorldShape object to open the shape file that is specified in the path between quotes. The full path, including the file extension, has to be present for the file to be found and opened. D. Next add the myWorldShape object to the map by adding this line of code below the previous line you added AxMap1.AddLayer(myWorldShape, True) Once you have added the line, your project should look like this: Public Class Form1 Private Sub Form1_Load(...) Handles MyBase.Load Dim myWorldShape As New MapWinGIS.Shapefile myWorldShape.Open(...) AxMap1.AddLayer(myWorldShape, True) End Sub End Class

14

Exercise 4: Adding Data to the Map

E. Click on the Form1.vb [Design] tab, and then click the Start Debugging button (the icon with the green play button) to run your program

Your program should now be running. The Map Component should be filed with a simple map of the world. The default cursor function is zoom in. Try manipulating the map with the cursor by clicking and dragging a bounding box.

You will soon discover that more tools are needed, such as the ability to zoom out and to pan the map; these features will be added in the next section. F. When you are done, close your program to return to the development environment

Chapter 1: Getting Started with MapWinGIS

15

Exercise 5: Adding Map Controls


Now that the basic map component has been added to the form, tools need to be added so that the user can further manipulate the map beyond zooming in and out. This exercise will add buttons to control zooming and panning. A. Open the Designer by clicking the tab labeled Form1.vb [Design] B. Open the Toolbox and click and drag a ToolStrip component onto the top left corner of Form1 C. Select the ToolStrip you added to Form1 D. Left click the drop down button labeled ToolStripButton and select button from the menu to create a new Button

16

Exercise 5: Adding Map Controls

E. Left click on the ToolStripButton1 Component and examine its properties in the properties panel. F. Rename your button by locating the (Name) attribute and changing its value from ToolStripButton1 to btnZoomIn. This is the name that we will use to later access the component programmatically.

G. Locate the DisplayStyle attribute and change its value from Image to Text H. Change the buttons Label by locating the Text attribute and changing it from ToolStripButton1 to Zoom In

I. Now that you have learned how to add buttons to your form, add three additional buttons beside the one that you just created. Name the new buttons btnZoomOut, btnPan and btnFullExtent, and label them Zoom Out, Pan and Full Extent respectively.

Chapter 1: Getting Started with MapWinGIS

17

J. Double click the Zoom In button on Form1 in the designer to create an event handler This action opens the Form1.vb tab and creates the event handler for the Zoom In button called btnZoomIn_Click. Any code written between the line Private Sub btnZoomIn_Click... and the End Sub below it will be executed when the button is pressed. K. Add the line AxMap1.CursorMode = MapWinGIS.tkCursorMode.cmZoomIn to the btnZoomIn_Click sub by inserting it below the line Private Sub btnZoomIn_Click(... The btnZoomIn_Click sub should now look like this. Private Sub btnZoomIn_Click(...) Handles btnZoomIn.Click AxMap1.CursorMode = MapWinGIS.tkCursorMode.cmZoomIn End Sub This line of code changes the CusorMode attribute of the AxMap1 MapComponent to MapWinGIS.thCursorMode.cmZoomIn. You can change the public attributes of any component programmatically by typing the components name and then pressing . This will then generate a drop down box of all the attributes and methods associated with that component. In this case we are accessing the MapComponents CursorMode attribute. Notice that once you type the equal sign, another drop down box forms showing all the possible values that can be assigned to that attribute. L. Now create an event handler for the Zoom Out button by repeating step J M. In the event handler for btnPan_Click set the AxMap1.CursorMode attribute to MapWinGIS.tkCursorMode.cmZoomOut N. Repeat steps L and M for the Pan button setting the CursorMode attribute to MapWinGIS.tkCursorMode.cmPan O. Now create an event handler for the Full Extent button The MapComponent contains a built-in method to zoom the map to the full extent of all layers loaded. We will call this method to quickly and easily zoom to the maps full extent.

18

Exercise 5: Adding Map Controls

P. In the btnFullExtent_Click event handler type AxMap1. Once you type the . a drop down box will form with all the public methods and properties MapComponent that you can access. Q. Look for the ZoomToMaxVisibleExtents method in the list that forms, select it from the drop down list and press enter.

R. Now that you have added functionality to all of the buttons, try to run your application. Try each of the buttons to manipulate the map. S. Close your program to return to the development environment, and save your work now by clicking File -> Save All

Chapter 1: Getting Started with MapWinGIS

19

20

Chapter 2: Manipulating Symbology


In most circumstances, GIS software developers need the ability to create rich and informative maps by presenting data in visually stimulating ways. Typically, we use such techniques as coloring schemes, markers, labels, and other types of symbology to improve the visual value of a digital map. In this chapter, you will learn how to adjust the global display properties for a layer and how to apply a coloring scheme to your data. The Exercises in Chapter 2 continues from Chapter 1. While step by step procedures are still given, it is assumed that the reader is now comfortable navigating between the various windows in Microsoft Visual Studio. If you feel that you have not completely memorized all of the techniques in Chapter 1, it is recommended you review them now.

Chapter 2: Manipulating Symbology

21

Exercise 1: Docking the Map Component


A. Run the program you created in Chapter 1 by clicking the start debugging icon B. Resize your program by left clicking on one of its corners and dragging outward You can resize your window, but the Map Component stays the same size. To make the Map Component grow and shrink with the main application form, we need to dock them together. C. Close your program and return to the development environment D. Select the Map Component in the designer and locate the Dock attribute in the properties panel E. Left click the Dock attribute drop down box and select the fill dock option

Notice how the Map Component now occupies the entire lower portion of Form1 and that the resize boxes on all sides have disappeared. F. Run the program again and resize the main form Since the Map Component is docked to the main form, its size is linked to the size of Form1.

22

Exercise 1: Docking the Map Component

Exercise 2: Polygon Layer Symbology


For this exercise we will design a new function specifically to load a polygon layer, and then apply a new symbology to that layer. A. Open the Form1.vb tab (Not the [Design] tab) B. Below the last End Sub but before End Class add the line Private Sub loadWorldShape And press Enter You will notice that once you press Enter the development environment adds () to the end of the line, and End Sub two lines lower. This occurs because the compiler recongnizes that you are trying to create a new Sub and fills in the required code for you. C. Now cut the code from Private Sub Form1_Load(...) and paste it into Private Sub loadWorldShape() so that it now reads: Private Sub Form1_Load(...) End Sub Private Sub loadWorldShape() Dim myWorldShape As New MapWinGIS.Shapefile myWorldShape.Open("C:\Program Files\...\world_adm0.shp") AxMap1.AddLayer(myWorldShape, True) End Sub D. Add the line loadWorldShape() to the Private Sub Form1_Load(...) Now every time Form1 is loaded and Form1_Load() is called, it will in turn call loadWorldShape( ). E. Above the line AxMap1.AddLayer(myWorldShape, True) add the line Dim hndWorldShape As Integer This will create a new variable called hndWorldShape of type integer.

Chapter 2: Manipulating Symbology

23

F. Now modify the line AxMap1.AddLayer(myWorldShape, True) to read hndWorldShape = AxMap1.AddLayer(myWorldShape, True) The hndWorldShape variable now contains the handle number of the layer. This handle can be used to access the layer from the AxMap1 map component so that later the layers properties can be modified. G. Add the following lines to the bottom of Private Sub loadWorldShape() Dim FillColor As UInt32 Dim LineColor As UInt32 Dim LineWidth As Single FillColor = Convert.ToUInt32(RGB(100, 255, 0)) LineColor = Convert.ToUInt32(RGB(0, 0, 255)) LineWidth = 2.0 The variables FillColor and LineColor each contain a Red / Green / Blue color value stored as a 32 bit unsigned integer. The function Convert.ToUInt32(RGB(0,0,255)) takes three parameters with values from 0 255. Each parameter represents one of the primary color components which, when combined, create a shade. This is then converted into the unsigned interger format that the MapComponent understands. The LineWidth variable contains a single precision decimal number which represents how thick to draw lines.

24

Exercise 2: Polygon Layer Symbology

H. Now assign the symbology that you defined in the previous step to the myWorldShape layer by adding the following lines below the ones you just added AxMap1.set_ShapeLayerFillColor(hndWorldShape, FillColor) AxMap1.set_ShapeLayerLineColor(hndWorldShape, LineColor) AxMap1.set_ShapeLayerLineWidth(hndWorldSahpe, LineWidth) Your final code should read as follows: Private Sub loadWorldShape() Dim myWorldShape As New MapWinGIS.Shapefile myWorldShape.Open("C:\Program Files\...\world_adm0.shp") Dim hndWorldShape As Integer hndWorldShape = AxMap1.AddLayer(myWorldShape, True) Dim fillColor As UInt32 Dim lineColor As UInt32 Dim lineWidth As Single fillColor = Convert.ToUInt32(RGB(100, 255, 0)) lineColor = Convert.ToUInt32(RGB(0, 0, 255)) lineWidth = 2.0 AxMap1.set_ShapeLayerFillColor(hndWorldShape, fillColor) AxMap1.set_ShapeLayerLineColor(hndWorldShape, lineColor) AxMap1.set_ShapeLayerLineWidth(hndWorldShape, lineWidth) End Sub I. Run your program and examine the modified symbology

Chapter 2: Manipulating Symbology

25

Exercise 3: Point Layer Symbology


A. Below loadWorldShape, create a new Sub called loadCitiesShape. Have the Form1_load sub call it after it calls loadWorldShape Public Class Form1 Private Sub Form1_Load(...) Handles MyBase.Load loadWorldShape() loadCitiesShape() End Sub ... Private Sub loadCitiesShape() End Sub End Class B. Create a new variable in the loadCitiesShape sub of type MapWinGIS.Shapefile called myCitiesShape C. Use the myCitiesShape variable to open the file C:\Program Files\MapWindow\Sample Projects_ \World\Shapefiles\cities_capital_pt.shp D. Create a new variable of type integer called hndCitiesShape E. Use AxMap1 to add the myCitiesShape layer to the map, saving its handle into the hdnCitiesShape variable Private Sub loadCitiesShape() Dim myCitiesShape As New MapWinGIS.Shapefile myCitiesShape.Open("...\cities_capital_pt.shp") Dim hndCitiesShape As Integer hndCitiesShape = AxMap1.AddLayer(myCitiesShape, True) End Sub F. Dimension a variable called pointColor as a UInt32 and assign it the value Convert.ToUInt32(RGB(255, 255, 0)) G. Dimension a variable called pointSize as a single and assign it the value 8.0

26

Exercise 3: Point Layer Symbology

H. Assign the pointColor symbology definition to the layer myCitiesShape using its handle and the Map Components set_ShapeLayerPointColor method I. Assign the pointSize symbology definition to the layer myCitiesShape using its handle and the Map Components set_ShapeLayerPointSize method In order to define the size and color of the point that will appear on the map, we first created variables to hold the color and size definitions, and then we assigned them to the layer we wanted to apply the symbology to by using methods on the Map Component. In order to change the shape of the point that will be drawn, we can use internal definitions that predefine some basic shapes. The class MapWinGIS.tkPointType contains many different point style definitions that we can use. J. Add the following line to the loadCitiesShape sub to assign a circle symbology to the points of the myCitiesShape layer axMap1.set_ShapeLayerPointType(hndCitiesShape,_ MapWinGIS.tkPointType.ptCircle) Now that you have defined the symbology for the myCitiesShape layer, your code should look like this: Private Sub loadCitiesShape() Dim myCitiesShape As New MapWinGIS.Shapefile myCitiesShape.Open("C:\Program Files\MapWindow\_ Sample projects\World\Shapefiles\cities_capital_pt.shp") Dim hndCitiesShape As Integer hndCitiesShape = AxMap1.AddLayer(myCitiesShape, True) Dim pointColor As UInt32 pointColor = Convert.ToUInt32(RGB(255, 255, 0)) Dim pointSize As UInt32 pointSize = 8.0 AxMap1.set_ShapeLayerPointColor(hndCitiesShape,pointColor) AxMap1.set_ShapeLayerPointSize(hndCitiesShape,pointSize) AxMap1.set_ShapeLayerPointType(hndCitiesShape,_ MapWinGIS.tkPointType.ptCircle) End Sub K. Run your program and examine the new symbology This demonstrates using a predefined point symbol contained within the MapWinGIS library. It is also possible to use an external symbol or image to represent a point. To do this we first need to load an image and then assign it to the point layer as a user defined point symbol.

Chapter 2: Manipulating Symbology

27

L. In the last line replace MapWinGIS.tkPointType.ptCircle with MapWinGIS.tkPointType.ptUserDefine so that it reads: AxMap1.set_ShapeLayerPointType(hndCitiesShape,_ MapWinGIS.tkPointType.ptUserDefined) Now that the point type is set to user defined, a user defined bitmap needs to be loaded and assigned as the point symbol. M. Dimension a new variable called imgCities of type MapWinGIS.Image N. Use the Open method on the imgCities object to open the file C:\Program Files\MapWindow\OfflineDocs\content\skins\_ common\images\Arr_d.png O. We now assign the custom point image symbol to the myCitiesShape layer with the line AxMap1.set_UDPointType(hndCitiesShape, imgCities) The loadCitiesShape sub should now read: Private Sub loadCitiesShape() Dim myCitiesShape As New MapWinGIS.Shapefile myCitiesShape.Open("C:\...\cities_capital_pt.shp") Dim hndCitiesShape As Integer hndCitiesShape = AxMap1.AddLayer(myCitiesShape, True) Dim pointColor As UInt32 pointColor = Convert.ToUInt32(RGB(255, 255, 0)) Dim pointSize As UInt32 pointSize = 1 AxMap1.set_ShapeLayerPointColor(hndCitiesShape,_ pointColor) AxMap1.set_ShapeLayerPointSize(hndCitiesShape, pointSize) AxMap1.set_ShapeLayerPointType(hndCitiesShape,_ mapWinGIS.tkPointType.ptUserDefined) Dim imgCities As New MapWinGIS.Image imgCities.Open("C:\Program Files\...\Arr_d.png") AxMap1.set_UDPointType(hndCitiesShape, imgCities) End Sub P. Run your program and examine the new symbology Q. Close your program to return to the development environment, and save your work now by clicking File -> Save All

28

Exercise 3: Point Layer Symbology

Exercise 4: Line Layer Symbology


A. Create a new sub called loadRiverShape below the loadCitiesShape sub B. Call the loadRiverShape() sub from Form1_Load() after loadCitiesShape() C. Dimension a new variable of type MapWinGIS.Shapefile in the loadRiverShape sub and name it myRiverShape D. Use the myRiverShape variable to open C:\Program Files\MapWindow\Sample Projects\World\Shapefiles\_ river_quality_li.shp E. Add the layer to the map using AxMap1.AddLayer() and save the handle in a variable called hndRiverShape of type integer F. Create a variable of type Uint32 named lineColor and assign it the value Convert.ToUInt32(RGB(0, 0, 128)) G. Create a variable of type Single named lineWidth and assign it the value 1 H. Assign the symbology variables lineColor and lineWidth to the myRiverShape layer using the MapComponents methods .set_ShapeLayerLineColor() and .set_ShapeLayerLineWidth() Private Sub loadRiverShape() Dim myRiverShape As New MapWinGIS.Shapefile myRiverShape.Open("C:\...\river_quality_li.shp") Dim hndRiverShape As Integer hndRiverShape = AxMap1.AddLayer(myRiverShape, True) Dim lineColor As UInt32 lineColor = Convert.ToUInt32(RGB(0, 0, 128)) Dim lineWidth As Single lineWidth = 1 AxMap1.set_ShapeLayerLineColor(hndRiverShape, lineColor) AxMap1.set_ShapeLayerLineWidth(hndRiverShape, lineWidth) End Sub I. Run your program and examine the new symbology J. Close your program to return to the development environment and save your work now by clicking File -> Save All

Chapter 2: Manipulating Symbology

29

30

Chapter 3: Accessing Feature Attributes


Non-spatial data is often associated with spatial data and goes beyond the simple location or shape of a feature. This data can be stored in a table linked to features. One of the most important abilities of a GIS is to be able to access the attributes associated with a specific feature quickly and efficiently. There is any number of reasons why a custom GIS application would need to access a features attributes. For example, a point layer may contain point features of the locations of major cities; the corresponding city names for each point could be stored in a table linked to these points. The writer of a custom GIS application may want to zoom to a specific city by searching for its name in an attribute table. In this chapter we will explore the best methods for accessing and manipulating feature attributes. We will also explore some simple ways of visualizing this information.

Chapter 3: Accessing Feature Attributes

31

Exercise 1: Accessing a Single Features Attributes


For this exercise we are going to create a simple subroutine which will query the attribute table for a value in one of its columns and return the shapes index. A. Cut the line Dim hndWorldShape As Integer from the Private Sub loadWorldShape() and place it directly below the line Public Class Form1 This changes hndWorldShape from a local variable to a class variable. Class variables are accessible from anywhere within the class, unlike local variables which are only accessible from within the sub they are dimensioned in. Dimensioning handle variables as class variables is an easy way to keep track of layers you add to the MapComponent. B. Open the Form1.vb [Design] tab and add a new button to ToolStrip1 named btnFindSouthAfrica C. Change the DisplayStyle attribute of ShowDataGrid to Text and D. Change the Text attribute of ShowDataGrid to Find South Africa E. Double click the btnShowDataGrid button to create an event handler for the button F. In the Private Sub btnFindSouthAfrica_Click() sub add the lines Dim myWorldShape As New MapWinGIS.Shapefile myWorldShape = AxMap1.get_GetObject(hndWorldShape) These two lines of code retrieve the layer designated by the hndWorldShape. Retrieving the shapefile from the MapComponent is more memory efficient than keeping a copy of the shapefile as a class variable.

32

Exercise 1: Accessing a Single Features Attributes

G. Now add the following code For i As Integer = 0 To myWorldShape.NumShapes If myWorldShape.CellValue(0, i) = "South Africa" Then MsgBox(i,MsgBoxStyle.OkOnly,_ "Which shape is South Africa?") End If Next This code loops from i = 0 to i = the number of shapes in the myWorldShape shapefile variable. Each iteration of the loop checks to see if the current shape contains the text South Africa in its column with index 0. If the shape does contain the text, a dialog box is created displaying the shapes index. H. Run your program and press the Find South Africa button

I. Close your program to return to the development environment and save your work now by clicking File -> Save All

Chapter 3: Accessing Feature Attributes

33

Exercise 2: Retrieving the Attribute Table from Shapefiles


For this exercise we will create a new windows form and place a DataGridView in it. We will then populate the DataGridView with data from one of the shapefiles in our project. A. Right click MyFirstMapApp in the Solution Explorer and select Add -> Windows Form from the drop down menu B. In the Add New Item window change the name to FormTable.vb and click OK A new tab called FormTable.vb [Design] will appear, and a new form called FormTable will appear within that tab. C. Left click the Toolbox to open it D. Left click and drag a DataGridView component to the center of the FormTable form and drop into by releasing the left mouse button. E. Change the dock attribute of DataGridView1 to Fill F. Open the FormTable.vb code tab by right clicking on FormTable.vb in the Solution Explorer and selecting View Code from the drop down menu G. Dimension a class variable called pMyShapeFile of type MapWinGIS.Shapefile H. Create a new Sub called New() with parameters ByRef myShapeFile As MapWinGIS.Shapefile by adding the code below to the public Class FormTable Public Sub New(ByRef myShapeFile As MapWinGIS.Shapefile) pMyShapeFile = myShapeFile InitializeComponent() End Sub The line InitializeComponent() calls a built-in subroutine of the Windows Form which must be called from the New subroutine. Since we have replaced the default New subroutine with ours, we have to include it here. I. Open the Form1.vb [Design] tab and add a new button to ToolStrip1 named btnShowDataGrid J. Change the DisplayStyle attribute of ShowDataGrid to Text and K. Change the Text attribute from ToolStripButton1 to Show Data Grid

34

Exercise 2: Retrieving the Attribute Table from Shapefiles

L. Resize Form1 so that there is room to see all the buttons M. Double click the btnShowDataGrid button to create an event handler for the button and open the Form1 code tab N. In the Private Sub btnShowDataGrid_Click() sub add the lines Dim myWorldShape As New MapWinGIS.Shapefile myWorldShape = AxMap1.get_GetObject(hndWorldShape) O. Declare a new instance of the FormTable form and display it with the lines Dim myTableForm As New FormTable(myWorldShape) myTableForm.Showdialog() Whenever the user presses the Show Data Grid button, a new instance of the FormTable will be created and then displayed. P. Open the FormTable [Design] Tab, double click the FormTables title bar to open the FormTable code tab, and create the event handler sub FormTable_Load(...) Q. Add the following lines to the FormTable_Load sub Dim myDataTable As New DataTable Dim myDataRow As DataRow These lines of code create a temporary datatable, datacolumn, and datarow for us to populate with data from the shapefiles attribute table. R. Insert the following lines of code next For i As Integer = 0 To pMyShapeFile.NumFields - 1 myDataTable.Columns.Add(pMyShapeFile.Field(i).Name) Next This snippet of code will loop through the column names found in the pMyShapeFile shapefile variable and add them to the myDataTable.

Chapter 3: Accessing Feature Attributes

35

S. Add the following lines of code next For j As Integer = 0 To pMyShapeFile.NumShapes - 1 myDataRow = myDataTable.NewRow For k As Integer = 0 To pMyShapeFile.NumFields - 1 myDataRow(k) = pMyShapeFile.CellValue(k, j) Next myDataTable.Rows.Add(myDataRow) Next This will loop through each shape in pMyShapeFile, create a new temporary row for its values, and then loop through each column of the current shape and add them to the temporary row variable. Finally the temporary row is added to the myDataTable variable. T. Now set the DataGridView1.DataSource attribute to be equal to myDataTable with the line DataGridView1.DataSource = myDataTable U. Run your program and press the Show Data Grid button

V. Close your program to return to the development environment and save your work now by clicking File -> Save All

36

Exercise 2: Retrieving the Attribute Table from Shapefiles

Chapter 4: Getting Started with MapWindow Plug-ins


Developing a completely stand alone custom GIS application can be a daunting task, even when using tools like the MapWinGIS Map Component. Since many of the features and functions that a GIS developer needs have already been included in the MapWindow GIS desktop application, it may be simpler for a developer to create their tools as plug-ins rather than as stand alone applications. The MapWindow GIS desktop application has a versatile plug-in interface which allows developers to add new functions to the existing framework, using tools similar to those used to develop programs with the stand alone Map Component. With the large number of existing plug-ins and built-in functions available with the MapWindow GIS desktop application, developers should thoroughly consider the scope of their project and the needs of their users before deciding between developing a stand alone application or a plug-in.

Chapter 4: Getting Started with MapWindow Plug-ins

37

Exercise 1: Setting up the Visual Basic 2008 for Plug-ins


There are many similarities between developing a stand alone GIS application using the Map Component and developing a plug-in for the MapWindow GIS desktop application. The two types of projects are, however, sufficiently different that code cannot be directly copied from one to the other without first being edited. Many of the objects are similar between the two environments but special care must be taken when working with plug-ins to allow for smooth debugging. MapWindow GIS contains a simple plug-in editor for Visual Basic .NET and C#. This editor, however, is limited in its functionality and some of the tools that Microsoft Visual Basic 2008 Express Edition has are missing. A. Launch Microsoft Visual Basic 2008 Express Edition, if it is not already open. If it is already open, save your work B. Click File -> New Project C. Select Class Library and enter MyFirstPlugin as the name and click OK D. From the tab Class1.vb delete all the code so it is empty E. Click Start -> All Programs -> MapWindow GIS -> MapWindow GIS F. Close the Welcome Screen and click Plug-ins -> Scripts This window by default contains the outline for a plug-in interface which we will use. It is the easiest way to get a template we need to build a plug-in.

38

Exercise 1: Setting up the Visual Basic 2008 for Plug-ins

G. Select all the code in this window and copy it by pressing crtl+c

H. Returns to Visual Basic 2008 Express Edition and paste the code into the Class1.vb tab by pressing ctrl+v You will get several errors at the bottom of your screen because some of the references made by the code have not been met. We will add those references now and the errors will clear.

I. Right click MyFirstPlugin in the Solution Explorer and select Add Reference from the drop down menu J. From the Add Reference window select the Browse tab

Chapter 4: Getting Started with MapWindow Plug-ins

39

K. Browse to the folder C:\Program Files\Map Window\ L. Select MapWinInterfaces.dll and MapWinGIS.ocx and click OK M. Right click MyFirstPlugin in the Solution Explorer and select Add Reference from the drop down menu once more N. From the Add Reference window select the .NET tab O. Scroll down to System.Window.Forms, highlight it then click OK P. Right click MyFirstPlugin in the Solution Explorer and select Add Reference from the drop down menu Q. From the .NET tab Scroll down to System.Drawing, highlight it then click OK All of the error messages should now be gone. If some error messages remain, check to make sure you did not accidentally skip adding a reference. R. Right click Class1.vb in the solution explorer and rename it MyFirstPlugin.vb S. In the MyFirstPlugin.vb tab modify the line Public Class MyPlugin To read Public Class MyFirstPlugin While it is permissible to have classes with a different name than the file that contains them, it is a good idea to keep them the same to simplify file management on large projects. T. Modify the line Return My New Plug-in To read Return My First Plug-in This is the name that is returned to MapWindow GIS when it loads the plug-in. This value must be unique among all the plug-ins as it is used to identify them.

40

Exercise 1: Setting up the Visual Basic 2008 for Plug-ins

U. Click Tools -> Options in the options window expand the Project and Solutions tree, and highlight General. Place a check mark beside Show advanced build configurations and click OK

V. Right click MyFirstPlugin from the Solution Explorer and select Properties from the drop down menu W. Click the Compile tab on the left hand side of the properties page and change the Build output path to C:\Program Files\MapWindow\Plugins X. Click the Debug tab and select Start external program and enter C:\Program Files\MapWindow\MapWindow.exe

Chapter 4: Getting Started with MapWindow Plug-ins

41

Please note that if you are using Visual Studio 2008 Express, the Start External Program option is missing due to changes that Microsoft made to the development environment. A work around has been found but MapWindow must be installed into its default location C:\Program Files\MapWindow\ Download the file http://idahofalls.mapwindow.org/myfirstplugin.zip and extract its contents to your hard drive. Close your current project and open the MyFirstPlugin.sln file with Visual Studio 2008 Express. If you are presented with a security warning, select Load Project Normally and click OK

42

Exercise 1: Setting up the Visual Basic 2008 for Plug-ins

Y. Run your plug-in by clicking the green Debug button MapWindow GIS should launch and your plug-in should appear in the Plug-ins menu.

Z. Close MapWindow GIS and save your project by clicking File -> Save All

Chapter 4: Getting Started with MapWindow Plug-ins

43

Exercise 2: Adding Buttons and Menus


Now that your plug-in is identified by MapWindow and can be activated, it needs to do something. One of the easiest ways to access the functionality of a plug-in from the Map Window GIS application is to add a button or drop down menu. When the plug-in is loaded by MapWindow the Initialize() Sub is called. Conversely, when the plug-in is unloaded the Terminate() Sub is called. This is where adding and removing buttons from the toolbars or drop down menus is performed. Any other function that needs to be done at load time can also be run in this area. Almost every plug-in stores a copy of the IMapWin interface as a class variable in the Initialize() Sub. A. Below the line Public g_MapWin As MapWindow.Interfaces.IMapWin Create a class variable called g_menuStack of type Stack(Of String) by typing Private g_MenuStack As New Stack(Of String) This variable will be used to keep track of all the menu items that are added to the main menu in the MapWindow GIS application. This needs to be done so that when the plug-in is terminated the buttons can be removed. B. Scroll down to the Initialize() Sub and add the following lines to the bottom g_MapWin.Menus.AddMenu("mfpMain", "", "My First Plug-in", "") g_MenuStack.Push("mfpMain") The first line adds the menu My First Plug-in to MapWindow GIS. The second line adds the menu title to the local stack of menu items so that they can be removed later. C. Next add the line g_MapWin.Menus.AddMenu("mfpItem1","mfpMain","Click Me","") g_menuStack.Push("mfpItem1") The first line adds the menu item Click Me to menu My First Plug-in. The second line adds the menu item to the local stack of menu items so that they can be removed later.

44

Exercise 2: Adding Buttons and Menus

D. Scroll down to the Terminate() Sub and add this code While g_MenuStack.Count > 0 g_MapWin.Menus.Remove(g_MenuStack.Pop()) End While This will loop through all the items that are in the stack in the reverse order that they were added, and remove them from the MapWindow GIS menu. E. Next find the Sub ItemClicked() and add the code If ItemName = "mfpItem1" Then MsgBox("My First Plug-in Clicked", MsgBoxStyle.OkOnly,_ "My First Plug-in") Handled = True End If The ItemClicked() sub catches an event which is fired whenever a menu item is clicked. The variable ItemName contains the name of the menu item that was clicked. This code checks if ItemName equals the name of the item added in Step C. If it is equal the code displays a msgbox indicating that it is. Finally the Handled variable is set to true; this prevents the event from fireing in other plug-ins and improves performance. F. Run your plug-in by clicking the green Debug button G. Expand the Plug-ins menu and make sure My First Plug-in is checked

Chapter 4: Getting Started with MapWindow Plug-ins

45

H. Click My First Plug-in -> Click Me

I. Close MapWindow and save your project by clicking File -> Save All

46

Exercise 2: Adding Buttons and Menus

Exercise 3: Adding Data to the Map from a Plug-in


When writing a plug-in for MapWindow GIS you can add data to the main map the same way you can with the ActiveX Map Component. A. Add a new button to the mfpMain menu named mfpAddData with the label Add Data Dont forget to store it in the stack after you add it to the menu. g_MapWin.Menus.AddMenu("mfpAddData","mfpMain","Add Data","") g_MenuStack.Push("mfpAddData") B. Now modify the ItemClicked Sub with an ElseIf statement to catch conditions when ItemName equals mfpAddData If ItemName = "mfpItem1" Then ... ElseIf ItemName = "mfpAddData" Then End If C. Add these lines between ElseIf and End If Dim myWorldShape As New MapWinGIS.Shapefile myWorldShape.Open("C:\Program Files\MapWindow\Sample Projects_ \World\Shapefiles\world_adm0.shp") g_MapWin.Layers.Add(myWorldShape, "My World") Handled = True g_MapWin.Layers.Add(...) can take many different parameters. In this case we pass it a shapefile and the title we would like the layer to get in the MapWindow legend. One of the useful features about the g_MapWin.Layers.Add method is that many different data types can be added without needing to dimension them first. The above code can be replaced with the following line and will behave the same way. g_MapWin.Layers.Add("C:\Program Files\MapWindow\_ Sample Projects\World\Shapefiles\world_adm0.shp","My World")

Chapter 4: Getting Started with MapWindow Plug-ins

47

J. Run your plug-in by clicking the green Debug button and click My First Plug-in -> Add Data A random color scheme has been assigned to the layer, but the layer has been named My World.

48

Exercise 3: Adding Data to the Map from a Plug-in

Exercise 4: Using the Debugger and Run-Time Editing


Visual Studio 2008 contains many useful debugging tools which facilitates working with plug-ins. For example, you can set break points and watch local variables, but more notably you can edit code while it is running. A. Place a breakpoint at the following line by left clicking in the gray margin adjacent to the line ElseIf ItemName = "mfpAddData" Then You can only place break points on functional lines of code; you cannot place them, for example, on blank lines or comment lines.

Chapter 4: Getting Started with MapWindow Plug-ins

49

B. Run your plug-in by clicking the green Debug button and click My First Plug-in -> Add Data The program will stop at the break point and the line will turn yellow. Notice that the lock icon on the code tab has disappeared. This indicates that the code can now be edited. Runtime code editing can be done only when the program has stopped at break point.

C. Below the lines g_MapWin.Layers.Add(myWorldShape, "My World") Handled = True add the line g_MapWin.Layers(0).Color = Drawing.Color.Aqua Notice that working with colors from Plug-ins is much simpler because the MapWindow GIS application handles translating Microsoft .NET color variables for you. D. Continue debugging by pressing the Debug button again E. Close MapWindow and save your project by clicking File -> Save All F. Remove the break point by clicking the Red dot

50

Exercise 4: Using the Debugger and Run-Time Editing

Chapter 5: Basic Examples of Plug-ins


While adding and removing layers is an important functionality built into MapWindow GIS, the point of a plug-in is to add functionality that is not present in a GIS by default, or a function that is designed for a specific data set. This chapter covers some simple examples of how a plug-in can interact with data and present results to the user in ways that are custom tailored to a specific task.

Chapter 5: Basic Examples of Plug-ins

51

Exercise 1: Making a Simple Query Tool


In this exercise we will create a simple query tool that searches the map of the world for a user entered country name and highlights it. A. Add a new button to the mfpMain menu and named mfpQuery with the label Find Country B. Add another ElseIf statement to ItemClicked(...) to catch menu clicks for mfpQuery C. Add a new form to the project by right clicking MyFirstPlugin in the solution explorer and selecting Add -> Windows Form... D. Select Windows Form from the Add New Item window and name it Query.vb E. Add a TextBox to the Query.vb form in the designer and rename it txtBoxQuery by changing the (name) attribute in the Properties panel F. Add a Button and rename it btnQuery, change its Text attribute to Search G. Double click btnQuery to open the forms code tab and create an event handler for the button H. Create the class variable Dim g_MapWin As MapWindow.Interfaces.IMapWin I. Above the btnQuery_Click Sub add the line Public Sub New(ByVal MapWin As MapWindow.Interfaces.IMapWin) InitializeComponent() g_MapWin = Mapwin End Sub When working with the the ActiveX Control most functions will need access to the Map. In this case, however, we are passing an interface to the main MapWindow Application rather than an interface to the MapComponent.

52

Exercise 1: Making a Simple Query Tool

J. Add the following code to the btnQuery_Click Sub Dim worldSF As New MapWinGIS.Shapefile worldSF = g_MapWin.Layers(0).GetObject() For i As Integer = 0 To worldSF.NumShapes If worldSF.CellValue(0, i) = txtBoxQuery.Text Then g_MapWin.Layers(0).Shapes(i).Color = _ Drawing.Color.LightBlue Exit Sub End If Next This will search through all the shapes in the file looking for the one with a corresponding attribute matching the text the user entered. K. Return to the MyFristPlugin.vb tab L. Below the line ElseIf ItemName = mfpAddData then add the lines Dim myQueryForm As New Query(g_MapWin) myQueryForm.Show() These two lines of code pass the MapWindow GIS application interface to the form and then display it. M. Run your plug-in by clicking the green Debug button N. Add the world data layer by clicking My First Plug-in -> Add Data O. Click My First Plug-in -> Find Country

Chapter 5: Basic Examples of Plug-ins

53

P. Enter South Africa in the text box and click Search Q. Close the Query Window Notice the color of South Africa has changed. R. Close MapWindow and save your project by clicking File -> Save All

54

Exercise 1: Making a Simple Query Tool

Exercise 2: Finding a Polygons Neighbor


This exercise will expand on the functionality of exercise one. It will locate all the countries that are directly neighboring the country a user queries. The results will be displayed in a list and the neighboring countries will have their fill color changed. A. Open the Query.vb code tab B. Below the line worldSF = ... add the line Dim countryShp As MapWinGIS.Shape Dim countryIndex As Integer These variables will be used to store the shape that corresponds to the country the user queried and its index. C. Now replace the line Exit Sub with CountryIndex = i Exit For This causes the index of the shape to be stored in the variable countryIndex and exits the loop but not the sub. D. Below the Next statement of the For loop add countryShp = worldSF.Shape(countryIndex) If countryIndex Is Nothing Then Exit Sub End If This will handle situations where no country is found.

Chapter 5: Basic Examples of Plug-ins

55

E. Add the following code below that Dim neighbor As MapWinGIS.Shape For i As Integer = 0 To worldSF.NumShapes() - 1 neighbor = worldSF.Shape(i) For j As Integer = 0 To neighbor.numPoints - 1 Dim point As MapWinGIS.Point = neighbor.Point(j) If worldSF.PointInShape(countryIndex, point.x,_ point.y) And i <> countryIndex Then g_MapWin.View.SelectedShapes.AddByIndex(i,_ Drawing.Color.Yellow) End If Next Next The first loop in the preceding code increments i from 0 to the number of shapes in the worldSF shapefile. The variable neighbor is then assigned the shape that i corresponds to. The second loop increments j from 0 to the number of points in the neighbor shape. The variable point is then assigned the point that j corresponds to. Each point is then tested to see if it borders the country being searched for; if it does the country is then selected and highlighted lavender. F. Now run your plug-in G. Add the My World layer to the map by clicking My First Plug-in -> Add Data H. Locate a country and select its neighbors by clicking My First Plug-in -> Find Country I. Enter South Africa in the text box and click Search The world map should change slightly: South Africa should change from cyan to light blue and its neighbors should have been selected and highlighted yellow.

56

Exercise 2: Finding a Polygons Neighbor

Exercise 3: Calculating the Area of a Polygon


One of the reasons to work with data in a GIS is to have access to spatial properties that you would not have access to by simply looking at tabular data. One of the simple things that can be done with polygon data is to calculate the area of a feature. MapWindow provides a library of predefined spatial operations that can be accessed from a plug-in or a stand alone application. A. Add a button to the My First Plug-in menu called mfpArea and label it Calculate Area B. Add an ElseIf statement to handle clicks of the mfpArea button Since our sample data is in decimal degrees, any area calculation performed on the data set would yield meaningless results since the length of decimal degrees vary with latitude. To generate meaningful results, the data must be re-projected into an area conserving projection. C. Add the following lines of code to the ElseIF statement The following code retrieves the shapefile that we added to the map earlier. Dim myWorldShape As New MapWinGIS.Shapefile myWorldShape = g_MapWin.Layers(0).GetObject() A temporary variable called myProjection is used to hold a string defining an equal area projection. Dim myProjection As String myProjection = "+proj=cea +lon_0=0 +lat_ts=0 +x_0=0 +y_0=0_ +ellps=WGS84 +datum=WGS84 +units=m +no_defs" The variable tmpShapePath is used to store the path to a temporary shapefile we will use to store the reprojected data set. Dim tmpShapePath As String tmpShapePath = myWorldShape.Filename.Replace(".shp","prj.shp") MapWinGeoPro is the MapWindow GIS processing library. In this case the SpatialReference.ProjectShapefile is being used to reproject the myWorldShape shapefile and create a new temporary file. MapWinGeoProc.SpatialReference.ProjectShapefile(myWorldShape.P rojection, myProjection, myWorldShape.Filename, tmpShapePath)

Chapter 5: Basic Examples of Plug-ins

57

Next myProjWorld is created to store to load the re-projected data from the disk. Dim myProjWorld As New MapWinGIS.Shapefile myProjWorld.Open(tmpShapePath) The next line enables editing the shapefiles attribute table. myWorldShape.StartEditingTable() This delcares a new field for the attribute and defines its name, the type of data stored in it, how wide to make it, and finally inserts the column into column possition 0. Dim myNewField As New MapWinGIS.Field myNewField.Name = "Area" myNewField.Type = FieldType.DOUBLE_FIELD myNewField.Width = 15 myWorldShape.EditInsertField(myNewField, 0) Once the area of the plygon is calculated, a variable is defined to temporarily hold the area. Dim myArea As Double This loop cycles through all the shapes in the projected shapefile and calculates their area. Since the shapefile is in meters, the resulting area is in square meters. This is not practical, so the MapWinGeoProc.UnitConverter.ConvertArea(...) is used to convert the value to hectares. Finally the value is stored in the corresponding cell of the original shapefile. For I As Integer = 0 To myProjWorld.NumShapes myArea = MapWinGeoProc.Utils.Area(myProjWorld.Shape(I)) myArea = MapWinGeoProc.UnitConverter.ConvertArea(_ UnitOfMeasure.Meters, UnitOfMeasure.Hectares, myArea) myWorldShape.EditCellValue(0, I, myArea) Next D. Now run your plug-in E. Add the My World layer to the map by clicking My First Plug-in -> Add Data F. Calculate the area of each country by clicking My First Plug-in -> Calculate Area

58

Exercise 3: Calculating a Polygons Neighbor

G. Now examine the attribute table of the My World layer by right clicking on it in the legend and selecting View Attribute Table Editor from the drop down menu

H. Close MapWindow and save your project by clicking File -> Save All

Chapter 5: Basic Examples of Plug-ins

59

60

Chapter 6: Advanced Examples of Plug-ins


One of the best ways to understand what is possible in plug-in development is to look at examples and learn how they work. Working through examples is beneficial while learning the basics, but ultimately is no substitute for independent examination of well documented code. Go to http://www.mapwindow.org/download.php and download the Sample MapWindow Plug-in Project: Path Analyzer. This plug-in analyzes the terrain under a line out put elevation. It shows several different methods of working with data and other tools in MapWindow GIS. Carefully studying this code will allow you to accomplish most tasks with MapWindow GIS. Further help can be sought on the MapWindow website in the form of an active community forum, as well as wiki.

Chapter 5: Basic Examples of Plug-ins

61

62

FOSS4G Conference Lab / Workshop comments page


How effective was the presenters lecture? ___________________________________________________________________________ ___________________________________________________________________________ ___________________________________________________________________________

How helpful were the tutorials? ___________________________________________________________________________ ___________________________________________________________________________ ___________________________________________________________________________ Was there any material that you would have liked to see but did not? ___________________________________________________________________________ ___________________________________________________________________________ ___________________________________________________________________________

Do you have any suggestions for improving future labs and workshops? ___________________________________________________________________________ ___________________________________________________________________________ ___________________________________________________________________________

Chapter 5: Basic Examples of Plug-ins

63

Anda mungkin juga menyukai