Home All Groups Group Topic Archive Search About

PropertyBag and settings

Author
21 Feb 2009 4:57 PM
mayayana
I've just been looking into an idea for a
convenient way to save program settings.
I'm wondering if anyone has done this and
might have comments or thoughts about it:

Write a DLL with a window for changing settings.
The main program would call a function in the DLL
public class to show the settings window.

Include a PublicNotCreatable class ("CSets") that
stores those settings.

  The CSets state gets retrieved as a byte array,
which is saved to disk, when the DLL unloads.
Likewise, the persisted CSets class gets created
with that byte array at load.
  The gist of that is that a PropertyBag is created
with a single property, the value of which is the
CSets class itself. The persisted class is then restored
by reading back the byte array from disk, assigning that
byte array as the Contents of a PropertyBag, then
setting a new instance of CSets as PropetyBag.Contents.

  The main program creates the DLL public class
when it loads and asks for an instance of CSets,
gettings all of the saved program settings in one
call without needing to parse XML, INI, or read
the Registry.

  The public class has an event Changed that fires
whenever settings are changed, at which point the
main program sets its CSets instance to Nothing
and gets a new copy.

  On the downside, the class CSets will have to be fairly
verbose. All of the persisted values have to be maintained
with wordy calls to ReadProperty, WriteProperty, and
PropertyChanged. Another disadvantage is that it adds
a DLL that must be registered during install. But from inside
the main program there's very little to do -- just load the
DLL at launch and store an up-to-date copy of CSets in
order to apply program settings while running.

Make sense?

Author
21 Feb 2009 6:00 PM
Claus Centrino
Don't know why you make it so complicated, at least
concerning window settings. To save and reload window
settings I simply use a little bit of code in the form_load
and unload event, precisely a simple call to a public save
and to a restore sub., like "SaveSettings Me" and
"LoadSettings Me". To save additional form specific data you
could pack them into a string, something like
"Par1=xxx;Par2=xxx;Par3=xxx" and pass this string as second
parameter. That's quite fast enough and bullet proof, and
each other code which needs it can it read out, edit, and
store in the same way.
Author
21 Feb 2009 6:50 PM
Ivar
Not sure I totally understand what you are asking but!
The PropertyBag is only available to write to within the IDE, not to the
compiled exe, it dosn't exist in it, or anywhere really. It's a UserControl
Method for storing settings and info at exe design time
The bag does one of two things with the data it wants to save, it will
either store short strings in the frm file, or any other info it stores in a
frx file.
When you say program, do you mean IDE or EXE?

Ivar
Author
21 Feb 2009 8:32 PM
DanS
"Ivar" <Ivar.ekstromer***@ntlworld.com> wrote in
news:22Ynl.20347$Dz4.14442@newsfe20.ams2:

> Not sure I totally understand what you are asking but!
> The PropertyBag is only available to write to within the IDE, not to
> the compiled exe, it dosn't exist in it, or anywhere really.

Actually, that is incorrect. The property bag *is* available at runtime.
I use it to store icons, and you can add and remove stored 'properties'
at will.

It's could be a bit of a PITA depending on wwhat you want to store, but
it works as advertised.

For x = 1 To ilMenu.ListImages.Count
        picHidden.Picture = ilMenu.ListImages(x).Picture
     picHidden.Picture = picHidden.Image
     pb.WriteProperty "" & iCount & "KEY", ilMenu.ListImages(x).key
     pb.WriteProperty "" & iCount & "ICON", picHidden.Image
     iCount = iCount + 1
Next x
pb.WriteProperty "ICOUNT", iCount - 1


I then have a couple of more groups of things stored as text.

I then save the PropBag to disk.......

'finally, write the contents of the PB to a file.
pbC = pb.Contents
Open appPath & "menus\" & mName & ".DDTmenu" For Binary As #1
Put #1, , pbC
Close #1
Set pb = Nothing

And then to restore, the process is done in reverse.....

'// Set the file handle
fFile = FreeFile
Open menuPath For Binary As #fFile
Get #fFile, , pbC
pb.Contents = pbC
Close #fFile

Now the PB holds evrthing it did before it was saved to the HD.


Regards,

DanS






Show quoteHide quote
> It's a
> UserControl Method for storing settings and info at exe design time
> The bag does one of two things with the data it wants to save, it will
> either store short strings in the frm file, or any other info it
> stores in a frx file.
> When you say program, do you mean IDE or EXE?
>
Author
21 Feb 2009 8:34 PM
DanS
"mayayana" <mayayaX***@rcXXn.com> wrote in news:#I6bDXElJHA.6124
@TK2MSFTNGP02.phx.gbl:

>    I've just been looking into an idea for a
> convenient way to save program settings.
> I'm wondering if anyone has done this and
> might have comments or thoughts about it:

(Near-top posted for brevity...)

Comments....why so involved ? Why not just save/restore setting's in your
main program, why in a DLL ?

But otherwise, it will work.

See my post to Ivar for some more details, but it seems like you've got
them down....save the contents (binary) to a file to save..read the file
in one binary chunk and set the PB contents to it.



Regards,

DanS









Show quoteHide quote
>
> Write a DLL with a window for changing settings.
> The main program would call a function in the DLL
> public class to show the settings window.
>
> Include a PublicNotCreatable class ("CSets") that
> stores those settings.
>
>   The CSets state gets retrieved as a byte array,
> which is saved to disk, when the DLL unloads.
> Likewise, the persisted CSets class gets created
> with that byte array at load.
>   The gist of that is that a PropertyBag is created
> with a single property, the value of which is the
> CSets class itself. The persisted class is then restored
> by reading back the byte array from disk, assigning that
> byte array as the Contents of a PropertyBag, then
> setting a new instance of CSets as PropetyBag.Contents.
>
>   The main program creates the DLL public class
> when it loads and asks for an instance of CSets,
> gettings all of the saved program settings in one
> call without needing to parse XML, INI, or read
> the Registry.
>
>   The public class has an event Changed that fires
> whenever settings are changed, at which point the
> main program sets its CSets instance to Nothing
> and gets a new copy.
>
>   On the downside, the class CSets will have to be fairly
> verbose. All of the persisted values have to be maintained
> with wordy calls to ReadProperty, WriteProperty, and
> PropertyChanged. Another disadvantage is that it adds
> a DLL that must be registered during install. But from inside
> the main program there's very little to do -- just load the
> DLL at launch and store an up-to-date copy of CSets in
> order to apply program settings while running.
>
>  Make sense?
>
>
>
>
Author
21 Feb 2009 11:12 PM
mayayana
>
> Comments....why so involved ? Why not just save/restore setting's in your
> main program, why in a DLL ?
>
> But otherwise, it will work.
>
> See my post to Ivar for some more details, but it seems like you've got
> them down....save the contents (binary) to a file to save..read the file
> in one binary chunk and set the PB contents to it.
>

  Thanks. I was thinking of using it in the way
you described. I don't particularly need a DLL.
I was just dealing with a sprawling program and
the settings window alone is fairly involved. So
I'm thinking about splitting things up. The Settings
menu would create an instance of the DLL, which
would then load the last class state, configure the
settings window accordingly, and show the settings
window. Then if there have been changes when the
window closes, the main EXE retrieves a new copy
of the settings class, the DLL saves the class state,
and the DLL is unloaded.

  It's a bit confusing. Somehow it doesn't seem quite
right that I can hold onto a settings class after the
DLL is unloaded, but it seems to work OK. There's a reference
set to the DLL, so the main EXE knows what a "CSets"
class is. (I'm creating the DLL instance via a main class,
which then passes me a CSets class and sets its own
CSets instance to Nothing. I then set the main DLL instance
class to nothing and am left with just a lightweight class
holding all of the latest settings.)
Author
21 Feb 2009 9:45 PM
Larry Serflaten
"mayayana" <mayayaX***@rcXXn.com> wrote
>    I've just been looking into an idea for a
> convenient way to save program settings.
> I'm wondering if anyone has done this and
> might have comments or thoughts about it:

If all your settings are simple data types (not
objects or pictures, etc) then a very simple
method is to use a User Defined Type which
can be loaded or saved to disk in one easy
operation....

LFS
Author
21 Feb 2009 11:54 PM
mayayana
>
> If all your settings are simple data types (not
> objects or pictures, etc) then a very simple
> method is to use a User Defined Type which
> can be loaded or saved to disk in one easy
> operation....
>

  That seemed like it might be a good idea, but the
result of testing it was ugly. :) I got some odd errors
and crashes. I'm not so sure that I can use a property
that's a UDT, anyway, but even if I could, the PropertyBag
WriteProperty method can't take a UDT.
Author
22 Feb 2009 2:23 AM
Larry Serflaten
Show quote Hide quote
"mayayana" <mayayaX***@rcXXn.com> wrote
> >
> > If all your settings are simple data types (not
> > objects or pictures, etc) then a very simple
> > method is to use a User Defined Type which
> > can be loaded or saved to disk in one easy
> > operation....
> >
>
>   That seemed like it might be a good idea, but the
> result of testing it was ugly. :) I got some odd errors
> and crashes. I'm not so sure that I can use a property
> that's a UDT, anyway, but even if I could, the PropertyBag
> WriteProperty method can't take a UDT.


What were you doing with the Property Bag?

Private Type UserSettings
  A as long
  B as Long
  .. etc...
End Type

Dim us as UserSettings

Sub Form_Load()
  SF = Freefile
  Open SettingsFile for binary as SF
  Get SF, , us
  Close SF
End Sub


The write operation is the same except for Put where
Get is.  I can't imagine how that could get ugly.
The ONLY hard part is deciding where the settings
file needs to go.....

LFS
Author
22 Feb 2009 4:26 AM
mayayana
I see what you mean. You're suggesting to use
the UDT as property storage to write to disk.
That's fine. Or I could use an INI file like I've
been using. That works well. But what I liked
about this PropertyBag method is that I can
essentially save a class to disk. I use a PropertyBag
with a single property, and to that property I assign
the class itself. The PropertyBag.Contents is then
a byte stream, reflecting the state of the class,
which gets written to a file. So it's easy to populate
the class on load. VB does it for me. I just read in
the byte stream, assign it to the Contents of anoyher
PropertyBag, then "read" the single property into a
class object variable. Then I can pass that class to the
main EXE and it won't need to have any settings
variables of its own. It can just work straight out of the
class.

   For instance, if I used to save a text color
in the Registry or in an INI file, I'd need to retrieve
it at startup, store it in a variable, and then do
something like:
  Ob.SelColor = TColor
With the PropertyBag approach I can save all of the
settings as a class "snapshot" that gets loaded again
on next run. So there's no retrieval work and no
variables. I can just do:
  Ob.SelColor = ClassSettings.TColor

  And when someone changes settings I can just set
my class to nothing and get a new copy.

  I had hoped that I could take a snapshot of the whole
class using this method, just capturing the memory
it inhabits, but it turns out that it can't work that
way. If I don't use the Class_ReadProperties and
Class_WriteProperties subs, as well as using PropertyChanged
when a property is changed, then the values don't
get written to disk. So it seems like this method should
work well but if I have, say, 50 program settings then it's
rather verbose. I'll need 100 Properties ( Get/Let * 50)
plus very long Class_ReadProperties and
Class_WriteProperties subs. I'm thinking that I might try
to somehow use some arrays to store multiple values.
I don't know yet whether the PropertyBag can handle that.

Show quoteHide quote
>
> What were you doing with the Property Bag?
>
> Private Type UserSettings
>   A as long
>   B as Long
>   .. etc...
> End Type
>
> Dim us as UserSettings
>
> Sub Form_Load()
>   SF = Freefile
>   Open SettingsFile for binary as SF
>   Get SF, , us
>   Close SF
> End Sub
>
>
> The write operation is the same except for Put where
> Get is.  I can't imagine how that could get ugly.
> The ONLY hard part is deciding where the settings
> file needs to go.....
>
> LFS
>
>
Author
22 Feb 2009 1:12 PM
Larry Serflaten
"mayayana" <mayayaX***@rcXXn.com> wrote

>   I see what you mean. You're suggesting to use
> the UDT as property storage to write to disk.
> That's fine. Or I could use an INI file like I've
> been using. That works well. But what I liked
> about this PropertyBag method is that I can
> essentially save a class to disk.

That would certainly have its uses in some
situations, but I would suggest its overkill for
this task.

Does all the extra overhead justify the means?

<...>

>    For instance, if I used to save a text color
> in the Registry or in an INI file, I'd need to retrieve
> it at startup, store it in a variable, and then do
> something like:
>   Ob.SelColor = TColor
> With the PropertyBag approach I can save all of the
> settings as a class "snapshot" that gets loaded again
> on next run. So there's no retrieval work and no
> variables. I can just do:
>   Ob.SelColor = ClassSettings.TColor

Where is that different from using the Type, which
after being read from the disk is nearly the exact same
syntax?

Ob.SelColor = US.TColor

>   And when someone changes settings I can just set
> my class to nothing and get a new copy.

Similarly with the Type, you need only call a function
to clear out all variables, or to set them to defaults:

Function BlankSettings() As UserSettings
' Erases all settings  ex: US = BlankSettings
End Function

Function DefaultSettings() As UserSettings
' Set defaults  ex: US = DefaultSettings
  With DefaultSettings
      A = 1
      B = "Two"
      ' ... etc ...
   End With
End Function


It is usually the case where 'settings' are specific to
the application they reside in.  Sure, window positions,
and a few other common courtesy settings are often
included, but there are usually going to be a majority
of values specifically used and named for each app
you write.  So my question is, with all that overhead
of property Lets and Gets in the class, added to the
code required to use the Propertybag, are you going
to want to go through that every time you need a
settings class?

If you instead put a settings type declaration in a
standard module, along with the Read and Save
functions, you have a module template that needs
only adjustments to the type variable names to
adapt to each new project.

So, excluding the 'cool' factor of saving the entire
class, is it really going to be worth the effort?

That is, (again,)  if all your data is held by intrinsic
data types, or arrays of instrinsic types.....

LFS
Author
22 Feb 2009 3:48 PM
mayayana
> Does all the extra overhead justify the means?
>

   I'm not sure. That's why I'm inviting comments
and criticism. It is a clunky method "under the
covers". It "feels" like saving the class whole,
in it's current state, but what it really entails is
just using a custom .FRX-type file that stores byte
data, strings and objects. (I've discovered that I can
save an array, but only dynamic byte arrays. So
to save a Long array I have to quadruple the UBound
and add a CopyMemory call to the Get/Let Properties.)

>
> Where is that different from using the Type, which
> after being read from the disk is nearly the exact same
> syntax?
>

  There's no difference there. And it's not different from
my usual method of just storing global settings variables:

   Ob.SelColor = TColor

>
> If you instead put a settings type declaration in a
> standard module, along with the Read and Save
> functions, you have a module template that needs
> only adjustments to the type variable names to
> adapt to each new project.
>
> So, excluding the 'cool' factor of saving the entire
> class, is it really going to be worth the effort?
>
   I like your idea of the UDT better than just using
global variables. And the class may not be worth it.
But it's not just a "cool factor". (It's certainly not
very cool to write all those properties. :) I guess
the potential appeal of the class boils down to two
things:

1) I don't have to parse out all of the settings
(INI/DAT storage), or make numerous Registry calls
(Registry storage). And I never have to rewrite the
values to disk or Registry.
   VB has to do it, and it's not pretty, but my
code can skip that step. I just have to have a short
function at load time to read the settings file into a
byte array, and a short function whenever settings
are changed to save the new byte array to disk and
update my copy of the class. Aside from those I can
treat the settings class as self-populating, self-updating.

2) #2 is specific to the idea of having a separate settings
DLL. I'm in a situation where a program has become large
and complex, and I'm thinking of breaking out some parts.
One of those is the settings window. Using the PropertyBag/
Class allows me to put the settings window and settings values
storage into a DLL that can pass all of the settings as a piece
by passing a class instance. I don't actually need the
PropertyBag for that. I could use a DLL and just save settings
to disk or Registry as usual. But I'd still need to use a class
to hold all the settings if I want to be able to pass them all in
a piece to the main EXE and avoid calling an external library in
the middle of functions, to retrieve values that should be
locally stored. I don't think I can use a UDT, though maybe
that's possible with early binding. (?) Maybe I could use a
Collection, but that seems somewhat awkward, and Collections
are slow. So if I *do* decide to use a class, then at that point
it seems I'd be crazy not to use the PropertyBag method to make
the class self-updating.

   At that point I run into another question: If I'm going to
use this DLL, is it better to load the DLL only at startup and
when someone wants to change settings, since settings are
likely to mostly stay the same once they've been selected?
Or is it better to just run the DLL for the life of the main EXE?

   I've noticed
that on Win98, at least, there seems to be a limit to how
much VB software can be running. Maybe it has to do with
an hWnd limit. NT seems to be much more sturdy and strong
in that regard. Nevertheless, I like the idea of keeping all of
those buttons, textboxes, etc. that are loaded in the settings
window, out of memory most of the time. It would notably
decrease the footprint of the program.
Author
22 Feb 2009 5:58 PM
Larry Serflaten
"mayayana" <mayayaX***@rcXXn.com> wrote

> >
> > Where is that different from using the Type, which
> > after being read from the disk is nearly the exact same
> > syntax?
>
>   There's no difference there. And it's not different from
> my usual method of just storing global settings variables:
>
>    Ob.SelColor = TColor

You're missing Intellisense.....


Show quoteHide quote
> > If you instead put a settings type declaration in a
> > standard module, along with the Read and Save
> > functions, you have a module template that needs
> > only adjustments to the type variable names to
> > adapt to each new project.

> 1) I don't have to parse out all of the settings
> (INI/DAT storage), or make numerous Registry calls
> (Registry storage). And I never have to rewrite the
> values to disk or Registry.
>    VB has to do it, and it's not pretty, but my
> code can skip that step. I just have to have a short
> function at load time to read the settings file into a
> byte array, and a short function whenever settings
> are changed to save the new byte array to disk and
> update my copy of the class.

You saw the IO used to get the UDT, it was 3 lines
of code (Open, Get, Close).  From that you get all
the settings, no re-creating a class and whatever else
for the PropertyBag....


> 2) #2 is specific to the idea of having a separate settings
> DLL. I'm in a situation where a program has become large
> and complex, and I'm thinking of breaking out some parts.
> One of those is the settings window. Using the PropertyBag/
> Class allows me to put the settings window and settings values
> storage into a DLL that can pass all of the settings as a piece
> by passing a class instance. I don't actually need the
> PropertyBag for that. I could use a DLL and just save settings
> to disk or Registry as usual. But I'd still need to use a class
> to hold all the settings if I want to be able to pass them all in
> a piece to the main EXE and avoid calling an external library in
> the middle of functions, to retrieve values that should be
> locally stored.

The last part is the key to whole design.  You typically use
settings in diverse places in your main EXE, so they need to
be globally available.  If you have several forms, you either
have to declare the class gobally, or you have to pass the
class between forms, to those that need it.  Most will say
using global variables should be avoided, but this is one
case where it is the more robust option.  Passing an object
between forms could get to be a hard to maintain tangled
mess.  Whereas declared globally, it becomes available to
all forms within the application.

> I don't think I can use a UDT, though maybe
> that's possible with early binding. (?)

You can't access a UDT late bound, its always early bound,
so to speak.  The only real advantage to using a class in
this instance is that a class has Initialize and Terminate
events you could use to access the disk, and the ability to
validate input in the Property Let events.

With a UDT, you'd have to decide when to access the disk,
and would need to validate the input where needed.  But other
than that, accessing the properties would be exactly the same.
The advantage of the UDT is in it reduced code requirement.


>    At that point I run into another question: If I'm going to
> use this DLL, is it better to load the DLL only at startup and
> when someone wants to change settings, since settings are
> likely to mostly stay the same once they've been selected?
> Or is it better to just run the DLL for the life of the main EXE?

Windows pretty much handles the loading and unloading of
such code modules.  Even if you set your class to nothing
that does not ensure the DLL will be removed from memory.

I guess the best teacher here is experience.  Try it both ways
and see which you prefer....

I just don't see the comparison myself.  There is so little code
needed when using the UDT, (even while it provides most of
the benefits of class like access,) that it seems obvious which
to use for typical applications.  If you need to store complex
data types, then a PropertyBag may be put to use, but for
simple data types, why add major effort for little gain?

As far as the smaller footprint, you still need to show
the settings window, but you should already know how
to control when that is moved into and out of memory.
Right?

Consider the code below as if it were added to a Standard
module.  To use it you need only assign the SettingsFile
file name and call the Settings routine.  To re-use it in
another application you need only change the variables
in the UDT if need be, and its ready to go....

???
LFS


Option Explicit
Public Type UserSettings
  A As Long
  B As String
  C() As Byte
End Type

Public Enum SettingsOptions
  usWrite = -1
  usDefault = 0
  usRead = 1
End Enum

Public US As UserSettings
Public SettingsFile As String

Public Sub Settings(ByVal Mode As SettingsOptions)
Dim sf As Long

  If Mode = usDefault Then
    US = DefaultSettings
  Else
    sf = FreeFile
    On Error GoTo Handler
    Open SettingsFile For Binary As sf
    If Mode < usDefault Then
      Put sf, , US
    Else
      Get sf, , US
    End If
    Close sf
    On Error GoTo 0
  End If

Handler:
  If Err.Number <> 0 Then
    Close
    MsgBox Err.Description, vbOKOnly, "User Settings Disk Access"
  End If

End Sub

Public Function DefaultSettings() As UserSettings
' reset settings
End Function
Author
22 Feb 2009 7:58 PM
mayayana
Aha! That's very nice. Thank you. I had no
idea that so many data types could be stored.
I assumed that you were just recommending the
UDT for holding settings but were populating it
by reading out the settings file and filling the UDT.
What you've got is really just what I had "hoped"
the PropertyBag was: A way to essentially just
write the memory of a data structure to disk. I
didn't think it would be possible to write the
content of pointer variables to disk.

  I tried a UDT with a string array and a long array.
Both work fine. The only limitation seems to be
that one can't assign the member to a fixed array.
But that's no problem, since it can be assigned
to an empty dynamic array. I can either do:

Dim A() as string
A = US.D
s1 = a(0)

Or:

s1 = US.D(0)

   And I have no trouble passing the UDT from an
ActiveX DLL as long as there's an early-binding
reference in the calling EXE. I also tried out some
code from Matthew Curland for loading COM DLLs
without registration. It's a fairly compact bit of code
and seems to work well. I can't imagine that he would
have put it into his book if it wasn't dependable.

   So that means I can have my settings window in
a DLL, pass the UDT to the main EXE, and do it all
without needing to register components. I think you're
right that that's much better than the Class/PropertyBag
method.
Author
22 Feb 2009 11:51 PM
Larry Serflaten
"mayayana" <mayayaX***@rcXXn.com> wrote
>     Aha! That's very nice. Thank you. I had no
> idea that so many data types could be stored.

That's what I was saying from the start.  Have a
look at my first response in this thread....


>    So that means I can have my settings window in
> a DLL, pass the UDT to the main EXE, and do it all
> without needing to register components.

So I'm curious, why someone would do that.  Could you
list for me the advantages to the user such a DLL offers,
and then the advantages to the programmer.

It just seems to me you are trying to make an optimization
that has little to no positive effect.  The downside is that
you'd unecessarily add a dependancy to your app. I assume
you realize that VB loads modules on demand.  If you don't
call up your settings form, it doesn't load into memory.
You could leave your settings window in the EXE and it
would never be loaded, unless the user specifically asks
for it.

What gain are you expecting to realize from the move?


LFS
Author
22 Feb 2009 11:54 PM
Bill McCarthy
Show quote Hide quote
"Larry Serflaten" <serfla***@usinternet.com> wrote in message
news:e2OJVhUlJHA.3888@TK2MSFTNGP02.phx.gbl...
>
> "mayayana" <mayayaX***@rcXXn.com> wrote
>>     Aha! That's very nice. Thank you. I had no
>> idea that so many data types could be stored.
>
> That's what I was saying from the start.  Have a
> look at my first response in this thread....
>
>
>>    So that means I can have my settings window in
>> a DLL, pass the UDT to the main EXE, and do it all
>> without needing to register components.
>
> So I'm curious, why someone would do that.  Could you
> list for me the advantages to the user such a DLL offers,
> and then the advantages to the programmer.
>
> It just seems to me you are trying to make an optimization
> that has little to no positive effect.  The downside is that
> you'd unecessarily add a dependancy to your app. I assume
> you realize that VB loads modules on demand.  If you don't
> call up your settings form, it doesn't load into memory.
> You could leave your settings window in the EXE and it
> would never be loaded, unless the user specifically asks
> for it.
>

Yep.  It sounds more like a response to poorly managed resources.  If the
settings are fundamental to the application, then that should be part of the
application. Even if dealing with localization, only the static default
values would be in a resource only dll.
Author
23 Feb 2009 2:34 AM
mayayana
> What gain are you expecting to realize from the move?
>

   It's true that I could just not load the form
when it's not needed, but as I said earlier, the
whole thing has become unwieldy. It's at a
point where I want to break out some of the
pieces so that I can work on them separately.