<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://htyp.org/mw/index.php?action=history&amp;feed=atom&amp;title=User%3AWoozle%2FVB%2FSettings_manager%2Fsource_code</id>
	<title>User:Woozle/VB/Settings manager/source code - Revision history</title>
	<link rel="self" type="application/atom+xml" href="https://htyp.org/mw/index.php?action=history&amp;feed=atom&amp;title=User%3AWoozle%2FVB%2FSettings_manager%2Fsource_code"/>
	<link rel="alternate" type="text/html" href="https://htyp.org/mw/index.php?title=User:Woozle/VB/Settings_manager/source_code&amp;action=history"/>
	<updated>2026-07-10T19:37:38Z</updated>
	<subtitle>Revision history for this page on the wiki</subtitle>
	<generator>MediaWiki 1.45.3</generator>
	<entry>
		<id>https://htyp.org/mw/index.php?title=User:Woozle/VB/Settings_manager/source_code&amp;diff=6345&amp;oldid=prev</id>
		<title>Woozle: notes: *api and *xml (moved from overview page)</title>
		<link rel="alternate" type="text/html" href="https://htyp.org/mw/index.php?title=User:Woozle/VB/Settings_manager/source_code&amp;diff=6345&amp;oldid=prev"/>
		<updated>2007-01-01T23:23:35Z</updated>

		<summary type="html">&lt;p&gt;notes: *api and *xml (moved from overview page)&lt;/p&gt;
&lt;table style=&quot;background-color: #fff; color: #202122;&quot; data-mw=&quot;interface&quot;&gt;
				&lt;col class=&quot;diff-marker&quot; /&gt;
				&lt;col class=&quot;diff-content&quot; /&gt;
				&lt;col class=&quot;diff-marker&quot; /&gt;
				&lt;col class=&quot;diff-content&quot; /&gt;
				&lt;tr class=&quot;diff-title&quot; lang=&quot;en&quot;&gt;
				&lt;td colspan=&quot;2&quot; style=&quot;background-color: #fff; color: #202122; text-align: center;&quot;&gt;← Older revision&lt;/td&gt;
				&lt;td colspan=&quot;2&quot; style=&quot;background-color: #fff; color: #202122; text-align: center;&quot;&gt;Revision as of 23:23, 1 January 2007&lt;/td&gt;
				&lt;/tr&gt;&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot; id=&quot;mw-diff-left-l1&quot;&gt;Line 1:&lt;/td&gt;
&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot;&gt;Line 1:&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-side-deleted&quot;&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;==Notes==&lt;/ins&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-side-deleted&quot;&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;* The &quot;*API&quot; classes are [[abstract class]]es which define the basic Settings [[API]] without actually doing anything.&lt;/ins&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-side-deleted&quot;&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;* The &quot;*XML&quot; classes implement the API classes using [[MSXML2]] to load and save the data.&lt;/ins&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;==Code==&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;==Code==&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;===clsSettingAPI===&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;===clsSettingAPI===&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;</summary>
		<author><name>Woozle</name></author>
	</entry>
	<entry>
		<id>https://htyp.org/mw/index.php?title=User:Woozle/VB/Settings_manager/source_code&amp;diff=6340&amp;oldid=prev</id>
		<title>Woozle at 23:02, 1 January 2007</title>
		<link rel="alternate" type="text/html" href="https://htyp.org/mw/index.php?title=User:Woozle/VB/Settings_manager/source_code&amp;diff=6340&amp;oldid=prev"/>
		<updated>2007-01-01T23:02:31Z</updated>

		<summary type="html">&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;New page&lt;/b&gt;&lt;/p&gt;&lt;div&gt;==Code==&lt;br /&gt;
===clsSettingAPI===&lt;br /&gt;
This is an abstract class for translating between internal data and the string to actually save. It is implemented by [[#clsSettingText]] and [[#xtForm]].&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Option Explicit&lt;br /&gt;
&lt;br /&gt;
&amp;#039; CLASS: clsSettingAPI&lt;br /&gt;
&amp;#039; PURPOSE: abstract class for saving a single item&amp;#039;s settings&lt;br /&gt;
Public Name As String&lt;br /&gt;
Public Value As String&lt;br /&gt;
Public Sub Save(iNode As clsSettingsNodeAPI)&lt;br /&gt;
&amp;#039; abstract&lt;br /&gt;
End Sub&lt;br /&gt;
Public Sub Load(iNode As clsSettingsNodeAPI)&lt;br /&gt;
&amp;#039; abstract&lt;br /&gt;
End Sub&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
===clsSettingsAPI===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Option Explicit&lt;br /&gt;
&lt;br /&gt;
&amp;#039; CLASS: clsSettingsAPI&lt;br /&gt;
&amp;#039; PURPOSE: abstract settings-saving class&lt;br /&gt;
&lt;br /&gt;
Public Function Root() As clsSettingsNodeAPI&lt;br /&gt;
&amp;#039; ACTION: Return the root node&lt;br /&gt;
&amp;#039; USAGE: abstract; this is model code:&lt;br /&gt;
    Dim objRoot As clsSettingsNodeAPI&lt;br /&gt;
    &lt;br /&gt;
    Set objRoot = New clsSettingsNodeAPI&lt;br /&gt;
    objRoot.Init Me, Nothing&lt;br /&gt;
    Set Root = objRoot&lt;br /&gt;
End Function&lt;br /&gt;
Public Sub Load(iForce As Boolean)&lt;br /&gt;
&amp;#039; abstract&lt;br /&gt;
End Sub&lt;br /&gt;
Public Sub Save()&lt;br /&gt;
&amp;#039; abstract&lt;br /&gt;
End Sub&lt;br /&gt;
Private Sub Class_Initialize()&lt;br /&gt;
&amp;#039; abstract; sample code&lt;br /&gt;
    Me.Load False&lt;br /&gt;
End Sub&lt;br /&gt;
Private Sub Class_Terminate()&lt;br /&gt;
&amp;#039; abstract; sample code&lt;br /&gt;
    Me.Save&lt;br /&gt;
End Sub&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
===clsSettingsNodeAPI===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;#039; CLASS: clsSettingsNodeAPI&lt;br /&gt;
&amp;#039; PURPOSE: set of values for clsSettingsAPI&lt;br /&gt;
&amp;#039; USAGE: Abstract&lt;br /&gt;
&lt;br /&gt;
Option Explicit&lt;br /&gt;
Private objMain As clsSettingsAPI&lt;br /&gt;
Private objParent As clsSettingsNodeAPI&lt;br /&gt;
Friend Sub Init(iSettings As clsSettingsAPI, iParent As clsSettingsNodeAPI)&lt;br /&gt;
    Set objMain = iSettings&lt;br /&gt;
    Set objParent = iParent&lt;br /&gt;
End Sub&lt;br /&gt;
Public Property Get Name() As String&lt;br /&gt;
&amp;#039; abstract&lt;br /&gt;
End Property&lt;br /&gt;
Public Function Node(iName As String, iCreate As Boolean) As clsSettingsNodeAPI&lt;br /&gt;
&amp;#039; ACTION: Return the root node&lt;br /&gt;
&amp;#039; USAGE: abstract; this is model code:&lt;br /&gt;
    Dim objNode As clsSettingsNodeAPI&lt;br /&gt;
    &lt;br /&gt;
    Set objNode = New clsSettingsNodeAPI&lt;br /&gt;
&amp;#039; find subnode with name iName; initialize objNode with it (not Nothing)&lt;br /&gt;
    objNode.Init Me, Nothing&lt;br /&gt;
    Set Node = objNode&lt;br /&gt;
End Function&lt;br /&gt;
Public Function AddItem(iItem As clsSettingAPI) As clsSettingsNodeAPI&lt;br /&gt;
&amp;#039; ACTION: Add an item to the tree; return the item&amp;#039;s node object&lt;br /&gt;
&amp;#039; abstract&lt;br /&gt;
End Function&lt;br /&gt;
Public Property Get ValueStored() As String&lt;br /&gt;
&amp;#039; ACTION: Returns the *stored* value (not the active value)&lt;br /&gt;
&amp;#039; abstract&lt;br /&gt;
End Property&lt;br /&gt;
Public Property Let ValueStored(iValue As String)&lt;br /&gt;
&amp;#039; ACTION: Sets the *stored* value (not the active value)&lt;br /&gt;
&amp;#039; abstract&lt;br /&gt;
End Property&lt;br /&gt;
Public Sub Load()&lt;br /&gt;
&amp;#039; abstract&lt;br /&gt;
End Sub&lt;br /&gt;
Public Sub Save()&lt;br /&gt;
&amp;#039; abstract&lt;br /&gt;
End Sub&lt;br /&gt;
Public Property Get ListNodes() As Scripting.Dictionary&lt;br /&gt;
&amp;#039; abstract&lt;br /&gt;
End Property&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
===clsSettingsXML===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Private strSection As String&lt;br /&gt;
Private strAppName As String&lt;br /&gt;
Private strFileSpec As String&lt;br /&gt;
Private xmlDoc As MSXML2.DOMDocument&lt;br /&gt;
Private objRoot As clsSettingsNodeXML&lt;br /&gt;
Private isLoaded As Boolean&lt;br /&gt;
Public Sub Init(Optional iSection As String = &amp;quot;&amp;quot;, Optional iAppName As String = &amp;quot;&amp;quot;)&lt;br /&gt;
    If iSection &amp;lt;&amp;gt; &amp;quot;&amp;quot; Then&lt;br /&gt;
        strSection = iSection&lt;br /&gt;
    End If&lt;br /&gt;
    If iAppName &amp;lt;&amp;gt; &amp;quot;&amp;quot; Then&lt;br /&gt;
        strAppName = iAppName&lt;br /&gt;
    End If&lt;br /&gt;
    &lt;br /&gt;
    strFileSpec = App.Path &amp;amp; &amp;quot;\&amp;quot; &amp;amp; App.Title &amp;amp; &amp;quot;.prefs.xml&amp;quot;&lt;br /&gt;
    isLoaded = False&lt;br /&gt;
End Sub&lt;br /&gt;
Public Function Root() As clsSettingsNodeAPI&lt;br /&gt;
&amp;#039; ACTION: Return the root node&lt;br /&gt;
&amp;#039;    Dim objRootSet As clsSettingText&lt;br /&gt;
    Dim xmlRoot As MSXML2.IXMLDOMNode&lt;br /&gt;
    &lt;br /&gt;
    If objRoot Is Nothing Then&lt;br /&gt;
 &amp;#039;       Set objRootSet = New clsSettingText&lt;br /&gt;
 &amp;#039;       objRootSet.Init strSection, &amp;quot;&amp;quot;&lt;br /&gt;
        Set objRoot = New clsSettingsNodeXML&lt;br /&gt;
        With Me.GetXMLDoc&lt;br /&gt;
            If .childNodes.Length = 0 Then&lt;br /&gt;
                Stop    &amp;#039; this should never happen - GetXMLDoc is supposed to create the root node&lt;br /&gt;
            Else&lt;br /&gt;
                Set xmlRoot = .firstChild&lt;br /&gt;
            End If&lt;br /&gt;
        End With&lt;br /&gt;
        objRoot.InitRoot strSection, xmlRoot, Me&lt;br /&gt;
    End If&lt;br /&gt;
    Set Root = objRoot&lt;br /&gt;
End Function&lt;br /&gt;
Public Property Get FileSpec() As String&lt;br /&gt;
    FileSpec = strFileSpec&lt;br /&gt;
End Property&lt;br /&gt;
Public Property Let FileSpec(iSpec As String)&lt;br /&gt;
    strFileSpec = iSpec&lt;br /&gt;
End Property&lt;br /&gt;
Public Sub Load(iForce As Boolean)&lt;br /&gt;
&amp;#039; ACTION: Read settings data from file&lt;br /&gt;
    If iForce Or (Not Me.Loaded) Then&lt;br /&gt;
        Me.GetXMLDoc.Load Me.FileSpec&lt;br /&gt;
&amp;#039;        Set xmlDoc = Nothing    &amp;#039; loading the document clears all nodes&lt;br /&gt;
        isLoaded = True&lt;br /&gt;
    End If&lt;br /&gt;
End Sub&lt;br /&gt;
Public Sub Save()&lt;br /&gt;
&amp;#039;    Dim objNode As clsSettingsNodeXML&lt;br /&gt;
    &lt;br /&gt;
&amp;#039;    Set objNode = Me.Root&lt;br /&gt;
&amp;#039;    objNode.Save&lt;br /&gt;
    Me.GetXMLDoc.Save Me.FileSpec&lt;br /&gt;
    isLoaded = True&lt;br /&gt;
End Sub&lt;br /&gt;
Public Function Loaded() As Boolean&lt;br /&gt;
    Loaded = isLoaded&lt;br /&gt;
End Function&lt;br /&gt;
Friend Function GetXMLDoc() As MSXML2.DOMDocument&lt;br /&gt;
    Dim xmlRoot As MSXML2.IXMLDOMNode&lt;br /&gt;
    &lt;br /&gt;
    &amp;#039; create document if needed&lt;br /&gt;
    If xmlDoc Is Nothing Then&lt;br /&gt;
        Set xmlDoc = New MSXML2.DOMDocument&lt;br /&gt;
    End If&lt;br /&gt;
    &lt;br /&gt;
    &amp;#039; create root node if needed&lt;br /&gt;
    If xmlDoc.childNodes.Length = 0 Then&lt;br /&gt;
        With xmlDoc&lt;br /&gt;
        &amp;#039; create the root node&lt;br /&gt;
            Set xmlRoot = .createNode(NODE_ELEMENT, strSection, &amp;quot;&amp;quot;)&lt;br /&gt;
            .appendChild xmlRoot&lt;br /&gt;
        End With&lt;br /&gt;
    End If&lt;br /&gt;
    Set GetXMLDoc = xmlDoc&lt;br /&gt;
End Function&lt;br /&gt;
Private Sub Class_Initialize()&lt;br /&gt;
    strSection = &amp;quot;settings&amp;quot; &amp;#039; default&lt;br /&gt;
    strAppName = App.EXEName&lt;br /&gt;
End Sub&lt;br /&gt;
Private Sub clsSettingsAPI_Load(iForce As Boolean)&lt;br /&gt;
    Me.Load iForce&lt;br /&gt;
End Sub&lt;br /&gt;
Private Function clsSettingsAPI_Root() As clsSettingsNodeAPI&lt;br /&gt;
    clsSettingsAPI_Root = Me.Root&lt;br /&gt;
End Function&lt;br /&gt;
Private Sub clsSettingsAPI_Save()&lt;br /&gt;
    Me.Save&lt;br /&gt;
End Sub&lt;br /&gt;
===clsSettingsNodeXML===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Option Explicit&lt;br /&gt;
&lt;br /&gt;
Implements clsSettingsNodeAPI&lt;br /&gt;
&lt;br /&gt;
Private strName As String&lt;br /&gt;
Private objMain As clsSettingsXML&lt;br /&gt;
Private objParent As clsSettingsNodeXML&lt;br /&gt;
Public XMLNode As MSXML2.IXMLDOMNode&lt;br /&gt;
Private objItem As clsSettingAPI&lt;br /&gt;
Private lstNodes As Scripting.Dictionary      &amp;#039; list of sub-nodes&lt;br /&gt;
Private lstXMLs As Scripting.Dictionary     &amp;#039; list of XML sub-nodes (refresh before using)&lt;br /&gt;
Friend Sub Init(iItem As clsSettingAPI, iXML As MSXML2.IXMLDOMNode, iParent As clsSettingsNodeAPI)&lt;br /&gt;
    Set objItem = iItem&lt;br /&gt;
    Set objParent = iParent&lt;br /&gt;
    Me.InitRoot iItem.Name, iXML, objParent.Main&lt;br /&gt;
End Sub&lt;br /&gt;
Friend Sub InitRoot(iName As String, iXML As MSXML2.IXMLDOMNode, iMain As clsSettingsXML)&lt;br /&gt;
&amp;#039; USAGES: (1) Internally, and (2) for clsSettingsXML to initialize root node only&lt;br /&gt;
    strName = iName&lt;br /&gt;
    Set XMLNode = iXML&lt;br /&gt;
    Set objMain = iMain&lt;br /&gt;
End Sub&lt;br /&gt;
Friend Sub InitHolder(iName As String, iXML As MSXML2.IXMLDOMNode, iParent As clsSettingsNodeXML)&lt;br /&gt;
&amp;#039; USAGE: For initializing a node when we don&amp;#039;t yet know what Item it will have&lt;br /&gt;
    Me.InitRoot iName, iXML, iParent.Main&lt;br /&gt;
    Set objParent = iParent&lt;br /&gt;
    Set objItem = Nothing   &amp;#039; this will be set later&lt;br /&gt;
End Sub&lt;br /&gt;
Friend Property Set Item(iItem As clsSettingAPI)&lt;br /&gt;
    Set objItem = iItem&lt;br /&gt;
End Property&lt;br /&gt;
Friend Property Get Item() As clsSettingAPI&lt;br /&gt;
    Set Item = objItem&lt;br /&gt;
End Property&lt;br /&gt;
Friend Property Get Main() As clsSettingsXML&lt;br /&gt;
    Set Main = objMain&lt;br /&gt;
End Property&lt;br /&gt;
Friend Property Set Main(iDoc As clsSettingsXML)&lt;br /&gt;
    Set objMain = iDoc&lt;br /&gt;
End Property&lt;br /&gt;
Public Function Node(iName As String, iCreate As Boolean) As clsSettingsNodeXML&lt;br /&gt;
&amp;#039; ACTION: Return the node with the given name&lt;br /&gt;
    Dim objNode As clsSettingsNodeXML&lt;br /&gt;
    &lt;br /&gt;
&amp;#039;    Set objNode = New clsSettingsNodeXML&lt;br /&gt;
&amp;#039; find subnode with name iName; initialize objNode with it (not Nothing)&lt;br /&gt;
    With Me.ListNodes&lt;br /&gt;
        If .Exists(iName) Then&lt;br /&gt;
            Set objNode = .Item(iName)&lt;br /&gt;
        Else&lt;br /&gt;
            If iCreate Then&lt;br /&gt;
                Set objNode = New clsSettingsNodeXML&lt;br /&gt;
                objNode.InitHolder iName, MakeXML(iName), Me&lt;br /&gt;
            Else&lt;br /&gt;
                Set objNode = Nothing&lt;br /&gt;
            End If&lt;br /&gt;
        End If&lt;br /&gt;
    End With&lt;br /&gt;
    Set Node = objNode&lt;br /&gt;
End Function&lt;br /&gt;
Public Property Get Name() As String&lt;br /&gt;
    Name = strName&lt;br /&gt;
End Property&lt;br /&gt;
Public Property Get ValueStored() As String&lt;br /&gt;
&amp;#039; ACTION: Returns the *stored* value (not the active value)&lt;br /&gt;
    If Not (XMLNode Is Nothing) Then&lt;br /&gt;
        ValueStored = XMLNode.Text&lt;br /&gt;
    End If&lt;br /&gt;
End Property&lt;br /&gt;
Public Property Let ValueStored(iValue As String)&lt;br /&gt;
&amp;#039; ACTION: Sets the *stored* value (not the active value)&lt;br /&gt;
    If XMLNode Is Nothing Then&lt;br /&gt;
        Stop    &amp;#039; does this ever happen?&lt;br /&gt;
    End If&lt;br /&gt;
    XMLNode.Text = iValue&lt;br /&gt;
End Property&lt;br /&gt;
Public Property Get ValueActive() As String&lt;br /&gt;
    If Not (objItem Is Nothing) Then&lt;br /&gt;
        ValueActive = objItem.Value&lt;br /&gt;
    End If&lt;br /&gt;
End Property&lt;br /&gt;
Public Property Let ValueActive(iValue As String)&lt;br /&gt;
&amp;#039; ACTION: Sets the *stored* value (not the active value)&lt;br /&gt;
    If Not (objItem Is Nothing) Then&lt;br /&gt;
        objItem.Value = iValue&lt;br /&gt;
    End If&lt;br /&gt;
End Property&lt;br /&gt;
Public Sub Load()&lt;br /&gt;
&amp;#039; ACTION: Read values from the XML DOM tree and stash them in clsSettingAPI objects&lt;br /&gt;
    Dim xmlThis As MSXML2.IXMLDOMNode&lt;br /&gt;
    Dim objSub As clsSettingsNodeXML&lt;br /&gt;
    &lt;br /&gt;
&amp;#039; 1. Look through the document and pull out values into the value list; save pointer to each node found&lt;br /&gt;
    Set xmlThis = XMLNode.firstChild&lt;br /&gt;
    Do While Not (xmlThis Is Nothing)&lt;br /&gt;
        With xmlThis&lt;br /&gt;
            If Not Me.ListNodes.Exists(.nodeName) Then&lt;br /&gt;
&amp;#039;            &amp;#039; this block duplicates code in me.List; should probably put it in a subroutine&lt;br /&gt;
&amp;#039;                Set objSub = New clsSettingsNodeXML&lt;br /&gt;
&amp;#039;                objSub.InitHolder .baseName, xmlThis, Me&lt;br /&gt;
&amp;#039;                lstNodes.Add .baseName, Nothing&lt;br /&gt;
                AddHolder xmlThis&lt;br /&gt;
            End If&lt;br /&gt;
            Set objSub = Me.Node(.nodeName, False)&lt;br /&gt;
            objSub.ValueActive = .Text&lt;br /&gt;
        End With&lt;br /&gt;
        Set xmlThis = xmlThis.nextSibling&lt;br /&gt;
    Loop&lt;br /&gt;
&amp;#039; 2. Go through the list and call Load() recursively&lt;br /&gt;
    LoadSub&lt;br /&gt;
End Sub&lt;br /&gt;
Private Sub AddHolder(iXML As MSXML2.IXMLDOMNode)&lt;br /&gt;
    Dim objSub As clsSettingsNodeXML&lt;br /&gt;
    Dim strName As String&lt;br /&gt;
    &lt;br /&gt;
    strName = iXML.nodeName&lt;br /&gt;
    Set objSub = New clsSettingsNodeXML&lt;br /&gt;
    objSub.InitHolder strName, iXML, Me&lt;br /&gt;
    lstNodes.Add strName, objSub&lt;br /&gt;
End Sub&lt;br /&gt;
Private Sub LoadSub()&lt;br /&gt;
    Dim idxSub As Long&lt;br /&gt;
    Dim objNode As clsSettingsNodeXML&lt;br /&gt;
    &lt;br /&gt;
    For idxSub = 0 To Me.ListNodes.Count - 1&lt;br /&gt;
        Set objNode = Me.ListNodes.Items(idxSub)&lt;br /&gt;
        objNode.Load&lt;br /&gt;
    Next&lt;br /&gt;
End Sub&lt;br /&gt;
Public Sub Save()&lt;br /&gt;
&amp;#039; ACTION:&lt;br /&gt;
    Dim xmlDoc As MSXML2.DOMDocument&lt;br /&gt;
    Dim xmlParent As MSXML2.IXMLDOMNode&lt;br /&gt;
    Dim xmlThis As MSXML2.IXMLDOMNode&lt;br /&gt;
    Dim strName As String&lt;br /&gt;
    &lt;br /&gt;
    Set xmlDoc = objMain.GetXMLDoc&lt;br /&gt;
&amp;#039;    &amp;#039; there doesn&amp;#039;t seem to be any way to find out if a child node already exists,&lt;br /&gt;
&amp;#039;    &amp;#039;   so for now we just kill them all.&lt;br /&gt;
&amp;#039;    Set xmlThis = xmlNode.firstChild&lt;br /&gt;
&amp;#039;    Do While Not (xmlThis Is Nothing)&lt;br /&gt;
&amp;#039;        Set xmlNext = xmlThis.nextSibling&lt;br /&gt;
&amp;#039;        xmlNode.removeChild xmlThis&lt;br /&gt;
&amp;#039;        Set xmlThis = xmlNext&lt;br /&gt;
&amp;#039;    Loop&lt;br /&gt;
&amp;#039;    If xmlSelf.childNodes.Length &amp;lt;&amp;gt; 0 Then Stop&lt;br /&gt;
&lt;br /&gt;
    If Not (objItem Is Nothing) Then&lt;br /&gt;
        objItem.Save Me &amp;#039; tell the object to save itself, in case it has any sub-items&lt;br /&gt;
&amp;#039;        Me.XMLNode.Text = objItem.Value&lt;br /&gt;
    End If&lt;br /&gt;
    &amp;#039; recursively repeat for all sub-nodes:&lt;br /&gt;
    SaveSub&lt;br /&gt;
End Sub&lt;br /&gt;
Private Sub SaveSub()&lt;br /&gt;
    Dim idxSub As Long&lt;br /&gt;
&amp;#039;    Dim objNode As clsSettingAPI&lt;br /&gt;
&amp;#039;    Dim objNode As Object&lt;br /&gt;
    Dim objNode As clsSettingsNodeXML&lt;br /&gt;
    Dim strKey As String&lt;br /&gt;
    Dim xmlThis As MSXML2.IXMLDOMNode&lt;br /&gt;
    &lt;br /&gt;
    Set lstXMLs = ListXMLs&lt;br /&gt;
    With Me.ListNodes&lt;br /&gt;
        For idxSub = 0 To .Count - 1&lt;br /&gt;
            Set objNode = .Items(idxSub)&lt;br /&gt;
            strKey = objNode.Name&lt;br /&gt;
            If Not lstXMLs.Exists(strKey) Then&lt;br /&gt;
            &amp;#039; if an XML node does not already exist, create it and add it to the parent node (i.e. Me)&lt;br /&gt;
                Set xmlThis = objMain.GetXMLDoc.createNode(NODE_ELEMENT, strKey, &amp;quot;&amp;quot;)&lt;br /&gt;
&amp;#039; Don&amp;#039;t save the data here; that&amp;#039;s done in objNode.Save()&lt;br /&gt;
&amp;#039;                xmlThis.Text = objNode.ValueActive&lt;br /&gt;
                Me.XMLNode.appendChild xmlThis&lt;br /&gt;
                Debug.Assert Not (xmlThis.parentNode Is Nothing)&lt;br /&gt;
            End If&lt;br /&gt;
            objNode.Save&lt;br /&gt;
            &lt;br /&gt;
&amp;#039;            Debug.Print &amp;quot;NAME=&amp;quot; &amp;amp; strName&lt;br /&gt;
&amp;#039;            Set xmlText = xmlDoc.createTextNode(.Items(intItem))&lt;br /&gt;
&amp;#039;            xmlThis.appendChild xmlText&lt;br /&gt;
        Next&lt;br /&gt;
    End With&lt;br /&gt;
End Sub&lt;br /&gt;
Friend Property Get ListXMLs() As Scripting.Dictionary&lt;br /&gt;
&amp;#039; ACTION: get a list of XML subnodes&lt;br /&gt;
&amp;#039; maybe this is doing more processing than needed...&lt;br /&gt;
    Dim xmlKid As MSXML2.IXMLDOMNode&lt;br /&gt;
    &lt;br /&gt;
    Set lstXMLs = New Scripting.Dictionary&lt;br /&gt;
    Set xmlKid = Me.XMLNode.firstChild&lt;br /&gt;
    Do Until xmlKid Is Nothing&lt;br /&gt;
        lstXMLs.Add xmlKid.nodeName, xmlKid&lt;br /&gt;
        Set xmlKid = xmlKid.nextSibling&lt;br /&gt;
    Loop&lt;br /&gt;
    Set ListXMLs = lstXMLs&lt;br /&gt;
End Property&lt;br /&gt;
&amp;#039;Friend Function GetXMLNode() As MSXML2.IXMLDOMNode&lt;br /&gt;
&amp;#039;    Dim xmlDoc As MSXML2.DOMDocument&lt;br /&gt;
&amp;#039;    Dim xmlRoot As MSXML2.IXMLDOMNode&lt;br /&gt;
&amp;#039;    Dim xmlNode As MSXML2.IXMLDOMNode&lt;br /&gt;
&amp;#039;&lt;br /&gt;
&amp;#039;    Set xmlDoc = objMain.GetXMLDoc&lt;br /&gt;
&amp;#039;&lt;br /&gt;
&amp;#039;    If objParent Is Nothing Then&lt;br /&gt;
&amp;#039;        &amp;#039; need root node&lt;br /&gt;
&amp;#039;        If xmlDoc.childNodes.Length = 0 Then&lt;br /&gt;
&amp;#039;            &amp;#039; none exists yet; create it:&lt;br /&gt;
&amp;#039;            Set xmlNode = xmlDoc.createNode(NODE_ELEMENT, Me.Name, &amp;quot;&amp;quot;)&lt;br /&gt;
&amp;#039;            xmlDoc.appendChild xmlNode&lt;br /&gt;
&amp;#039;        Else&lt;br /&gt;
&amp;#039;            Set xmlNode = xmlDoc.firstChild&lt;br /&gt;
&amp;#039;        End If&lt;br /&gt;
&amp;#039;    Else&lt;br /&gt;
&amp;#039;        &amp;#039; create non-root node&lt;br /&gt;
&amp;#039;        Set xmlNode = xmlDoc.createNode(NODE_ELEMENT, Me.Name, &amp;quot;&amp;quot;)&lt;br /&gt;
&amp;#039;        Set xmlRoot = objParent.GetXMLNode&lt;br /&gt;
&amp;#039;        xmlRoot.appendChild xmlNode&lt;br /&gt;
&amp;#039;    End If&lt;br /&gt;
&amp;#039;&lt;br /&gt;
&amp;#039;    Set GetXMLNode = xmlNode&lt;br /&gt;
&amp;#039;End Function&lt;br /&gt;
Public Property Get ListNodes() As Scripting.Dictionary&lt;br /&gt;
    Dim xmlDoc As MSXML2.DOMDocument&lt;br /&gt;
    Dim xmlRoot As MSXML2.IXMLDOMElement&lt;br /&gt;
    Dim xmlThis As MSXML2.IXMLDOMNode&lt;br /&gt;
&amp;#039;    Dim objNew As clsSettingsNodeXML&lt;br /&gt;
&lt;br /&gt;
    If lstNodes Is Nothing Then&lt;br /&gt;
&amp;#039; What is often happening at this point is that the XML document has been loaded, but items have not been assigned.&lt;br /&gt;
&amp;#039; So we have to set up item-nodes without knowing what objects to assign to them.&lt;br /&gt;
&lt;br /&gt;
&amp;#039; 2006-02-12 actually, this list should never be rebuilt from the XML tree. For one thing, that tree has stuff we don&amp;#039;t want&lt;br /&gt;
&amp;#039;   to put in the nodes list. For another, this list is maintained explicitly.&lt;br /&gt;
&amp;#039;   Correction: unfortunately, we need to be able to list items not explicitly added, for things like dynamic lists&lt;br /&gt;
        Set lstNodes = New Scripting.Dictionary &amp;#039; create the list object&lt;br /&gt;
        If Not (Me.XMLNode Is Nothing) Then&lt;br /&gt;
            If Me.XMLNode.nodeType &amp;lt;&amp;gt; NODE_TEXT Then&lt;br /&gt;
            &amp;#039; text nodes get saved along with their parent&lt;br /&gt;
                For Each xmlThis In Me.XMLNode.childNodes&lt;br /&gt;
                    With xmlThis&lt;br /&gt;
    &amp;#039;                    Set objNew = New clsSettingsNodeXML&lt;br /&gt;
    &amp;#039;                    objNew.InitHolder .baseName, xmlThis, Me&lt;br /&gt;
    &amp;#039;                    lstNodes.Add .nodeName, .Text&lt;br /&gt;
                        AddHolder xmlThis&lt;br /&gt;
                    End With&lt;br /&gt;
                Next&lt;br /&gt;
            End If&lt;br /&gt;
        End If&lt;br /&gt;
    End If&lt;br /&gt;
    Set ListNodes = lstNodes&lt;br /&gt;
End Property&lt;br /&gt;
&amp;#039;Public Property Get Exists(iName As String)&lt;br /&gt;
&amp;#039;    Exists = Me.ListItems.Exists(iName)&lt;br /&gt;
&amp;#039;End Property&lt;br /&gt;
Public Sub LoadTextBox(iCtrl As TextBox, Optional iName As String = &amp;quot;&amp;quot;)&lt;br /&gt;
    Dim strName As String&lt;br /&gt;
    &lt;br /&gt;
    If iName = &amp;quot;&amp;quot; Then&lt;br /&gt;
        strName = iCtrl.Name&lt;br /&gt;
    Else&lt;br /&gt;
        strName = iName&lt;br /&gt;
    End If&lt;br /&gt;
    If Me.ListNodes.Exists(strName) Then&lt;br /&gt;
        iCtrl.Text = Me.Node(strName, False).ValueStored&lt;br /&gt;
    End If&lt;br /&gt;
End Sub&lt;br /&gt;
Public Sub SaveTextBox(iCtrl As TextBox, Optional iName As String = &amp;quot;&amp;quot;)&lt;br /&gt;
    Dim strName As String&lt;br /&gt;
    Dim strValue As String&lt;br /&gt;
    &lt;br /&gt;
    If iName = &amp;quot;&amp;quot; Then&lt;br /&gt;
        strName = iCtrl.Name&lt;br /&gt;
    Else&lt;br /&gt;
        strName = iName&lt;br /&gt;
    End If&lt;br /&gt;
    strValue = iCtrl.Text&lt;br /&gt;
    Me.Node(strName, True).ValueStored = strValue&lt;br /&gt;
End Sub&lt;br /&gt;
Public Sub LoadChkBox(iCtrl As CheckBox, Optional iName As String = &amp;quot;&amp;quot;)&lt;br /&gt;
    Dim strName As String&lt;br /&gt;
    Dim strValue As String&lt;br /&gt;
    &lt;br /&gt;
    If iName = &amp;quot;&amp;quot; Then&lt;br /&gt;
        strName = iCtrl.Name&lt;br /&gt;
    Else&lt;br /&gt;
        strName = iName&lt;br /&gt;
    End If&lt;br /&gt;
    strValue = Me.Node(strName, False).ValueStored&lt;br /&gt;
    If strValue &amp;lt;&amp;gt; &amp;quot;&amp;quot; Then&lt;br /&gt;
        If strValue = &amp;quot;0&amp;quot; Then&lt;br /&gt;
            iCtrl.Value = vbUnchecked&lt;br /&gt;
        Else&lt;br /&gt;
            iCtrl.Value = vbChecked&lt;br /&gt;
        End If&lt;br /&gt;
    End If&lt;br /&gt;
End Sub&lt;br /&gt;
Public Sub SaveChkBox(iCtrl As CheckBox, Optional iName As String = &amp;quot;&amp;quot;)&lt;br /&gt;
    Dim strName As String&lt;br /&gt;
    Dim strValue As String&lt;br /&gt;
    Dim objNode As clsSettingsNodeAPI&lt;br /&gt;
    &lt;br /&gt;
    If iName = &amp;quot;&amp;quot; Then&lt;br /&gt;
        strName = iCtrl.Name&lt;br /&gt;
    Else&lt;br /&gt;
        strName = iName&lt;br /&gt;
    End If&lt;br /&gt;
    Set objNode = Me.Node(strName, True)&lt;br /&gt;
    If iCtrl.Value Then&lt;br /&gt;
        strValue = &amp;quot;1&amp;quot;&lt;br /&gt;
    Else&lt;br /&gt;
        strValue = &amp;quot;0&amp;quot;&lt;br /&gt;
    End If&lt;br /&gt;
    objNode.ValueStored = strValue&lt;br /&gt;
End Sub&lt;br /&gt;
Public Sub LoadCombo(iCombo As ComboBox, Optional iName As String = &amp;quot;&amp;quot;)&lt;br /&gt;
    Dim strName As String&lt;br /&gt;
    Dim strValue As String&lt;br /&gt;
    Dim idxValue As Long&lt;br /&gt;
    &lt;br /&gt;
    If iName = &amp;quot;&amp;quot; Then&lt;br /&gt;
        strName = iCombo.Name&lt;br /&gt;
    Else&lt;br /&gt;
        strName = iName&lt;br /&gt;
    End If&lt;br /&gt;
    &lt;br /&gt;
    strValue = Me.Node(strName, False).ValueStored&lt;br /&gt;
    If IsNumeric(strValue) Then&lt;br /&gt;
        idxValue = CLng(strValue)&lt;br /&gt;
        If idxValue &amp;lt; iCombo.ListCount Then&lt;br /&gt;
           iCombo.ListIndex = CLng(strValue)&lt;br /&gt;
        End If&lt;br /&gt;
    End If&lt;br /&gt;
End Sub&lt;br /&gt;
Public Sub SaveCombo(iCombo As ComboBox, Optional iName As String = &amp;quot;&amp;quot;)&lt;br /&gt;
    Dim strName As String&lt;br /&gt;
    Dim strValue As String&lt;br /&gt;
    &lt;br /&gt;
    If iName = &amp;quot;&amp;quot; Then&lt;br /&gt;
        strName = iCombo.Name&lt;br /&gt;
    Else&lt;br /&gt;
        strName = iName&lt;br /&gt;
    End If&lt;br /&gt;
    &lt;br /&gt;
    strValue = CStr(iCombo.ListIndex)&lt;br /&gt;
    Me.Node(strName, True).ValueStored = strValue&lt;br /&gt;
End Sub&lt;br /&gt;
Private Function MakeXML(iName As String) As MSXML2.IXMLDOMNode&lt;br /&gt;
    Dim objXML As MSXML2.IXMLDOMNode&lt;br /&gt;
        &lt;br /&gt;
    If Me.ListXMLs.Exists(iName) Then&lt;br /&gt;
        Set objXML = lstXMLs.Item(iName)&lt;br /&gt;
    Else&lt;br /&gt;
        Set objXML = objMain.GetXMLDoc.createNode(NODE_ELEMENT, iName, &amp;quot;&amp;quot;)&lt;br /&gt;
        Me.XMLNode.appendChild objXML&lt;br /&gt;
    End If&lt;br /&gt;
    Set MakeXML = objXML&lt;br /&gt;
End Function&lt;br /&gt;
Private Function clsSettingsNodeAPI_AddItem(iItem As clsSettingAPI) As clsSettingsNodeAPI&lt;br /&gt;
    Dim objNode As clsSettingsNodeXML&lt;br /&gt;
    Dim objXML As MSXML2.IXMLDOMNode&lt;br /&gt;
&lt;br /&gt;
    If Me.XMLNode Is Nothing Then Stop&lt;br /&gt;
&lt;br /&gt;
    If Me.ListNodes.Exists(iItem.Name) Then&lt;br /&gt;
        Set objNode = lstNodes.Item(iItem.Name)&lt;br /&gt;
        Set objNode.Item = iItem&lt;br /&gt;
    Else&lt;br /&gt;
        Set objNode = New clsSettingsNodeXML&lt;br /&gt;
        Set objXML = MakeXML(iItem.Name)&lt;br /&gt;
        objNode.Init iItem, objXML, Me&lt;br /&gt;
        lstNodes.Add iItem.Name, objNode&lt;br /&gt;
    End If&lt;br /&gt;
End Function&lt;br /&gt;
Private Property Get clsSettingsNodeAPI_ListNodes() As Scripting.IDictionary&lt;br /&gt;
    Set clsSettingsNodeAPI_ListNodes = Me.ListNodes&lt;br /&gt;
End Property&lt;br /&gt;
Private Sub clsSettingsNodeAPI_Load()&lt;br /&gt;
&amp;#039; ACTION:&lt;br /&gt;
&amp;#039;   - Load the current node&amp;#039;s value&lt;br /&gt;
&amp;#039;   - Iterate through children and call Load() for each&lt;br /&gt;
    Dim objNode As clsSettingsNodeXML&lt;br /&gt;
    Dim objKid As clsSettingAPI&lt;br /&gt;
    Dim idxKid As Long&lt;br /&gt;
&lt;br /&gt;
    If Not (objItem Is Nothing) Then&lt;br /&gt;
        objItem.Load Me&lt;br /&gt;
    End If&lt;br /&gt;
    For idxKid = 0 To Me.ListNodes.Count - 1&lt;br /&gt;
        Set objNode = lstNodes.Items(idxKid)&lt;br /&gt;
        Set objKid = objNode.Item&lt;br /&gt;
        objKid.Load objNode&lt;br /&gt;
    Next&lt;br /&gt;
End Sub&lt;br /&gt;
Private Property Get clsSettingsNodeAPI_Name() As String&lt;br /&gt;
    clsSettingsNodeAPI_Name = Me.Name&lt;br /&gt;
End Property&lt;br /&gt;
Private Function clsSettingsNodeAPI_Node(iName As String, iCreate As Boolean) As clsSettingsNodeAPI&lt;br /&gt;
    Set clsSettingsNodeAPI_Node = Me.Node(iName, iCreate)&lt;br /&gt;
End Function&lt;br /&gt;
Private Sub clsSettingsNodeAPI_Save()&lt;br /&gt;
    Me.Save&lt;br /&gt;
End Sub&lt;br /&gt;
Private Property Let clsSettingsNodeAPI_ValueStored(RHS As String)&lt;br /&gt;
    Me.ValueStored = RHS&lt;br /&gt;
End Property&lt;br /&gt;
Private Property Get clsSettingsNodeAPI_ValueStored() As String&lt;br /&gt;
    clsSettingsNodeAPI_ValueStored = Me.ValueStored&lt;br /&gt;
End Property&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
===clsSettingText===&lt;br /&gt;
An implementation of [[#clsSettingAPI]]&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Option Explicit&lt;br /&gt;
&lt;br /&gt;
&amp;#039; CLASS: clsSettingText&lt;br /&gt;
&amp;#039; PURPOSE: generic clsSettingAPI class for storing a text value&lt;br /&gt;
&amp;#039;   without needing an associated control&lt;br /&gt;
&lt;br /&gt;
Implements clsSettingAPI&lt;br /&gt;
&lt;br /&gt;
Private strName As String&lt;br /&gt;
Private strVal As String&lt;br /&gt;
Public Sub Init(iName As String, iVal As String)&lt;br /&gt;
    strName = iName&lt;br /&gt;
    strVal = iVal&lt;br /&gt;
End Sub&lt;br /&gt;
Private Sub clsSettingAPI_Load(iNode As clsSettingsNodeAPI)&lt;br /&gt;
    strVal = iNode.ValueStored&lt;br /&gt;
End Sub&lt;br /&gt;
Private Property Let clsSettingAPI_Name(ByVal RHS As String)&lt;br /&gt;
    strName = RHS&lt;br /&gt;
End Property&lt;br /&gt;
Private Property Get clsSettingAPI_Name() As String&lt;br /&gt;
    clsSettingAPI_Name = strName&lt;br /&gt;
End Property&lt;br /&gt;
Private Sub clsSettingAPI_Save(iNode As clsSettingsNodeAPI)&lt;br /&gt;
    iNode.ValueStored = strVal&lt;br /&gt;
End Sub&lt;br /&gt;
Private Property Let clsSettingAPI_Value(ByVal RHS As String)&lt;br /&gt;
    strVal = RHS&lt;br /&gt;
End Property&lt;br /&gt;
Private Property Get clsSettingAPI_Value() As String&lt;br /&gt;
    clsSettingAPI_Value = strVal&lt;br /&gt;
End Property&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
===xtForm===&lt;br /&gt;
Implementation of [[#clsSettingAPI]]&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;#039; CLASS: xtForm&lt;br /&gt;
&amp;#039; PURPOSE: extended form functionality&lt;br /&gt;
&amp;#039; HISTORY:&lt;br /&gt;
&amp;#039;   1999.12.06 - NJS - adapted from Forms.bas&lt;br /&gt;
&amp;#039;   2001.01.03 - NJS - modified to use clsConfigReg for storing position&lt;br /&gt;
&amp;#039;   2006-01-22 - Wzl - modified to use clsSettingsAPI for storing position&lt;br /&gt;
&lt;br /&gt;
Implements clsSettingAPI&lt;br /&gt;
&lt;br /&gt;
Public WithEvents Form As Form&lt;br /&gt;
Public doSaveSize As Boolean&lt;br /&gt;
Public doAutoSave As Boolean&lt;br /&gt;
&lt;br /&gt;
Private strPos As String&lt;br /&gt;
&amp;#039;Private objSet As clsSettingsNodeAPI&lt;br /&gt;
Private strName As String&lt;br /&gt;
&lt;br /&gt;
Option Explicit&lt;br /&gt;
Public Sub Init(iForm As Form)&lt;br /&gt;
    Set Form = iForm&lt;br /&gt;
    doSaveSize = (iForm.BorderStyle = vbSizable) Or (iForm.BorderStyle = vbSizableToolWindow)&lt;br /&gt;
&amp;#039;    Set objSet = iSettings&lt;br /&gt;
&amp;#039;    Me.LoadPos&lt;br /&gt;
    strName = iForm.Name&lt;br /&gt;
End Sub&lt;br /&gt;
Public Property Let Pos(istr As String)&lt;br /&gt;
    strPos = istr&lt;br /&gt;
    If Me.Form.Visible Then Me.PlaceForm&lt;br /&gt;
End Property&lt;br /&gt;
Public Property Get Pos() As String&lt;br /&gt;
&amp;#039; ACTION: return a string specifying the given form&amp;#039;s size and position&lt;br /&gt;
    Dim ostr As String&lt;br /&gt;
    Dim can_size As Boolean&lt;br /&gt;
    &lt;br /&gt;
    With Me.Form&lt;br /&gt;
        If .WindowState &amp;lt;&amp;gt; vbNormal Then&lt;br /&gt;
            .WindowState = vbNormal &amp;#039; so dimensions are meaningful when we read them&lt;br /&gt;
        End If&lt;br /&gt;
        ostr = .Left &amp;amp; &amp;quot; &amp;quot; &amp;amp; .Top&lt;br /&gt;
        If doSaveSize Then&lt;br /&gt;
            ostr = ostr &amp;amp; &amp;quot; &amp;quot; &amp;amp; .Width &amp;amp; &amp;quot; &amp;quot; &amp;amp; .Height&lt;br /&gt;
        End If&lt;br /&gt;
    End With&lt;br /&gt;
    Pos = ostr&lt;br /&gt;
End Property&lt;br /&gt;
&amp;#039;Public Sub Reveal()&lt;br /&gt;
&amp;#039;&amp;#039; ACTION: show the given form, and make sure it&amp;#039;s not minimized.&lt;br /&gt;
&amp;#039;    With Me.Form&lt;br /&gt;
&amp;#039;        .Show&lt;br /&gt;
&amp;#039;        If .WindowState = vbMinimized Then&lt;br /&gt;
&amp;#039;            .WindowState = vbNormal&lt;br /&gt;
&amp;#039;        End If&lt;br /&gt;
&amp;#039;        LoadPos &amp;#039; restore saved position&lt;br /&gt;
&amp;#039;    End With&lt;br /&gt;
&amp;#039;End Sub&lt;br /&gt;
&amp;#039;Public Sub LoadPos(Optional iKey As String)&lt;br /&gt;
&amp;#039;    If iKey = &amp;quot;&amp;quot; Then&lt;br /&gt;
&amp;#039;        iKey = Form.Name&lt;br /&gt;
&amp;#039;    End If&lt;br /&gt;
&amp;#039;    Me.Pos = objSet.Value(iKey)&lt;br /&gt;
&amp;#039;    PlaceForm&lt;br /&gt;
&amp;#039;End Sub&lt;br /&gt;
&amp;#039;Public Sub SavePos(Optional iKey As String)&lt;br /&gt;
&amp;#039;&amp;#039; PURPOSE: saves the given form&amp;#039;s position to the registry&lt;br /&gt;
&amp;#039;    With Me.Form&lt;br /&gt;
&amp;#039;        If iKey = &amp;quot;&amp;quot; Then&lt;br /&gt;
&amp;#039;            iKey = .Name&lt;br /&gt;
&amp;#039;        End If&lt;br /&gt;
&amp;#039;        If .Visible And (.WindowState &amp;lt;&amp;gt; vbMinimized) Then&lt;br /&gt;
&amp;#039;            objSet.Value(iKey) = Me.Pos&lt;br /&gt;
&amp;#039;        End If&lt;br /&gt;
&amp;#039;    End With&lt;br /&gt;
&amp;#039;End Sub&lt;br /&gt;
Public Sub PlaceForm()&lt;br /&gt;
&amp;#039; ACTION: set the given form&amp;#039;s size and position from the stored string&lt;br /&gt;
    Dim oarr As Variant&lt;br /&gt;
    Dim can_size As Boolean&lt;br /&gt;
    &lt;br /&gt;
    If strPos = &amp;quot;&amp;quot; Then&lt;br /&gt;
    &amp;#039; use default position: center in screen&lt;br /&gt;
        With Me.Form&lt;br /&gt;
            .Left = (Screen.Width - .Width) / 2&lt;br /&gt;
            .Top = (Screen.Height - .Height) / 2&lt;br /&gt;
        End With&lt;br /&gt;
    Else&lt;br /&gt;
    &amp;#039; use stored position (and size if applicable)&lt;br /&gt;
        oarr = Split(strPos, &amp;quot; &amp;quot;)&lt;br /&gt;
        With Form&lt;br /&gt;
            .Left = oarr(0)&lt;br /&gt;
            .Top = oarr(1)&lt;br /&gt;
            If .Left &amp;gt; Screen.Width Then&lt;br /&gt;
                .Left = Screen.Width - .Width&lt;br /&gt;
            End If&lt;br /&gt;
            If .Top &amp;gt; Screen.Height Then&lt;br /&gt;
                .Top = Screen.Height - .Height&lt;br /&gt;
            End If&lt;br /&gt;
            If doSaveSize And (UBound(oarr) &amp;gt; 1) Then&lt;br /&gt;
                .Width = oarr(2)&lt;br /&gt;
                .Height = oarr(3)&lt;br /&gt;
            End If&lt;br /&gt;
        End With&lt;br /&gt;
    End If&lt;br /&gt;
End Sub&lt;br /&gt;
Private Sub clsSettingAPI_Load(iNode As clsSettingsNodeAPI)&lt;br /&gt;
    strPos = iNode.ValueStored&lt;br /&gt;
    PlaceForm&lt;br /&gt;
End Sub&lt;br /&gt;
Private Property Let clsSettingAPI_Name(ByVal RHS As String)&lt;br /&gt;
    strName = RHS&lt;br /&gt;
End Property&lt;br /&gt;
Private Property Get clsSettingAPI_Name() As String&lt;br /&gt;
    clsSettingAPI_Name = strName&lt;br /&gt;
End Property&lt;br /&gt;
Private Sub clsSettingAPI_Save(iNode As clsSettingsNodeAPI)&lt;br /&gt;
    iNode.ValueStored = Me.Pos&lt;br /&gt;
End Sub&lt;br /&gt;
Private Property Let clsSettingAPI_Value(ByVal RHS As String)&lt;br /&gt;
    strPos = RHS&lt;br /&gt;
    PlaceForm&lt;br /&gt;
End Property&lt;br /&gt;
Private Property Get clsSettingAPI_Value() As String&lt;br /&gt;
    clsSettingAPI_Value = Me.Pos&lt;br /&gt;
End Property&lt;br /&gt;
&amp;#039;Private Sub Form_Activate()&lt;br /&gt;
&amp;#039; EVENT: runs the first time the form is shown&lt;br /&gt;
&amp;#039;    Me.PlaceForm&lt;br /&gt;
&amp;#039;End Sub&lt;br /&gt;
Private Sub Form_Deactivate()&lt;br /&gt;
    strPos = Me.Pos &amp;#039; get new position&lt;br /&gt;
End Sub&lt;br /&gt;
Private Sub Form_QueryUnload(Cancel As Integer, UnloadMode As Integer)&lt;br /&gt;
&amp;#039; This is redundant; xtForm also handles this&lt;br /&gt;
&amp;#039;    If doAutoSave Then&lt;br /&gt;
&amp;#039;        Me.SavePos&lt;br /&gt;
&amp;#039;    End If&lt;br /&gt;
End Sub&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
===xtListBox===&lt;br /&gt;
Implementation of [[#clsSettingAPI]]&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;#039; CLASS: xtListBox&lt;br /&gt;
&amp;#039; PURPOSE: extended functionality for ListBox control&lt;br /&gt;
&amp;#039; REQUIRES: xtListItems.cls, xtListItem.cls, property let/get AppSetting(Name)&lt;br /&gt;
Option Explicit&lt;br /&gt;
Implements clsSettingAPI&lt;br /&gt;
&lt;br /&gt;
Public Event ItemChosen(oKey As Long)&lt;br /&gt;
Public Event ItemChecked(oKey As Long)&lt;br /&gt;
&lt;br /&gt;
&amp;#039;Public Config As clsSettingsNodeAPI&lt;br /&gt;
&lt;br /&gt;
&amp;#039;local variable(s) to hold property value(s)&lt;br /&gt;
Private strName As String&lt;br /&gt;
Private WithEvents ctrlList As ListBox &amp;#039;local copy&lt;br /&gt;
Private WithEvents ctrlForm As Form&lt;br /&gt;
Private lstItems As Scripting.Dictionary&lt;br /&gt;
Private doDataSave As Boolean&lt;br /&gt;
Private intNewItem As Long&lt;br /&gt;
Public Sub Init(iList As ListBox, Optional iDataSave As Boolean = True)&lt;br /&gt;
    Set ctrlList = iList&lt;br /&gt;
    Set ctrlForm = iList.Parent&lt;br /&gt;
&amp;#039;    Set Config = iConfig&lt;br /&gt;
    Set lstItems = New Scripting.Dictionary&lt;br /&gt;
    doDataSave = iDataSave&lt;br /&gt;
    With ctrlList&lt;br /&gt;
        strName = .Parent.Name &amp;amp; &amp;quot;.&amp;quot; &amp;amp; .Name&lt;br /&gt;
    End With&lt;br /&gt;
End Sub&lt;br /&gt;
Public Property Get List() As Scripting.Dictionary&lt;br /&gt;
    Set List = lstItems&lt;br /&gt;
End Property&lt;br /&gt;
Public Sub Add(iText As String, Optional iObj As Object)&lt;br /&gt;
&amp;#039; NOTES:&lt;br /&gt;
&amp;#039;   1. Add object to list&lt;br /&gt;
&amp;#039;   2. Add text to listbox, with ItemData pointer to list&lt;br /&gt;
    With ctrlList&lt;br /&gt;
        intNewItem = intNewItem + 1&lt;br /&gt;
        .AddItem iText&lt;br /&gt;
        .ItemData(.NewIndex) = intNewItem&lt;br /&gt;
        lstItems.Add intNewItem, iObj&lt;br /&gt;
    End With&lt;br /&gt;
End Sub&lt;br /&gt;
Public Sub Clear()&lt;br /&gt;
    ctrlList.Clear&lt;br /&gt;
    lstItems.RemoveAll&lt;br /&gt;
End Sub&lt;br /&gt;
Public Property Get SelectedItem() As Object&lt;br /&gt;
&amp;#039; to be written&lt;br /&gt;
End Property&lt;br /&gt;
Public Function SelectCount() As Integer&lt;br /&gt;
    SelectCount = ctrlList.SelCount&lt;br /&gt;
End Function&lt;br /&gt;
Public Sub ClearSelection()&lt;br /&gt;
&amp;#039; PURPOSE: removes any selections from the control&lt;br /&gt;
    Dim idxList As Long, qtyList As Long&lt;br /&gt;
    &lt;br /&gt;
    qtyList = ctrlList.ListCount&lt;br /&gt;
    For idxList = 1 To qtyList&lt;br /&gt;
        ctrlList.Selected(idxList) = False&lt;br /&gt;
    Next&lt;br /&gt;
End Sub&lt;br /&gt;
Public Sub DelSelected()&lt;br /&gt;
&amp;#039; ACTION: Delete selected items from the list&lt;br /&gt;
    Dim idxList As Long, qtyList As Long&lt;br /&gt;
    Dim idxDel As Long&lt;br /&gt;
    &lt;br /&gt;
    qtyList = Me.List.Count&lt;br /&gt;
    For idxList = qtyList - 1 To 0 Step -1&lt;br /&gt;
        &amp;#039; find the item&amp;#039;s key in the stored list&lt;br /&gt;
        idxDel = lstItems.Keys(idxList)&lt;br /&gt;
        If ctrlList.Selected(idxList) Then&lt;br /&gt;
            &amp;#039; delete item from the stored list&lt;br /&gt;
            lstItems.Remove idxDel&lt;br /&gt;
            &amp;#039; delete item from the control&lt;br /&gt;
            ctrlList.RemoveItem idxList&lt;br /&gt;
        End If&lt;br /&gt;
    Next&lt;br /&gt;
End Sub&lt;br /&gt;
Public Sub KeyDown(KeyCode As Integer, Shift As Integer)&lt;br /&gt;
&amp;#039;&amp;#039; PURPOSE: define additional standard behavior for non-ASCII key presses&lt;br /&gt;
&amp;#039;&amp;#039; ACTION: Shift-Insert copies list contents to clipboard&lt;br /&gt;
&amp;#039;    If ((KeyCode = vbKeyInsert) And (Shift &amp;amp; &amp;amp;H1)) Then&lt;br /&gt;
&amp;#039;        ClipCopy&lt;br /&gt;
&amp;#039;    End If&lt;br /&gt;
End Sub&lt;br /&gt;
Private Sub clsSettingAPI_Load(iNode As clsSettingsNodeAPI)&lt;br /&gt;
&amp;#039; ACTION: Load current selection and, if applicable, list data&lt;br /&gt;
    Dim qtyItem As Long&lt;br /&gt;
    Dim idxItem As Long&lt;br /&gt;
    Dim objNode As clsSettingsNodeAPI&lt;br /&gt;
    Dim strVal As String&lt;br /&gt;
    &lt;br /&gt;
&amp;#039;    Me.Value = iNode.ValueStored&lt;br /&gt;
    &amp;#039; check for saved data list&lt;br /&gt;
    qtyItem = iNode.ListNodes.Count&lt;br /&gt;
    &amp;#039; load data, if there is any&lt;br /&gt;
    For idxItem = 0 To qtyItem - 1&lt;br /&gt;
        Set objNode = iNode.ListNodes.Items(idxItem)&lt;br /&gt;
        strVal = objNode.ValueStored&lt;br /&gt;
        If objNode.Name = &amp;quot;selected&amp;quot; Then&lt;br /&gt;
            Me.Value = objNode.ValueStored&lt;br /&gt;
        Else&lt;br /&gt;
            If strVal &amp;lt;&amp;gt; &amp;quot;&amp;quot; Then&lt;br /&gt;
            &amp;#039; klugefix&lt;br /&gt;
                If Not Me.List.Exists(strVal) Then&lt;br /&gt;
                    Me.Add strVal&lt;br /&gt;
                End If&lt;br /&gt;
            End If&lt;br /&gt;
        End If&lt;br /&gt;
    Next&lt;br /&gt;
End Sub&lt;br /&gt;
Private Property Let clsSettingAPI_Name(ByVal RHS As String)&lt;br /&gt;
    strName = RHS&lt;br /&gt;
End Property&lt;br /&gt;
Private Property Get clsSettingAPI_Name() As String&lt;br /&gt;
    clsSettingAPI_Name = strName&lt;br /&gt;
End Property&lt;br /&gt;
Private Sub clsSettingAPI_Save(iNode As clsSettingsNodeAPI)&lt;br /&gt;
    Dim idxItem As Long&lt;br /&gt;
    Dim objNode As clsSettingsNodeAPI&lt;br /&gt;
            &lt;br /&gt;
    Set objNode = iNode.Node(&amp;quot;selected&amp;quot;, True)&lt;br /&gt;
    objNode.ValueStored = Me.Value&lt;br /&gt;
    If doDataSave Then&lt;br /&gt;
        For idxItem = 0 To Me.List.Count - 1&lt;br /&gt;
            Set objNode = iNode.Node(&amp;quot;line-&amp;quot; &amp;amp; CStr(idxItem), True)&lt;br /&gt;
            objNode.ValueStored = ctrlList.List(idxItem)&lt;br /&gt;
        Next&lt;br /&gt;
    End If&lt;br /&gt;
End Sub&lt;br /&gt;
Public Property Let Value(iValue As String)&lt;br /&gt;
    Dim xtsVal As xtString&lt;br /&gt;
    Dim idxSel As Long&lt;br /&gt;
    Dim strSel As String&lt;br /&gt;
    &lt;br /&gt;
    Set xtsVal = New xtString&lt;br /&gt;
    &lt;br /&gt;
    xtsVal.Value = iValue   &amp;#039; data is list of selected items, by index&lt;br /&gt;
    &amp;#039; parse data&lt;br /&gt;
    strSel = xtsVal.FindFirst&lt;br /&gt;
    Do While xtsVal.IsFound&lt;br /&gt;
        If IsNumeric(strSel) Then&lt;br /&gt;
            idxSel = CLng(strSel)&lt;br /&gt;
            ctrlList.Selected(idxSel) = True&lt;br /&gt;
        End If&lt;br /&gt;
        strSel = xtsVal.FindNext&lt;br /&gt;
    Loop&lt;br /&gt;
End Property&lt;br /&gt;
Public Property Get Value() As String&lt;br /&gt;
    Dim strSel As String&lt;br /&gt;
    Dim idxItem As Long&lt;br /&gt;
    &lt;br /&gt;
&amp;#039; debugging:&lt;br /&gt;
&amp;#039;    If Me.List.Count &amp;lt;&amp;gt; ctrlList.ListCount Then Stop&lt;br /&gt;
&lt;br /&gt;
    For idxItem = 0 To ctrlList.ListCount - 1&lt;br /&gt;
        If ctrlList.Selected(idxItem) Then&lt;br /&gt;
            strSel = strSel &amp;amp; &amp;quot; &amp;quot; &amp;amp; idxItem&lt;br /&gt;
        End If&lt;br /&gt;
    Next&lt;br /&gt;
    Value = strSel&lt;br /&gt;
End Property&lt;br /&gt;
Private Property Let clsSettingAPI_Value(ByVal RHS As String)&lt;br /&gt;
    Me.Value = RHS&lt;br /&gt;
End Property&lt;br /&gt;
Private Property Get clsSettingAPI_Value() As String&lt;br /&gt;
    clsSettingAPI_Value = Me.Value&lt;br /&gt;
End Property&lt;br /&gt;
Private Sub ctrlList_Click()&lt;br /&gt;
    Dim intLine As Integer&lt;br /&gt;
    Dim intKey As Long&lt;br /&gt;
&lt;br /&gt;
    intLine = ctrlList.ListIndex&lt;br /&gt;
    intKey = ctrlList.ItemData(intLine)&lt;br /&gt;
    If intKey Then&lt;br /&gt;
        RaiseEvent ItemChosen(intKey)&lt;br /&gt;
    End If&lt;br /&gt;
End Sub&lt;br /&gt;
Private Sub ctrlList_ItemCheck(Item As Integer)&lt;br /&gt;
    Dim intKey As Long&lt;br /&gt;
&lt;br /&gt;
    If Me.List.Exists(Item) Then&lt;br /&gt;
        intKey = ctrlList.ItemData(Item)&lt;br /&gt;
        RaiseEvent ItemChecked(intKey)&lt;br /&gt;
    End If&lt;br /&gt;
End Sub&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Woozle</name></author>
	</entry>
</feed>