In User Modifiable Options, you've learnt how to create options for your skins. In this section, you'll learn the way to use these options for conditional compilation of Messenger's windows files, how to create custom option panels and about boxes for your skin and more.
Adding options in the restrictions of your resource groups is very practical for pictures, strings and other similar resources. However, for definition and style files, it can quickly become troublesome: options requiring modification in those files eventually combine together, requiring lots of different versions of the same definition file (3 options alone would require 8 versions of the same file to accommodate all the possible combinations).
You can solve this problem by adding conditions directly into your definition and style sheet files. When Messenger Plus! loads this kind of resource, it searches for specific condition tags and uses them to conditionally include parts of the file. Those tags are normally written <*PlusSkin ... *></*PlusSkin*> and are case sensitive. They can be inserted anywhere in the files and tags can be embedded in one another. Here is how it works:
A Conditions attribute is found in the tag, written as Conditions(condition string). Messenger Plus! marks the tag as being recognized and proceeds with its analysis:
Everything that's specified between the opening and the closing tag is subject to the condition string. The string is analyzed exactly the same way as when specified in the <Conditions> element of a restriction block. A complete opening tag looks like this:
<*PlusSkin Conditions(option = value) *>
If the condition is valid, the content specified between the tags is kept as-is, if not, it is removed from the file in memory before being sent to Messenger. In both cases, the PlusSkin tags are completely removed from the file, leaving no trace of them being there in the first place. When the content is kept, its text is analyzed the same way for possible sub condition tags.
Let's say you want to add an option in your skin called DispSignAuto that lets the user decides whether or not the "Sign me in automatically" checkbox is displayed in the logon window: open the definition file of the logon frame window (id 947 in Messenger 8.5) and search for the checkbox (it's using id=atom(idMakeDefaultUserChk) in Messenger 8.5). Here is how it may look like:
<Checkbox id=atom(idMakeDefaultUserChk) Class="CheckBox"> <ButtonIcon LayoutPos=Left/> <ButtonText LayoutPos=Client/> </Checkbox>
To conditionally include this block of text in your skin without having to make a duplicate of the file, you need to include the block in a condition tag, like this:
<*PlusSkin Conditions(DispSignAuto = true) *> <Checkbox id=atom(idMakeDefaultUserChk) Class="CheckBox"> <ButtonIcon LayoutPos=Left/> <ButtonText LayoutPos=Client/> </Checkbox> </*PlusSkin*>
If you had an additional option to add or remove the ButtonText element from this text, it could be added the same way in the existing condition block (note: this is for demonstration purposes only, removing this element won't necessarily do anything visible).
<*PlusSkin Conditions(DispSignAuto = true) *> <Checkbox id=atom(idMakeDefaultUserChk) Class="CheckBox"> <ButtonIcon LayoutPos=Left/> <*PlusSkin Conditions(AnotherOption = false) *> <ButtonText LayoutPos=Client/> </*PlusSkin*> </Checkbox> </*PlusSkin*>
Because condition strings can also be used in style sheet files, you can now add many options in your skin to let the user decide on minor but important details such as colors, text formatting, etc... don't hesitate to use this technique whenever possible to make your skin more enjoyable for everyone!
Sometimes, it may be easier to link an option's value directly with what's inserted in the definition files. Let's consider the following example which uses a boolean option named ShowButton.
<*PlusSkin Conditions(ShowButton = true) *> <Element visible=true> ... </Element> </*PlusSkin*> <*PlusSkin Conditions(ShowButton = false) *> <Element visible=false> ... </Element> </*PlusSkin*>
Although the two conditions could be inserted directly next to visible=, this piece of code shows an apparent need for simplification, which can be done using the ValueOf statement. Using this technique, the code can be simplified like this:
<Element visible=<*PlusSkin ValueOf(ShowButton)*/> > ... </Element>
Any option's value can be inserted directly into a file, without additional conditions, simply by using ValueOf. You'll notice that because no data is necessary in this case, the element can be closed directly with /> to avoid adding the usual bigger </*PlusSkin*>. Note that string option's values are inserted without quotes so it is your responsibility to add them in between the PlusSkin element, if needed.
In Messenger Plus! Live 4.60 and above, environment conditions can be used the same way option conditions are. This is done with the Environment statement. Instead of specifying one of your options' names, you simply need to specify one of the known property names supported by the system. Here is an example of how to include an element based on the current version of Messenger.
<*PlusSkin Environment(MsgVersion = "8.5") *> <Element> ... </Element> </*PlusSkin*>
Here are the properties you can use for your environment conditions:
Note: you cannot mix environment conditions and options based conditions in one tag. If you want to use both kinds of conditions, you need to define two different <*PlusSkin*> tags, embedded in one another.
If you're a user of Messenger Plus!, you know that the software changes some elements of the Messenger windows to add its own features. The most obvious modification is the addition of icons in the contact list's and the chat windows' toolbars. Although these changes are coded to automatically adapt to most skins, some definition files with advanced modifications may prevent Messenger Plus! to include its material, inclusion may not be suitable for your skin or you may simply want to relocate those features elsewhere.
Skininfo files can request that these modifications do not take place automatically when the skin is loaded. All that's needed is one of the following elements, added in <Options>\<MessengerPlus>:
This code will prevent Messenger Plus! from adding its icons in the main toolbar of chat windows:
<Options> <MessengerPlus> <AllowChatWndChange>false</AllowChatWndChange> </MessengerPlus> </Options>
Because most users expect Messenger Plus! features to be accessible in every skin, removing them with these options also means adding them back manually in your windows. If you're familiar enough with definition files to do such a thing, all you need to know is that your buttons need a cmdid attribute ranging from 7801 to 7810. This represents the command ids used by Messenger Plus! in Messenger's windows and any element that sends this id will trigger the same response as the original (like displaying a menu).
What good is it to skin Messenger if you don't even have control over your own option panel and about box? doing such a thing is possible with a Messenger Plus! interface file. Before you read the rest of this section, please check out Skinning Messenger Plus! Itself. All the basics about Messenger Plus! windows can be found there and you'll need this information to fully understand what's next.
By default, Messenger Plus! creates a generic child window template for your skin's options. Every option is listed, one on each line and skininfo elements such as DispLabel and DispHelp are used to display the appropriate labels. With a custom template, none of this happens and you're free to do anything you like. You create your own template, from scratch, you include the options you want in it, you can add extra elements such as pictures to improve the look of the window and you can even use different control types for your options. In addition to all of that, custom templates can be created in multiple languages to accommodate different localized versions of Messenger.
Here is the result of a custom template created for Test Skin Revisited:
This option panel has a bigger title that's colorized, a picture of the clouds background and the "Remember me" options are in a list box instead of a combo box. You may also notice that the text displayed in the checkbox and list items is different from what was specified in the skininfo file.
Option panels are created like any other Messenger Plus! window but they need to use <ChildTmpl/> as Messenger Plus! will embed your creation into a standard frame with OK/Cancel buttons. The option panel file is loaded like any another Messenger Plus! skinned interface: you specify the directory where the file is located and Messenger Plus! takes care of the rest. Images referenced in your option panel are loaded from the Images subdirectory. The main difference with <PlusSkin> is that for option panels, you also need to specify the interface file name as well as the window's ids.
Here is an example of how to declare a custom option panel in skininfo:
<Options> <Skin> ... <OptionInterface> <InterfaceDir>OptionPanel</InterfaceDir> <InterfaceFile>OptInterfaces.xml</InterfaceFile> <WindowIds> <WindowId Language="en-us">SkinOpt</WindowId> </WindowIds> </OptionInterface> </Skin> </Options>
In this example, the window's template will be loaded from %skindir%\OptionPanel\OptInterfaces.xml. In this file, the software will locate window's id SkinOpt and will display its content in the option panel. Images for this window will be loaded from %skindir%\OptionPanel\Images. Click here to get the interface window's code and picture used in the example above.
You'll notice that "en-us" was specified as the window's language. A Language attribute is required for every <WindowId> element and in this case, it simply means that the text in the window is displayed in English. The system allows you to create localized versions of the window but you don't have to do that if you don't want to. One <WindowId> element can be specified for each language code that you support (Messenger Plus! compares the code with the one specified in Messenger) and if no matching language can be found, the first window in the list is loaded and its language code is ignored.
For example, if you also had a French version of your panel available for French users, you would write:
<WindowIds> <WindowId Language="en-us">SkinOpt</WindowId> <WindowId Language="fr-fr">SkinOptFrench</WindowId> </WindowIds>
With this code, the SkinOptFrench window will be loaded in French versions of Messengers only and the SkinOpt window will be loaded for any other language (because it's the first windows that's specified).
You can add any element and controls you wants in your option panel using any Id of your choice. Everything will be displayed as-is by Messenger Plus! and connections will be made only in the following circumstances:
As you can see, properties can be associated with more than one kind of control. For MultiVal properties, listboxes and comboboxes can be used exactly the same way, however, there's a particularity to using radio button controls for BoolVal properties. Each property can only be associated to one control so if you add two radio buttons, you'll need two properties, you cannot specify that one radio button is for true and the other one is for false (this would result in the creation of two mutually exclusive properties).
In Messenger Plus! 4.60 and above, the AboutWnd id can be used to add a button linking to your own customized about box. When the control is clicked, Messenger Plus! searches for the id of an about box defined in your skininfo in <AboutIds>. About box windows are defined like option windows and are associated to a language to allow localization. Example:
<AboutIds> <AboutId Language="en-us">SkinAbout</AboutId> </AboutIds>
Finally, the AboutUrl id can be used to add a button linking to your web site (as specified in the <Information> block). Other link controls in the window are analyzed for possible url recognition. If the caption of a link control contains no space and begins with either "http://" or "https://", the corresponding address is automatically opened in the default web browser when the control is clicked. Any other control with any other id won't be associated to your properties and will only serve as decoration. Here is the interface code that was used to associate the two properties of Test Skin Revisited to the interface shown in the screenshot:
<Control xsi:type="ListBoxControl" Id="RememberMeTxt"> <Position Top="37" Width="97" Left="5" Height="40"/> <Items> <Item Id="goodbye">This is goodbye</Item> <Item Id="hello">This is hello</Item> </Items> </Control> <Control xsi:type="CheckBoxControl" Id="ChangeBkg"> <Position Top="88" Width="150" Left="5"/> <Caption>Change &background picture to:</Caption> </Control>
One last thing you can notice in this code is the <Item> elements specified in the list box control. They are not required: if <Items> is not present or empty, all the values specified in the MultiVal property are listed in order, with their DispLabel, exactly like in the generic template. If you want to translate their display label, change their order or prevent users from selecting some of the values specified in your skin (while in beta tests for example), use <Item> elements and set the Id attribute to correspond to the the value's name.
Options in Messenger Plus! skins is a vast subject. Like it is the case for so many other things, spend time working with the feature and you'll quickly forget about the technical details. The only thing that will remain from this learning experience is the fun of designing new windows, adding special options to your skin, etc... this section almost concludes the Specialized Subjects chapter. If you've read all the sections of all the chapters of this documentation, congratulations and thank you very much for your time. We hope to see your creations online soon!
Specialized Subjects, User Modifiable Options, Skinning Messenger Plus! Itself.