Saving Program Settings

March 2, 2009

As I have written of previously, here, I use XML files to save program settings.  The types of settings I am saving are:

  • Default PMF locations (Directories)
  • Field Names

programsettings

The code to save the settings is:

Private Sub cmdSave_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles cmdSave.Click
‘Program Defaults
objSettings.blnWriteString(“Program”, “DefaultPath”, (txtDefaultPath.Text))
objSettings.blnWriteString(“Program”, “DefaultMap”, (txtDefaultMap.Text))
objSettings.blnWriteBoolean(“Program”, “DefaultLayers”, CStr(chkDefaultLayers.CheckState))

‘Parcel Query Defaults
objSettings.blnWriteString(“ParcelQuery”, “ParcelFile”, (Me.txtParcelFile).Text)
objSettings.blnWriteString(“ParcelQuery”, “ParcelID”, (Me.txtParcelID).Text)
objSettings.blnWriteString(“ParcelQuery”, “OwnerName”, (Me.txtOwner).Text)
objSettings.blnWriteString(“ParcelQuery”, “HouseNumber”, (Me.txtHouseNum).Text)
objSettings.blnWriteString(“ParcelQuery”, “StreetName”, (Me.txtStreetName).Text)
objSettings.blnWriteString(“ParcelQuery”, “Map”, (Me.txtMap).Text)
objSettings.blnWriteString(“ParcelQuery”, “Group”, (Me.txtGroup).Text)
objSettings.blnWriteString(“ParcelQuery”, “Parcel”, (Me.txtParcel).Text)

‘Street Query Defaults
objSettings.blnWriteString(“StreetQuery”, “StreetField”, (Me.txtStreetField).Text)
objSettings.blnWriteString(“StreetQuery”, “StreetID”, (Me.txtStreetID).Text)
objSettings.blnWriteString(“StreetQuery”, “StreetFile”, (Me.txtStreetFile).Text)

‘destroy the class, this causes the class_finalize
‘event which saves the settings to persist in the
‘disk file
objSettings.blnSaveFile()
‘objSettings = Nothing
Call sGetCurvSettings()
Me.Close()
End Sub

The code to load the settings is:

Private Sub ProgramSettings_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
‘Program Defaults
Me.txtDefaultPath.Text = objSettings.strReadString(“Program”, “DefaultPath”, “”)
Me.txtDefaultMap.Text = objSettings.strReadString(“Program”, “DefaultMap”, “”)
chkDefaultLayers.Checked = objSettings.blnReadBoolean(“Program”, “DefaultLayers”, False)

‘Parcel Query Defaults
Me.txtParcelFile.Text = objSettings.strReadString(“ParcelQuery”, “ParcelFile”, “”)
Me.txtParcelID.Text = objSettings.strReadString(“ParcelQuery”, “ParcelID”, “”)
Me.txtOwner.Text = objSettings.strReadString(“ParcelQuery”, “OwnerName”, “”)
Me.txtHouseNum.Text = objSettings.strReadString(“ParcelQuery”, “HouseNumber”, “”)
Me.txtStreetName.Text = objSettings.strReadString(“ParcelQuery”, “StreetName”, “”)
Me.txtMap.Text = objSettings.strReadString(“ParcelQuery”, “Map”, “”)
Me.txtGroup.Text = objSettings.strReadString(“ParcelQuery”, “Group”, “”)
Me.txtParcel.Text = objSettings.strReadString(“ParcelQuery”, “Parcel”, “”)

‘Street Query Defaults
Me.txtStreetFile.Text = objSettings.strReadString(“StreetQuery”, “StreetFile”, “”)
Me.txtStreetID.Text = objSettings.strReadString(“StreetQuery”, “StreetID”, “”)
Me.txtStreetField.Text = objSettings.strReadString(“StreetQuery”, “StreetField”, “”)
End Sub

I also use the following function to save the Program settings as global varials for use throughout the program:

Public Sub sGetCurvSettings()

‘Program Defaults
gtxtDefaultPath = objSettings.strReadString(“Program”, “DefaultPath”, “”)
gtxtDefaultMap = objSettings.strReadString(“Program”, “DefaultMap”, “”)
gysnDefaultLayers = objSettings.blnReadBoolean(“Program”, “DefaultLayers”, False)

‘Parcel Query Defaults
gtxtParcelFile = objSettings.strReadString(“ParcelQuery”, “ParcelFile”, “”)
gtxtParcelID = objSettings.strReadString(“ParcelQuery”, “ParcelID”, “”)
gtxtOwner = objSettings.strReadString(“ParcelQuery”, “OwnerName”, “”)
gtxtHouseNum = objSettings.strReadString(“ParcelQuery”, “HouseNumber”, “”)
gtxtStreetName = objSettings.strReadString(“ParcelQuery”, “StreetName”, “”)
gtxtMap = objSettings.strReadString(“ParcelQuery”, “Map”, “”)
gtxtGroup = objSettings.strReadString(“ParcelQuery”, “Group”, “”)
gttxtParcel = objSettings.strReadString(“ParcelQuery”, “Parcel”, “”)

‘Street Query Defaults
gtxtStreetFile = objSettings.strReadString(“StreetQuery”, “StreetFile”, “”)
gtxtStreetID = objSettings.strReadString(“StreetQuery”, “StreetID”, “”)
gtxtStreetField = objSettings.strReadString(“StreetQuery”, “StreetField”, “”)
End Sub

Global variables:

Public objSettings As New xmlrw(“CURVSettings.xml”)
‘Program Settings
Public gtxtDefaultPath As String
Public gtxtDefaultMap As String
Public gysnDefaultLayers As Boolean

‘Parcel Search Settings
Public gtxtParcelFile As String
Public gtxtParcelID As String
Public gtxtOwner As String
Public gtxtHouseNum As String
Public gtxtStreetName As String
Public gtxtMap As String
Public gtxtGroup As String
Public gttxtParcel As String

‘Street Query Defaults
Public gtxtStreetFile As String
Public gtxtStreetID As String
Public gtxtStreetField As String

‘Layer Indexes
Public gintGroupIndex As Short
Public gintLayerIndex As Short


Saving Map Settings

March 1, 2009

One of the first things I want to be able to do with my ArcReadercontrol Viewer is be able to save program and map settings.  I have some experience with VB 6 and considered using INI files.  In the course of my research for upgrading to VB.net I became aware the INI files were strongly discouraged (INI Files Will Never Die: How-To in .NET).  With a little digging, I found that the same functionality of INI files could be found by using XML files.

XML Demo

A program that demonstrates how to persist VB.NET application settings using an XML document. This is basically notice the pun an example of how to use an XML file to persist settings in your application. The coding convention is the same as the VB SaveSettings or GetSettings, also the same as the old INI file convention. You use a Section to separate different types of settings then a key=value pair to store individual settings.

The sample from XML Demo works well, but I did need to make 1 change to the code to make it work:

I Changed:

Private Function blnSaveFile() As Boolean
‘private function used by the class to
’save current settings to the file, this
‘function is called on class_finalize, when
‘the object representing the class is destroyed
‘or set to nothing

m_xmld_File.Save(m_str_File_Name)

End Function

To:

Public Function blnSaveFile() As Boolean
‘private function used by the class to
’save current settings to the file, this
‘function is called on class_finalize, when
‘the object representing the class is destroyed
‘or set to nothing

m_xmld_File.Save(m_str_File_Name)

End Function

I created 2 functions that use the sample code from XML Demo.  These function are accessed via Menu items, Save Map Settings and Load Map Settings.

mapsettingsSave Map Settings:

Private Sub SaveMapToolStripMenuItem_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles SaveMapToolStripMenuItem.Click
Dim strFileName As String
Dim saveFileDialog1 As New SaveFileDialog()
saveFileDialog1.Title = “Select Location to Save Map Settings”
saveFileDialog1.Filter = “Curv Files (*.curv)|*.curv”
saveFileDialog1.RestoreDirectory = True

If saveFileDialog1.ShowDialog() = DialogResult.OK Then
strFileName = saveFileDialog1.FileName
Dim objMapSettings As New xmlrw(strFileName)
Dim varLayerInfo() As String
Dim i As Integer
Dim strKey As String
Dim strValue As String
Dim intLayers As Integer
Dim strCoords As String
Dim dXmin As Double, dYmin As Double, dXmax As Double, dYmax As Double
conARMap.ARPageLayout.FocusARMap.GetExtent(dXmin, dYmin, dXmax, dYmax)
strCoords = dXmin & “,” & dYmin & “,” & dXmax & “,” & dYmax
intLayers = fCountLayers()
varLayerInfo = fSetLayerIndexes(intLayers)
objMapSettings.blnWriteString(“Layers”, “SettingsForMap”, cmbMapSelection.Text)
objMapSettings.blnWriteString(“Layers”, “LayerExtents”, strCoords)
objMapSettings.blnWriteString(“Layers”, “Count”, CStr(intLayers))
For i = LBound(varLayerInfo) To UBound(varLayerInfo)
strValue = varLayerInfo(i)
If Len(strValue) > 0 Then
strKey = “Layer” & i
strValue = varLayerInfo(i)
objMapSettings.blnWriteString(“Layers”, strKey, strValue)
Else
i = 1001
End If
Next i
‘destroy the class, this causes the class_finalize
‘event which saves the settings to persist in the
‘disk file
objMapSettings.blnSaveFile()
objMapSettings = Nothing
End If
End Sub

I will try to explain the code:


Dim strFileName As String
Dim saveFileDialog1 As New SaveFileDialog()
saveFileDialog1.Title = “Select Location to Save Map Settings”
saveFileDialog1.Filter = “Curv Files (*.curv)|*.curv”
saveFileDialog1.RestoreDirectory = True

Open a save dialog and select a file to create.

If saveFileDialog1.ShowDialog() = DialogResult.OK Then

If a user selects a file and hits OK in the save dialog, continue.

Dim objMapSettings As New xmlrw(strFileName)

Create the save file via the xml class

Dim dXmin As Double, dYmin As Double, dXmax As Double, dYmax As Double
conARMap.ARPageLayout.FocusARMap.GetExtent(dXmin, dYmin, dXmax, dYmax)
strCoords = dXmin & “,” & dYmin & “,” & dXmax & “,” & dYmax

Get the coords of the map.

intLayers = fCountLayers()

Count the number of layers in the map (See Supporting Subs and Functions below)

varLayerInfo = fSetLayerIndexes(intLayers)

Create an Array of Layer index numbers, used to save layer index as well as visibility, ie on or off. (See Supporting Subs and Functions below)

objMapSettings.blnWriteString(“Layers”, “SettingsForMap”, cmbMapSelection.Text)
objMapSettings.blnWriteString(“Layers”, “LayerExtents”, strCoords)
objMapSettings.blnWriteString(“Layers”, “Count”, CStr(intLayers))
For i = LBound(varLayerInfo) To UBound(varLayerInfo)
strValue = varLayerInfo(i)
If Len(strValue) > 0 Then
strKey = “Layer” & i
strValue = varLayerInfo(i)
objMapSettings.blnWriteString(“Layers”, strKey, strValue)
Else
i = 1001
End If
Next i
‘destroy the class, this causes the class_finalize
‘event which saves the settings to persist in the
‘disk file
objMapSettings.blnSaveFile()
objMapSettings = Nothing
End If
End Sub

Save the settings to a file.

Load Map Settings

Sub sLoadDefaults()

OpenFileDialog1.Title = “Select a Map Settings File”
OpenFileDialog1.Filter = “Curv Files (*.curv)|*.curv”
OpenFileDialog1.ShowDialog()

‘Exit if no map document is selected
Dim sFilePath As String
sFilePath = OpenFileDialog1.FileName
If sFilePath = “” Then Exit Sub
Dim objMapSettings As New xmlrw(sFilePath)
Dim i As Integer
Dim strValue As String
Dim strKey As String
Dim intLayers As Integer
Dim intGroup As Integer
Dim intChild As Integer
Dim ysnLayerOnOff As Boolean
Dim arrString() As String
Dim arrCoords() As String
Dim strMapName As String
Dim strCoords As String
Dim dXmin As Double, dYmin As Double, dXmax As Double, dYmax As Double
strMapName = objMapSettings.strReadString(“Layers”, “SettingsForMap”, “”)
If cmbMapSelection.Text <> strMapName Then
Exit Sub
End If
strCoords = objMapSettings.strReadString(“Layers”, “LayerExtents”, “”)
arrCoords = Split(strCoords, “,”, -1)
dXmin = CDbl(arrCoords(0))
dYmin = CDbl(arrCoords(1))
dXmax = CDbl(arrCoords(2))
dYmax = CDbl(arrCoords(3))
conARMap.ARPageLayout.FocusARMap.SetExtent(dXmin, dYmin, dXmax, dYmax)
intLayers = CInt(objMapSettings.strReadString(“Layers”, “Count”, “”))
For i = 0 To intLayers – 1
If intLayers > 0 Then
strKey = “Layer” & i
strValue = objMapSettings.strReadString(“Layers”, strKey, “”)
arrString = Split(strValue, “,”, -1)
intGroup = CInt(arrString(0))
intChild = CInt(arrString(1))
ysnLayerOnOff = (arrString(2))
Call sLayerOn(intGroup, intChild, ysnLayerOnOff)
End If
Next i
conARMap.ARPageLayout.FocusARMap.Refresh()
objMapSettings = Nothing
End Sub

I will attempt to explain key points:

OpenFileDialog1.Title = “Select a Map Settings File”
OpenFileDialog1.Filter = “Curv Files (*.curv)|*.curv”
OpenFileDialog1.ShowDialog()

Open “Open File” dialog box

strMapName = objMapSettings.strReadString(“Layers”, “SettingsForMap”, “”)
If cmbMapSelection.Text <> strMapName Then
Exit Sub
End If

Check that the Map Settings file being opened matches the current, open PMF file, if it does not match, stop loading.

strCoords = objMapSettings.strReadString(“Layers”, “LayerExtents”, “”)
arrCoords = Split(strCoords, “,”, -1)
dXmin = CDbl(arrCoords(0))
dYmin = CDbl(arrCoords(1))
dXmax = CDbl(arrCoords(2))
dYmax = CDbl(arrCoords(3))
conARMap.ARPageLayout.FocusARMap.SetExtent(dXmin, dYmin, dXmax, dYmax)
intLayers = CInt(objMapSettings.strReadString(“Layers”, “Count”, “”))
For i = 0 To intLayers – 1
If intLayers > 0 Then
strKey = “Layer” & i
strValue = objMapSettings.strReadString(“Layers”, strKey, “”)
arrString = Split(strValue, “,”, -1)
intGroup = CInt(arrString(0))
intChild = CInt(arrString(1))
ysnLayerOnOff = (arrString(2))
Call sLayerOn(intGroup, intChild, ysnLayerOnOff)
End If
Next i
conARMap.ARPageLayout.FocusARMap.Refresh()
objMapSettings = Nothing
End Sub

Load the settings from the file use the Split function to break apart strings into an array (Split(strValue, “,”, -1))

Supporting Subs and Functions

Count Layers in the map.

Public Function fCountLayers() As Integer

Dim i As Integer
Dim j As Integer
Dim pLayer As ARLayer
Dim intLayerCount As Integer
intLayerCount = frmMain.conARMap.ARPageLayout.FocusARMap.ARLayerCount – 1
Dim intCounter As Integer
intCounter = 0
‘Loop through each layer in the focus map
For i = 0 To intLayerCount
pLayer = frmMain.conARMap.ARPageLayout.FocusARMap.ARLayer(i)
If pLayer.IsGroupLayer = False Then
‘If the layer is searchable add layer
‘to collection, and name to combo box
Else
For j = 0 To pLayer.ARLayerCount – 1
intCounter = intCounter + 1
Next j
End If
Next i

fCountLayers = intCounter
End Function

Create string with layer group index, layer index, and on/off state

Public Function fSetLayerIndexes(ByVal pintLayerCount As Integer) As String()

Dim i As Integer
Dim j As Integer
Dim pLayer As ARLayer
Dim intLayerCount As Integer
Dim strValue As String
intLayerCount = frmMain.conARMap.ARPageLayout.FocusARMap.ARLayerCount – 1
Dim arr() As String
Dim intCounter As Integer
intCounter = 0
ReDim arr(pintLayerCount)
‘Loop through each layer in the focus map
For i = 0 To intLayerCount
pLayer = frmMain.conARMap.ARPageLayout.FocusARMap.ARLayer(i)
If pLayer.IsGroupLayer = False Then
‘If the layer is searchable add layer
‘to collection, and name to combo box
Else
For j = 0 To pLayer.ARLayerCount – 1
strValue = i & “,” & j & “,” & pLayer.ChildARLayer(j).Visible
arr(intCounter) = strValue
intCounter = intCounter + 1
Next j
End If
Next i
fSetLayerIndexes = arr
End Function


ArcReaderControl

February 15, 2009

Recently i have begun program a GIS viewer utilizing the arcreadercontrol. i wanted the viewer to have as much flexibility as possible. Some of the feature i am attempting to to include are:

  • Saved program settings
  • Saved map settings
    • zoom level
    • layer status(on/off)
  • Custom searches
  • Geocoding

currently, i have all functionality i desired working with the exception of text mark up. in the following posts i will attempt to detail how each item of functionality was accomplished.

Saved Program Settings

There are several reasons to save program settings.  In the case of the people I work with I find it easier to store the path to GIS data and projects within my programs.  I also, as stated earlier, want to be able to to build some custom searches.  The layer I want to be able to search is a parcel layer.  The parcel data I plan to search is from several different counties.  Unfortunately, due to naming conventions used in each county the field names are not always the same.  Therefore i need to save the field names as settings.

Saved Map Settings

On of the biggest frustrations, I have with ArcReader is the inability to save map settings.  For example, if I am working with a PMF files with many different layers, I would like the ability to save layers visibility based on the last setup I used.  With the standalone ArcReader application this is impossible.  I will work around this limitation in the custom viewer.

Custom Searches

The GIS users I work with tend to heavily utilize the available parcel layers.  To help facilitate their work I plan to create some customized searches to supplement the built in “Find” commands.  Alt hough the “Find” command is suitable for searching a single field, it does not handle searching multiple criteria.

Geocoding

The Geocoding functionailty availbe in ArcReader is limited to the ArcWeb Services Locators.  ArcReader and ArcReadercontrol can not utilize file based address locators.  I will attempt to see if there is a work around to allow file based geocoding.