Part V: Learning the Basics of ArcObjects Programming
Project 1 - Part V: Learning the Basics of ArcObjects Programming
Before we can do any sophisticated customization, we have a lot of basic concepts to cover.
Begin by reviewing the following topics in the Concept Gallery:
A. Illustrating the Concepts
It's OK if you are confused at this point. We'll use a very simple program to illustrate these concepts.
- Re-open the Lesson1.sln Visual Studio project.
- Confirm that you have Option Explicit set to “on”. To find this setting, go to Tools > Options and select Projects and Solutions > VB Defaults. Check that Option Explicit is set to “on”.
- With Option Explicit turned on, if you try to run a procedure that has an undeclared variable, the editor will give you an error message. It's generally good programming practice to use Option Explicit. If you don't, undeclared variables are treated as variants, which means they are allocated a large amount of memory. This can result in a waste of memory resources and slower code execution.
- The procedure written earlier in the lesson was designed to execute when a click button event was triggered. We will add a new Add-In button for our practice in this part of the lesson.
- Right-click on the name of the project in the Visual Studio Solution Explorer on the right and select Add>New Item. Select ArcGIS > Desktop Add-Ins and choose Add-In Component on the right. Name your new Add-In “Button2.vb”.
- Walk through the Add-In wizard and make a new button with the same category selected earlier (“GEOG489_Lesson1”). You should also choose a new icon so this tool will be distinguishable from the first button. After clicking Finish, you should have a new button class named “Button2.vb” present in the Visual Studio project.
- Copy and paste the following code into the Button2.vb OnClick procedure:
Dim pMxDoc As IMxDocument
pMxDoc = My.ArcMap.Application.Document
Dim pMap As IMap
pMap = pMxDoc.FocusMap
Dim pFLayer As IFeatureLayer2
pFLayer = pMap.Layer(0)
Dim strDisplayField As String
strDisplayField = pFLayer.DisplayField
MsgBox(strDisplayField, vbOKOnly, "Test")
- Note that there are “blue squiggles” (potential compile errors) under the names IMxDocument, IMap, FocusMap and IFeatureLayer2. Let’s fix that using Visual Studio’s intellisense abilities. Move your cursor over a word with the “blue squiggle” (IMxDocument). There should be a small red exclamation mark popup under the selected word. Move your cursor over to the red exclamation mark and left-click the mouse. This presents another popup window with the message “Type IMxDocument is not defined” and the window presents some options for automatically fixing the issue. Select the option “Import ESRI.ArcGIS.ArcMapUI”. Visual Studio just added an Imports statement at the top of the document and the blue squiggles went away from IMxDocument.
Note: Imports statements are a shortcut to allow you to refer to externally referenced objects by their short names and not their "fully qualified" name. For example, without an Imports statement, you could refer to the IMxDocument interface with this fully qualified name: ESRI.ArcGIS.ArcMapUI.IMxDocument. After adding the Imports statement, you can refer simply to IMxDocument.
- Do the same procedure for the “blue squiggles” under IMap, FocusMap and IFeatureLayer2. Note that the popup window offers no solution for fixing the problem with the IMap interface name. This is because the ESRI.ArcGIS.Carto assembly is not yet referenced in the project. Next, move on to hover your cursor over the FocusMap error "squiggles". Note that the solution offered in the popup is different in that Visual Studio wants to create a new assembly reference. Select the only option presented to reference the ESRI.ArcGIS.Carto assembly. Next, when you hover your cursor over the IFeatureLayer2 interface name, you should be able to create an Imports statement to load the ESRI.ArcGIS.Carto assembly reference, which will also fix the problem with the IMap type name. This should have fixed all of the “blue squiggle” errors which would have caused compile errors when we build the project.
Note: Referencing an assembly is a way to access programming objects in external code libraries, usually .DLL files. Generally you want to reference as few external assemblies as possible so that your compiled code doesn't have to include copies of unnecessary code libraries. You will need to add several ESRI assemblies to your projects in this course. Until you add a needed assembly reference, you will get compile errors when you try to reference objects only found in those assemblies.
- Click Build > Build Lesson 1. Make sure your build was successful. You should have success or error messages in the "Output" window at the bottom of Visual Studio. If you have errors, carefully examine the error message to see if you can pinpoint where the problem is coming from. If you get stuck, please post your problem to the forum and/or email the instructor.
Assuming that you had no errors, open up ArcMap and go to the customize dialog to add the newly updated Lesson1.esriAddIn file into the ArcMap document, using your earlier experience as a guide. You should receive confirmation of what buttons were just added to the ArcMap document. In the customize dialog, select the Commands tab and scroll down to the category GEOG489_Lesson1. Find your new button and drag it onto a toolbar.
- Click the new button to run your procedure. This simple procedure finds the name of the primary display field in the topmost layer and reports it to the user. Exciting, huh? Let's walk through the procedure line-by-line.
The first two lines of the procedure are used to obtain a pointer to the current map document object. MxDocument is the name of the class that represents map documents and IMxDocument is the interface used to gain access to its most important properties and methods. Line 1 declares a variable that is a pointer to the IMxDocument interface. My.ArcMap.Application.Document is a convenient variable available in the Add-In framework that references the currently opened map document through the IDocument interface. So, Line 2 is an example of a QueryInterface (QI) operation. We initialize our pMxDoc variable to point to the current map document by setting it equal to My.ArcMap.Application.Document.
When working with ArcObjects, there are a couple of naming conventions you'll need to get used to. All interface names begin with the letter "I." By convention, a variable that points to an ArcObjects interface begins with the letter "p" (for "pointer"). The "p" is lower-case, while other letters in the name are capitalized to increase readability. Keep in mind that you have control over the naming of variables. For example, you could spell out the name completely (pMxDocument) to match the name of the interface. The important point to remember is that ArcObjects programmers tend to follow this convention. If you also follow the convention, your code will be more readable when you share it with others.
Now that we have pMxDoc, we can get a pointer to the active data frame. Recall that earlier I mentioned that what the typical ArcGIS user refers to as a data frame, an ArcObjects programmer refers to as a map. The IMxDocument interface (referenced by the pMxDoc variable) supports a property called FocusMap. The FocusMap property returns a Map object, whose most commonly used interface is IMap. In order to store the object returned by FocusMap, we first declare a variable pMap of type IMap.
Having obtained a reference to the active data frame, we can get a reference to the topmost layer in the dataframe (probably Cities in this example). The IMap interface does not provide a property or method that allows you to get a layer by name. However, there are ways to obtain a specific layer which we'll discuss later in the course. In this example, we're using the IMap interface's Layer property with an argument of 0 to obtain the topmost layer. The 0 argument returns the first layer in the data frame, 1 would return the second. (More on this topic later.) We declare a variable pFLayer of typeIFeatureLayer2 to reference the object returned by the Layer property.
One of the properties all feature layers share is a primary display field (found under the Fields tab in Layer Properties). This is the default field for labeling, the field that appears when you use the Identify tool, etc. In the next part of the procedure, we use the DisplayFieldproperty of the IFeatureLayer2 interface. This returns a string, so we declare a variable strDisplayField of type String to store the result.
Finally, we report to the user using the VB MsgBox function. MsgBox requires one string argument and has two optional arguments. The required string is the text that you want to appear in the message box. In this instance, we included the two optional arguments. The first optional argument specifies what kinds of buttons you want to display. The next argument specifies the name you'd like to appear in the title bar of the message box.
Note: MsgBox is a Visual Basic specific function that is included to be backward compatible with the older VB6 and VBA languages. It is not available in other .NET languages like C#. There is another similar function that you can use in all .NET languages, called MessageBox. To display a MessageBox, you call its Show method like this: MessageBox.Show("My message here"). However, we will be using MsgBox in this course as much of the sample code was originally written in VBA.
An important point to note about the MsgBox line is that one string argument is supplied as a variable and the other by a literal string. It would also be perfectly reasonable to specify each as a variable. For example, we could add the following two lines to the procedure:
Dim strWindowName As String
strWindowName = "Test"
then change the last line to read:
MsgBox (strDisplayField, vbOKOnly, strWindowName)
Another point that this procedure emphasizes is that some properties and methods return simple data values like strings and integers, while others return references to objects that implement other interfaces (e.g., the FocusMap property of the IMxDocument interface returns aMap object, which implements the IMap interface).
In Lesson 2 you'll learn how to find information about classes, interfaces, properties and methods, information you'll need to begin building your own programs.
That's it for Part V!
You have just completed Part V of the project, which involved learning the basics of ArcObjects programming. In Part VI, you will get a chance to practice writing some simple VB programs.