This article mainly introduces how to use C # to develop geographic information systems with ArcGISEngine. ArcGISEngine allows programmers to create custom GIS desktop programs on Windows systems. For more information, see
Simple map reading and display
It's finally summer vacation... I began to carefully organize my learning experiences ~
First, fill in the pitfalls of C # secondary development that have been dug a long time ago ~ This time, I plan to release C # ArcEngine 10.0 development experiences in one month ~
The first part is the simplest helloworld: understanding how to use controls to create simple GIS applications ~
(The environment configuration is omitted in the early stage ~ Please use Baidu ~)
First, open VS2010, and create a Windows form application named "MyHelloWorld" through (file -- new -- project -- S form application. Then, enter the control:
Find the ArcGIS Engine-related controls in the VS Toolbox. here we use AxTOCControl, AxLicenseControl, and MapControl, here, MapControl corresponds to the data view in ArcMap. it encapsulates the Map object and provides additional attributes, methods, and events. It is an essential part of a series of development processes.
After the three controls are arranged, the results are shown in:
Note:
1. the AxLicenseControl control is required for Arcengine development. without it or without the ArcEngine Lisence license, we cannot call any GIS function.
2. after dragging the three controls into the form, we will find that the system automatically imports the reference, but whether it is imported by the system itself or manually, note: set "copy local" in the reference property to False. otherwise, code may fail to run.
After the control is set, open Program. cs and add the following code at the system entrance:
ESRI.ArcGIS.RuntimeManager.Bind(ESRI.ArcGIS.ProductCode.EngineOrDesktop);
This is mainly set for changes in Arcgis10.0. the added code is as follows:
namespace MyHelloWorld { static class Program { /// /// The main entry point for the application. /// [STAThread] static void Main() { ESRI.ArcGIS.RuntimeManager.Bind(ESRI.ArcGIS.ProductCode.EngineOrDesktop); Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); Application.Run(new Form1());
Next, we can add the required tools to the ToolbarControl by setting and editing its attributes. remember to set the attributes of the ToolBar control and the axTOCCControl1 control, set the Buddy option of the ToolBar to axTOCCControl1 to associate the two.
In the attribute settings of ToolbarControl, right-click the -- attribute -- Item button to set the required tools for the Toolbar control. here I have selected some common tools: save, move, undo, zoom in, zoom out, and so on, as shown in:
After all the settings, the content in Chapter 1 is basically over. after the program is debugged, the final effect is as follows: a simplest GIS desktop program will come out ~~
Open a map document and create an EagleEye chart
First, create a button to open the map document:
Drag the Button control in the toolbox to our Form, and then call the OpenFileDialog class in the Cilck event of the button to obtain the file path,
Call the file path to axMapControl1.LoadMxFile (path) to open the MXD document.
Private void button1_Click (object sender, EventArgs e) {OpenFileDialog OpenMXD = new OpenFileDialog (); OpenMXD. title = "Open map"; OpenMXD. initialDirectory = "E:"; OpenMXD. filter = "Map Documents (*. mxd) | *. mxd "; if (OpenMXD. showDialog () = DialogResult. OK) {string MxdPath = OpenMXD. fileName; axMapControl1.LoadMxFile (MxdPath );}}
You can open the shape file in the same way, but note the following:
In the axMapControl1.AddShapeFile () method, you do not directly enter the file path like LoadMx, but AddShapeFile (filePath, fileName ), therefore, we need to write a function to split the file path string:
Private void button2_Click (object sender, EventArgs e) {string [] S = OpenShapeFile (); try {axMapControl1.AddShapeFile (S [0], S [1]);} catch {MessageBox. show ("select at least one shape file", "ERROR") ;}} public string [] OpenShapeFile () {string [] ShpFile = new string [2]; openFileDialog OpenShpFile = new OpenFileDialog (); OpenShpFile. title = "Open Shape file"; OpenShpFile. initialDirectory = "E:"; OpenShpFile. filter = "Shape File (*. shp) | *. shp "; if (OpenShpFile. showDialog () = DialogResult. OK) {string ShapPath = OpenShpFile. fileName; // use "\" to divide the file path into two parts: int Position = ShapPath. lastIndexOf ("\"); string FilePath = ShapPath. substring (0, Position); string ShpName = ShapPath. substring (Position + 1); ShpFile [0] = FilePath; ShpFile [1] = ShpName;} return ShpFile ;}
The result is as follows:
After this part is completed, the next step is to create an EagleEye image ~ :
The operation of the EagleEye chart is mainly divided into two parts. when you reload a chart in the main control, the chart of the other control also changes accordingly, the general idea is to add the same layer to MapControl2 after you open the main map, and constantly update the current range of the main map, then, draw a red box in the corresponding area of the EagleEye chart to indicate the corresponding range.
The IEnvelope and IPoint interfaces are used to obtain the coordinates of the mouse and draw a red box indicating the range. For more information, see here ~
Drag the second map control axMapControl2 into the form and use it as the EagleEye graph of axMapControl1.
First, write the OnMapReplaced event and OnExtentUpdated event of MapControl1. let's get the map range update of MapControl1, add layers to MapControl2, and draw rectangles:
Private void axmapcontrolpoliconextentupdated (object sender, ESRI. arcGIS. controls. IMapControlEvents2_OnExtentUpdatedEvent e) {// set a new external rectangle IEnvelope pEnvelope = (IEnvelope) e. newEnvelope; export pGraphicsContainer = axMapControl2.Map as IGraphicsContainer; IActiveView pActiveView = pGraphicsContainer as IActiveView; // clear any graphic element pGraphicsContainer in axMapControl2 before drawing. deleteAllElements (); IRectangleElement pRectangleEle = new RectangleElementClass (); IElement pElement = pRectangleEle as IElement; pElement. geometry = pEnvelope; // set the Red Line box IRgbColor pColor = new RgbColorClass (); pColor in the EagleEye chart. red= 255; pColor. green = 0; pColor. blue = 0; pColor. transparency = 255; // Generate a line symbol object ILineSymbol pOutline = new SimpleLineSymbolClass (); pOutline. width = 3; pOutline. color = pColor; // set the Color attribute pColor = new RgbColorClass (); pColor. red= 255; pColor. green = 0; pColor. blue = 0; pColor. transparency = 0; // Set the attribute IFillSymbol pFillSymbol = new SimpleFillSymbolClass (); pFillSymbol. color = pColor; pFillSymbol. outline = pOutline; IFillShapeElement pFillShapeEle = pElement as IFillShapeElement; pFillShapeEle. symbol = pFillSymbol; pGraphicsContainer. addElement (IElement) pFillShapeEle, 0); pActiveView. partialRefresh (esriViewDrawPhase. esriViewGraphics, null, null); // display the map range in StripStatus IPoint ll, Ur; ll = axMapControl1.Extent. lowerLeft; Ur = axMapControl1.Extent. lowerRight; toolStripStatusLabel3.Text = "(" + Convert. toString (ll. x) + "," + Convert. toString (ll. y) + ")";} private void axmapcontrolpoliconmapreplaced (object sender, ESRI. arcGIS. controls. IMapControlEvents2_OnMapReplacedEvent e) {// add a layer to MapControl2 if (axMapControl1.LayerCount> 0) {axMapControl2.Map = new MapClass (); for (int I = 0; I <= axMapControl1.Map. layerCount-1; I ++) {axMapControl2.AddLayer (axMapControl1.get _ Layer (I);} axMapControl2.Extent = axMapControl1.Extent; axMapControl2.Refresh ();}}
The next step is to write the On_MouseDown and On_MouseMove events of the MapControl2 control, so that we can drag the red box on the EagleEye chart to reverse the map position in MapControl1:
Private void axMapControl2_OnMouseMove (object sender, ESRI. arcGIS. controls. IMapControlEvents2_OnMouseMoveEvent e) {if (e. button = 1) {IPoint pPoint = new PointClass (); pPoint. putCoords (e. mapX, e. mapY); axMapControl1.CenterAt (pPoint); axMapControl1.ActiveView. partialRefresh (esriViewDrawPhase. esriViewGeography, null, null) ;}} private void axMapControl2_OnMouseDown (object sender, ESRI. arcGIS. controls. IMapControlEvents2_OnMouseDownEvent e) {if (axMapControl2.Map. layerCount> 0) {if (e. button = 1) {IPoint pPoint = new PointClass (); // Set the coordinate transformation of the clicked position to the central pPoint of MapControl1. putCoords (e. mapX, e. mapY); axMapControl1.CenterAt (pPoint); axMapControl1.ActiveView. partialRefresh (esriViewDrawPhase. esriViewGeography, null, null);} else if (e. button = 2) {IEnvelope pEnv = axMapControl2.TrackRectangle (); axMapControl1.Extent = pEnv; axMapControl1.ActiveView. partialRefresh (esriViewDrawPhase. esriViewGeography, null, null );}}}
Add another statusStrip control in the lower left corner of Form to display the range of the current image in real time ~
The final result is as follows:
Access and display of attribute tables
Access and display the shapefile attribute table ~
The general idea is as follows: create a new Form to obtain the attribute table of the selected element, right-click the corresponding vector element on the initial interface, and then open the new form to display the element attribute table.
Start now ~
First, add ESRI. ArcGIS. Controls and Geodatabase references to update the namespace;
Then we add a new Form to display the content of the attribute table, add the dataGridView control to the new Form, and add Column.
In Form2, we predefine the data types of the available attribute tables:
Public static string ParseFieldType (esriFieldType fieldType) // Convert EsriType to String {switch (fieldType) {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 ";}}
Then we get the shpaefile attribute table. here we mainly use the IField, IFeatureCursor, IFeature interfaces to achieve the goal:
The interface is described as follows:
- IField interface: used to obtain the element table.
- IFeature interface: used to receive queried elements.
- IFeatureCursor interface: you can store the query results here through Search, and use the NextFeature method to traverse all elements.
The code is as follows:
public void Opentable() { 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 = System.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] = Convert.ToString(pFeature.Shape.GeometryType); } else fldValue[i] = Convert.ToString(pFeature.get_Value(i)); } dataGridView1.Rows.Add(fldValue); pFeature = pFeatureCursor.NextFeature(); } }
Done ~ The next step is to jump to the page to display the attribute table after selecting elements on the initial interface ~
Predefine in form1 first:
IFeatureLayer pFeatureLayer = null; public IFeatureLayer pGlobalFeatureLayer; // defines the global variable public ILayer player;
Because it is decided to display options when right-clicking the mouse, add the contextMenuStrip control to the Form1 form, add the option "Display attribute table", and open the new form in the click event:
Form2 Ft = new Form2(player as IFeatureLayer); Ft.Show();
Then we can ensure that the corresponding attribute table can be opened successfully after right-clicking the relevant layer elements. here we mainly use the HitTest () method of TOCControl:
Publicvoid HitTest (int X, int Y, ref esriTOCControlItem ItemType, ref IBasicMapBasicMap, ref ILayer Layer, ref object Unk, ref object Data );
Where
- X, Y: Coordinates of mouse clicks;
- ITemType: esriTOCControlItem enumeration constant
- BasicMap: IBasicMap interface bound to MapControl
- Layer: the Layer to be clicked.
- Unk: TOCControl LegendGroup object
- Data: Index of LegendClass in LegendGroup.
Add the following code to the OnMouseDown event of the TOCControl control ~ :
if (axMapControl1.LayerCount > 0) { esriTOCControlItem pItem = new esriTOCControlItem(); pGlobalFeatureLayer = new FeatureLayerClass(); IBasicMap pBasicMap = new MapClass(); object pOther = new object(); object pIndex = new object(); axTOCControl1.HitTest(e.x, e.y, ref pItem, ref pBasicMap, ref player, ref pOther, ref pIndex); } if (e.button == 2) { contextMenuStrip1.Show(axTOCControl1, e.x, e.y); }
Success ~~
The running result is as follows:
Right-click to display the attribute table:
The attribute table is displayed after you click it ~~~ :