Just about every program ends up with some global variables when it gets large enough, and managing them is just one of those things which you have to take into account as you continue extending or bug fixing the program. Being someone who dislikes having to constantly run into situations where "Oh no, I need another global!", I started using a Dictionary Object with VB programs. That was fairly simple, the object didn't care what type of value you passed to it, and VB didn't care what it got from it. On the surface that is, I know there was a lot of type casting going on in the background in the compiled program, didn't care.
In "porting" one of my programs from VB to PB, I really needed to maintain some use of that ability to manage all my configuration settings in a single place so it was not only easy to access and use, but to also be able to export and import the settings. Really critical stuff when you want to be able to permit the user of the program to adjust things to their taste, and not have to do it each time they start the program.
So, I wrote a class which would fufill that need:
That's my template, which is included in the attached zip file, it's read by the Excel VBA, also in the attached zip, and filled in to produce something which manages the various settings you need to manage your program's operation. Lets Go over all the various psuedo %variables% so you can see how I put all this together.
%INSERTCONSTANTS%
The constants are part of being able to use the class easy, the whole idea was to make it easy to get and set values in the class without needing to remember what ID was which value, and to not use a string for lookup.
%INSERTINSTANCES%
The compiler is not complaining about variable names being the same as the constants, and overall, it makes readability of the class easy. The class is designed to handle 3 types of values, STRING, LONG, and BOOLEAN. Seeing as PB don't have an intristic boolean value, it's a tad faked with a long.
%INSERTGETSTRING% / %INSERTSETSTRING% (cString)
These two sections are for managing strings in the class, I suppose if you wanted to access values as strings, you could also include that ability into the class, however, as I constructed it, if the value you wanted was not a string, then an empty string is returned. Could probably add error management into the class so it does something if the programmer does something funky like that.
%INSERTGETTITLE% (cTitle)
Special purpose class item for when I throw up an Open File dialog or a Browse For Folder dialog I can get the title for the function from the class based on the value I'm permitting the user to adjust.
%INSERTGETVALUES% / %INSERTSETVALUES% (cValue)
Overall, there is no restriction on having a class like this limited to strictly Long's for values, at this point, I have no need to include other values than the three I was interesting in maintaining. It's not unfeasable to include structures into the class and use the class for managing something complex.
%INSERTGETBOOLEAN% / %INSERTSETBOOLEAN% (cBoolean)
You will note, from the above template, and when dealing with boolean values in the configuraton class, I explicitedly set the inbound value to being either true or false, and likewise, when returning the value from the class, by using the ISTRUE function.
%INSERTGETNAME% (cName)
%INSERTGETINDEX% (cIndex)
I suppose these two properties could of been made private to the class, it's a waffle. But they're for the next part of this class. The first one is for fetching the name of the associated configuration variable and the second is for determining the index for that name.
%INSERTCONSTRUCTORS% (MakeConfigurationString)
%INSERTDESTRUCTORS% (SetConfigurationValue)
I suppose you could include the ability to load and save the configuration settings to a file as part of the class, I didn't include that due to the need to have "other" values written to the file, mainly a recent files list. Hence the reason that SetConfigurationValue returns either TRUE or FALSE from the operation, if FALSE, then the line from the file needs to be handled differently.
In "porting" one of my programs from VB to PB, I really needed to maintain some use of that ability to manage all my configuration settings in a single place so it was not only easy to access and use, but to also be able to export and import the settings. Really critical stuff when you want to be able to permit the user of the program to adjust things to their taste, and not have to do it each time they start the program.
So, I wrote a class which would fufill that need:
Code:
' class Configuration Manager %INSERTCONSTANTS% CLASS ConfigurationClass %INSERTINSTANCES% CLASS METHOD CREATE() END METHOD CLASS METHOD DESTROY() END METHOD INTERFACE ConfigurationHandler INHERIT IUNKNOWN PROPERTY GET cString(BYVAL ItemIndex AS LONG) AS STRING LOCAL rString AS STRING IF ItemIndex <= %cfgMax THEN SELECT CASE ItemIndex %INSERTGETSTRING% END SELECT END IF PROPERTY = rString END PROPERTY PROPERTY SET cString(BYVAL ItemIndex AS LONG, BYVAL ItemValue AS STRING) IF ItemIndex <= %cfgMax THEN SELECT CASE ItemIndex %INSERTSETSTRING% END SELECT END IF END PROPERTY PROPERTY GET cTitle(BYVAL ItemIndex AS LONG) AS STRING LOCAL rString AS STRING IF ItemIndex <= %cfgMax THEN SELECT CASE ItemIndex %INSERTGETTITLE% END SELECT END IF PROPERTY = rString END PROPERTY PROPERTY GET cValue(BYVAL ItemIndex AS LONG) AS LONG LOCAL rValue AS LONG IF ItemIndex <= %cfgMax THEN SELECT CASE ItemIndex %INSERTGETVALUES% END SELECT END IF PROPERTY = rValue END PROPERTY PROPERTY SET cValue(BYVAL ItemIndex AS LONG, BYVAL ItemValue AS LONG) IF ItemIndex <= %cfgMax THEN SELECT CASE ItemIndex %INSERTSETVALUES% END SELECT END IF END PROPERTY PROPERTY GET cBoolean(BYVAL ItemIndex AS LONG) AS LONG LOCAL rBoolean AS LONG IF ItemIndex <= %cfgMax THEN SELECT CASE ItemIndex %INSERTGETBOOLEAN% END SELECT END IF PROPERTY = ISTRUE rBoolean END PROPERTY PROPERTY SET cBoolean(BYVAL ItemIndex AS LONG, BYVAL ItemValue AS LONG) IF ItemIndex <= %cfgMax THEN ItemValue = ISTRUE ItemValue SELECT CASE ItemIndex %INSERTSETBOOLEAN% END SELECT END IF END PROPERTY PROPERTY GET cName(BYVAL ItemIndex AS LONG) AS STRING LOCAL rName AS STRING IF ItemIndex <= %cfgMax THEN SELECT CASE ItemIndex %INSERTGETNAME% END SELECT END IF PROPERTY = rName END PROPERTY PROPERTY GET cIndex(BYVAL ItemName AS STRING) AS LONG LOCAL rIndex AS LONG SELECT CASE UCASE$(ItemName) %INSERTGETINDEX% CASE ELSE rIndex = -1 END SELECT PROPERTY = rIndex END PROPERTY METHOD MakeConfigurationString(BYVAL ItemIndex AS LONG) AS STRING LOCAL cString AS STRING cString = me.cName(ItemIndex) IF LEN(cString) > 0 THEN cString = cString & "=" SELECT CASE ItemIndex %INSERTCONSTRUCTORS% END SELECT END IF METHOD = cString END METHOD METHOD SetConfigurationValue(BYVAL cString AS STRING) AS LONG LOCAL ItemIndex AS LONG LOCAL cValue AS STRING LOCAL Success AS LONG ItemIndex = me.cIndex(TRIM$(PARSE$(cString, "=", 1))) cValue = TRIM$(PARSE$(cString, "=", 2)) Success = %TRUE SELECT CASE ItemIndex %INSERTDESTRUCTORS% CASE ELSE Success = %FALSE END SELECT METHOD = Success END METHOD END INTERFACE END CLASS
%INSERTCONSTANTS%
Code:
%cfgActiveFolder = 0 %cfgCloseGracefully = 1 %cfgSaveOnExit = 2 %cfgScreenX = 3 %cfgScreenY = 4 %cfgUseLongNames = 5 %cfgWindowCount = 6 %cfgWorkingFolder = 7 %cfgMax = 7
%INSERTINSTANCES%
Code:
INSTANCE cfgActiveFolder AS STRING INSTANCE cfgCloseGracefully AS LONG ' Boolean INSTANCE cfgSaveOnExit AS LONG ' Boolean INSTANCE cfgScreenX AS LONG INSTANCE cfgScreenY AS LONG INSTANCE cfgUseLongNames AS LONG ' Boolean INSTANCE cfgWindowCount AS LONG INSTANCE cfgWorkingFolder AS STRING
%INSERTGETSTRING% / %INSERTSETSTRING% (cString)
Code:
SELECT CASE ItemIndex CASE %cfgActiveFolder rString = cfgActiveFolder
Code:
SELECT CASE ItemIndex CASE %cfgActiveFolder cfgActiveFolder = ItemValue
%INSERTGETTITLE% (cTitle)
Code:
SELECT CASE ItemIndex CASE %cfgWorkingFolder rString = "Select Default Working Folder"
%INSERTGETVALUES% / %INSERTSETVALUES% (cValue)
Code:
SELECT CASE ItemIndex CASE %cfgScreenX rValue = cfgScreenX
Code:
SELECT CASE ItemIndex CASE %cfgScreenX cfgScreenX = ItemValue
%INSERTGETBOOLEAN% / %INSERTSETBOOLEAN% (cBoolean)
Code:
SELECT CASE ItemIndex CASE %cfgCloseGracefully rBoolean = cfgCloseGracefully
Code:
SELECT CASE ItemIndex CASE %cfgCloseGracefully cfgCloseGracefully = ItemValue
%INSERTGETNAME% (cName)
Code:
SELECT CASE ItemIndex CASE %cfgActiveFolder rName = "cfgActiveFolder"
Code:
SELECT CASE UCASE$(ItemName) CASE "CFGACTIVEFOLDER" rIndex = %cfgActiveFolder
%INSERTCONSTRUCTORS% (MakeConfigurationString)
Code:
SELECT CASE ItemIndex CASE %cfgActiveFolder cString = cString & ME.cString(ItemIndex) CASE %cfgCloseGracefully cString = cString & IIF$(ISTRUE ME.cBoolean(ItemIndex), "True", "False") CASE %cfgScreenX cString = cString & FORMAT$(ME.cValue(ItemIndex))
Code:
SELECT CASE ItemIndex CASE %cfgActiveFolder ME.cString(ItemIndex) = cValue CASE %cfgCloseGracefully ME.cBoolean(ItemIndex) = IIF(ucase$(cValue) = "TRUE", %TRUE, %FALSE) CASE %cfgScreenX ME.cValue(ItemIndex) = VAL(cValue)