|
User Modifiable Options
Skins often tend to modify key elements of the Messenger
interface. In addition to changes to the look of the windows,
things like buttons, toolbars, links and menus are often modified
or removed by them. The main problem with functional changes such
as these is that in most cases, no choice is given to the user.
Skins that are distributed in static hard-patch packages present
themselves as one single entity doing all sorts of things, some of
which users may dislike.
Instead of requiring from the developer to decide everything on
behalf of his users, Messenger Plus! skins allow the creation of
sets of user modifiable options. These options are displayed
together in a special window, accessible from the skin menu and the
preferences panel, which can also be customized to incorporate
things like a banner, additional links to your web site, etc...
Messenger Plus! takes care of all the technical details, all you
need to do is declare the name of an option and use it the way you
deem necessary.
Declaring New Options
User options are declared in the <Skin>\<Properties> child of the
<Options> element. Every property
has a name, a type and a default. Additional display elements such
as DispLabel and DispHelp are also available to create more user
friendly option panels. Here are the two current types of
properties offered by Messenger Plus!:
- BoolVal. A simple true/false value. It can be
used for options that only require to be either enabled or disabled
and is represented with a checkbox control by default.
- MultiVal. A value that can be set to any given
string. Use it for options that require a selection to be made in a
list. It is represented with a combobox (dropdown) control by
default.
Options only allow users to make a choice between predefined
values that you created for them. The Messenger Plus! skinning
system does not allow variable options (example: strings entered in
an edit box) for security reasons. You can never be sure of what
users can specify in a non-controlled environment and this may lead
to crashes in Messenger.
All the options you specify in your skininfo file are
automatically displayed by Messenger Plus! in a option panel
created specifically for your skin. Every option is displayed in
the order specified in the file and Messenger Plus! takes care of
reading/saving the properties in the Windows' registry. If an
option is changed, Messenger Plus! also asks the user if Messenger
should be restarted immediately for the options to be applied. A
restart is always required for new option values to be applied
because of optimizations made in Messenger and Messenger Plus!
itself.
Here is an example of how to declare two options for your skin,
one boolean and the other one list-based. Note that spaces are not
allowed in the Name attributes.
<Options>
<Skin>
<Properties>
<BoolVal Name="ChangeBkg">
<Default>true</Default>
</BoolVal>
<MultiVal Name="RememberMeTxt">
<Values>
<Value>hello</Value>
<Value>goodbye</Value>
<Value>farewell</Value>
</Values>
<Default>hello</Default>
</MultiVal>
</Properties>
</Skin>
</Options>
That's all you've got to do for Messenger Plus! to recognize and
take care of your options!. If you add this code to the Test Skin file and restart Messenger, you'll
notice that a "Skin's Options" menu is now available for it.
Here is the window that Messenger Plus! will generate for these
options:
As you can see, the default values are properly set in this
screen. Because skins are loaded when Messenger starts-up, the
options are global to every user registered in a given Windows'
account. Options are displayed with their name by default but
DispLabel elements and attributes
should always be used for added clarity. Using display names will
also allow you to change the text displayed in your options window
without risking to alter the internal name of your option and
breaking some of your skin's code as a result (seen later in this
section).
Both BoolVal and MultiVal accept <DispLabel> elements. Values specified in a
MultiVal also accept DispElement but as an attribute. If additional
information is required to explain the purpose of an option, a
<DispHelp> element can be added
for tooltip creation. Let's modify the example's code to take
advantage of all of this:
<Options>
<Skin>
<Properties>
<BoolVal Name="ChangeBkg">
<DispLabel>Change the background picture</DispLabel>
<DispHelp>This option displays a cloudy sky</DispHelp>
<Default>true</Default>
</BoolVal>
<MultiVal Name="RememberMeTxt">
<DispLabel>New "Remember Me" label</DispLabel>
<Values>
<Value DispLabel="Hello World!">hello</Value>
<Value DispLabel="Goodbye Planet!">goodbye</Value>
<Value DispLabel="Farewell Kosmos!">farewell</Value>
</Values>
<Default>hello</Default>
</MultiVal>
</Properties>
</Skin>
</Options>
The updated screenshot shows a window that's now appropriate for
general public use. The tooltip added by <DispHelp> will be shown only when the mouse
cursor is left a couple of seconds hovering above the ChangeBkg checkbox.
Of course, declaring the options is just half of the story.
Let's see how to put these variables into good use.
Option Restrictions
As you saw in Restrictions: How and
Why?, resource groups can be paired to blocks of restrictions
for conditional loading. User options are one of the restrictions
you can use for each resource group. Thanks to them, you can now
easily design different resources to match different options.
Options can be specified as restrictions in two different ways
that could be called "basic" and "advanced". Several options can be
grouped together in a restriction block and the principle is the
same as with any other restriction kind: grouping is made with a
logical OR so the resources will be loaded as long as one of the
option conditions is considered valid. Conditions are specified in
what's called an Option Set. With the basic
method, each <OptionSet> element
specifies a single option and is represented in XML like this:
<Restrictions>
<SkinOptions>
<OptionSet>
<BoolVal Name="ChangeBkg">true</BoolVal>
</OptionSet>
<OptionSet>
<MultiVal Name="RememberMeTxt">goodbye</MultiVal>
</OptionSet>
</SkinOptions>
</Restrictions>
The example above can be read as "Load this groups if
ChangeBkg is true OR RememberMeTxt
is goodbye". Let's say that you want to
use a more elaborate condition such as "ChangeBkg is true AND
RememberMeTxt is farewell": to do that you'll need to use the
advanced method.
Option sets
can use condition strings instead of single option
element. These strings allow a mix of AND and OR with an unlimited
number of options. Here are a couple of examples:
- ChangeBkg = true
- RememberMeTxt != "hello"
- ChangeBkg = true AND RememberMeTxt != "hello"
- ChangeBkg = false OR RememberMeTxt = "goodbye"
- RememberMeTxt = "hello" OR RememberMeTxt =
"hello" AND ChangeBkg = false
Condition strings use a simple syntax that recognizes the
following operators:
Boolean values are either true or
false and strings are enclosed between
"" or ''.
The \, " and ' characters must be escaped if
written in a string (written \, \", and '). != stands for 'not equal to'.
Parenthesis are not supported: conditions are evaluated from left
to right and OR operators have grouping priority over AND. Any
number of space characters can be used to separate each entity.
Operators are case sensitive but options' names and values are
not.
Priority of operators means that the last example in the list
above is read by Messenger Plus! as (RememberMeTxt =
"hello" OR RememberMeTxt = "hello") AND
ChangeBkg = false. The reason why OR conditions are grouped is
because to write RememberMeTxt = "hello" OR
(RememberMeTxt = "hello" AND ChangeBkg = false)
you simply need to add two different option sets. If you're not
familiar with programming languages, this may not make much sense
to you right now but if you start using condition strings, you'll
quickly get used to how they work. For now, let's just see how to
rewrite the example above with one condition string:
<OptionSet>
<Conditions>ChangeBkg=true OR RememberMeTxt="goodbye"</Conditions>
</OptionSet>
Test Skin Revisited
Let's use what we've learned here to improve the Test
Skin project. This new skin allows the user to enable or
disable the new background and offers two alternatives for the
"Remember Me" text replacement. To make sure you've understood the
content of this section correctly, please try to do the
modifications yourself on the original
code and compare your solution with the one below.
<SkinInfo>
<Information>
<Name>Test Skin Revisited</Name>
</Information>
<Options><Skin>
<Properties>
<BoolVal Name="ChangeBkg">
<DispLabel>Change the background picture</DispLabel>
<Default>true</Default>
</BoolVal>
<MultiVal Name="RememberMeTxt">
<DispLabel>New "Remember Me" label</DispLabel>
<Values>
<Value DispLabel="Hello World!">hello</Value>
<Value DispLabel="Goodbye Planet!">goodbye</Value>
</Values>
<Default>hello</Default>
</MultiVal>
</Properties>
</Skin></Options>
<MessengerSkin>
<!-- background replacement -->
<ResGroup>
<Restrictions>
<MsgVersions>
<Version Major="8" Minor="5"/>
</MsgVersions>
<SkinOptions>
<OptionSet>
<BoolVal Name="ChangeBkg">true</BoolVal>
</OptionSet>
</SkinOptions>
</Restrictions>
<Resources><Replace>
<Graphics><Pictures>
<Picture Id="20061">
<File>clouds.jpg</File>
</Picture>
</Pictures></Graphics>
</Replace></Resources>
</ResGroup>
<!-- "hello" alternative to Remember Me -->
<ResGroup>
<Restrictions>
<MsgVersions>
<Version Major="8" Minor="5"/>
</MsgVersions>
<SkinOptions>
<OptionSet>
<MultiVal Name="RememberMeTxt">hello</MultiVal>
</OptionSet>
</SkinOptions>
</Restrictions>
<Resources><Replace>
<Strings>
<String Id="61288">Hello World!</String>
</Strings>
</Replace></Resources>
</ResGroup>
<!-- "goodbye" alternative to Remember Me -->
<ResGroup>
<Restrictions>
<MsgVersions>
<Version Major="8" Minor="5"/>
</MsgVersions>
<SkinOptions>
<OptionSet>
<Conditions>RememberMeTxt = "goodbye"</Conditions>
</OptionSet>
</SkinOptions>
</Restrictions>
<Resources><Replace>
<Strings>
<String Id="61288">Goodbye Planet!</String>
</Strings>
</Replace></Resources>
</ResGroup>
</MessengerSkin>
</SkinInfo>
It's Not Over Yet
The subject of options cannot be dealt with in a single section
of documentation. Much more can be done with what you've just
learnt so once you'll have practiced what is shown here, go read
about Options for Advanced
Users.
See Also
Specialized Subjects,
Options for Advanced Users.
|