Skins
Introduction
Creating a skin for YaZZle is fairly straightforward, though due to the amount of things that can be skinned, and multiple ways to accomplish a task, there can be quite a bit of work involved. Besides some first necessary steps though, most things after that are optional. In general, a skin is just a collection of images (can be just a few) and one or more textfiles (with .ini extension) which hold commands on where and how to display the images.
What you need first is a new folder and a textfile renamed to 'main.ini'. Start it with these lines/properties - they'll be displayed in the skin choosing dialog:
[General] Name=Name of skin Author=Your name Description=Short line with description
Comments
If you want to add comments in your .ini files, explaining things (which is considered an nice gesture to other skinners disecting yours), put a semicolon before these lines; these will not be read by Yazzle.
We'll now go through all parts of the skin. Note you can zoom in on the images used in this tutorial by hovering your cursor over them. Also hovering anyway marked words could get you a more detailed (tooltip) explanation.
In general, it's a good idea to copy the files of an existing skin with options you want to a new folder and go from there. This tutorial uses the 'plastique' skin as an example, as it's not designed to be good looking, but to show off Yazzle options.
Wherever images are involved, this tutorial uses .bmp. In your skin though, you can also use .png and .jpg.
- Main window
- Adding text fields
- Format (rightclick)menu's & tooltips
- Adding pilemat images
- Adding buttons
- Transparency & alphablending
- Splash- & pauze screen
- Dialogs
- Adding additional bitmaps
- Conclusion
Main window
Basically, there's two ways to do your background image. Most simple is creating a 24-bit colored image and let Yazzle stretch it for you when being resized. You'll only need these lines in main.ini:
[Background] Image=background.bmp
This could be your Yazzle skin, the only thing required to display it is defining the playing area (required in all skins):
[PlayingArea] X=8 Y=37 W=80 H=8
The x, y properties define starting point of playing area in pixels; w, h width and height (thus where it ends, calculated by Yazzle). When whole bitmap gets stretched, playing area gets stretched likewise. Use this to define parts at edges you don't want covered by cards. This could already be your full skin.
But, stretching an image blurs it, and doesn't necessarily look good. Most skinners will look for a way to get more pixel precision. For this, create an image - it can be very small - with corners exactly as you want, and sides plus middle that can be either tiled or stretched. Here's the plastique .bmp:

In this skin corners are displayed exactly as is, sides and center are tiled by defining this in the .ini:
[Background] Image=background.bmp StretchResize=0 CenterTiled=1 TopLeftWidth=9 TopRightWidth=86 TopHeight=38 BottomLeftWidth=9 BottomRightWidth=10 BottomHeight=37 LeftTopHeight=38 LeftBottomHeight=37 LeftWidth=9 RightTopHeight=38 RightBottomHeight=37 RightWidth=10
The last 12 properties make Yazzle stop resizing whole bitmap. For each side, there's 3 properties in which you define width (top/bottom) or height (left/right) of the beginning and end of the side, then height (top/bottom) or width (left/right) of whole side. Here's result in our case:

No Tic-Tac-Toe
Ofcourse, it's most easy to create an evenly divided 9 square. But if you want to get fancy, you got to understand what Yazzle is doing here.
What happens is this. Top, bottom, left and right side are drawn seperately. They all have 3 parts, a beginning, middle and end. Including center, that's 13 parts, as opposed to the 9 parts you see here, they overlap. As such, you can create more complicated frames, once you know drawing order.
Order is this: top beginning, top middle, top end, bottom beginning, bottom middle, bottom end, left beginning, left middle, left end, right beginning, right middle, right end, center.
The property ‘StretchResize=0’ - defines that middle parts are to be tiled. Default is ‘1’, stretched (no need for this line at all if you want that).
Other property, ‘CenterTiled=1’ tells that the center part is to be tiled (0 being default, no need for this line if you want that).
There's only one way to add transparency to the background, and that's using magenta (RGB 255 0 255 aka ‘magic pink’, a long established skinning tradition). Other parts of the skin can have alphablended transparency, main window has just this. Notable is this is applied to the window with all other parts (buttons, text) drawn, meaning if a button is over a transparent area, transparency will apply to the button too. If transparency is applied to parts that will be stretched or tiled, transparent part gets treated likewise.
A last, sensible thing to add is a minimum size (of whole application) to this section:
[Background] MinWidth=640 MinHeight=480
By default display of the cards is limited to the playing area. If you want them displayed over whole program (can't have them over whole screen), add ‘ClipPlayingArea=0’ to this section of the .ini.
Adding text fields & color other text
Now, you'll want some text added to our window, like which game is actually being played in a titlebar. There's 6 text sections you can add, and some font settings to go with that. Lets start with general font formatting:
[DefaultFont] Name=trebuchet ms File=trebuc.ttf Size=10 Bold=1 Italic=0 Red=0 Green=0 Blue=0 Shadow=2 ShadowRed=121 ShadowGreen=148 ShadowBlue=173 MouseOverRed=198 MouseOverGreen=57 MouseOverBlue=57 HighlightRed=152 HighlightGreen=219 HighlightBlue=86
It's all pretty self-explanatory. First line defines font be be used by its friendly name, optionally, when using a non-standard font (that's distributable), you can include it in skins folder (‘File=’). Size, weight and italic can be set. Optional shadow - bottom-right direction - distance can be set, and its color. The MouseOverRGB and HighlightRGB settings are not used in main window, will be used later for additional dialogs. Now here's the text fields these will apply to:
- [GameTitle]
- Displays current game, prefixed with easy/hard.
- [GameTime]
- Displays playing time.
- [GameNumber]
- Displays number of current game.
- [GameMoves]
- Displays number of moves made.
- [GameScore]
- Displays number of cards that are played free to foundation.
- [WallClock]
- Displays current time, in format you choose.
All these are added as new sections in main.ini and follow same format:
[TextSection] X=# Y=# W=# H=# C=1 ;other options are 2, 3, 4 HorzCentered=0|1 VertCentered=0|1 LeftAligned=0|1 RightAligned=0|1 TopAligned=0|1 BottomAligned=0|1
Percentual placement
Now what if you want something placed in middle of a side, whatever size Yazzle has. Use XP & YP instead of X & Y, and a number between 0-99.
X and Y are the numbers that define horizontal and vertical placement of the textfield respectivily, in pixels. These apply to buttons and other things too. Due to Yazzle being resizable, these values get set in relation to one of the corners. ‘C’ tells Yazzle from which corner to start calculating, Topleft (1), Topright (2), Bottomleft (3) or Bottomright (4). No need for negative values, Yazzle reads them upwards and leftwards when corner is ‘4’, for instance.
W(idth) and H(eight are then used to reserve proper space for the textfield. The last six lines you can use to further align the text within this space. Note you only have to add the lines you set to ‘1’. These all can be set to false (0, which is default) or true (1) only.
[WallClock] has two extra properties available:
[WallClock] Format=%#H:%M Lowercase=0|1 (False/true)
Here's the list of valid options to add to first property (with nothing defined, it defaults to %#I:%M:%S %p):
%a | 3 letter weekday of the week name |
%A | full weekday of the week name |
%b | 3 letter month of the year name |
%B | full month of the year name |
%c | day and time formatted for locale |
%d | day of the month number |
%H | hour of the day number (24 hour format) |
%I | hour of the day number (12 hour format) |
%j | day of the year number |
%m | month of the year number |
%M | minute of the hour number |
%p | A.M./P.M. indicator for 12 hour clock |
%S | seconds of the minute number |
%U | week of the year number (Sun as first weekday) |
%w | weekday of the week number |
%W | week of the year number (Mon as first weekday) |
%x | date as formatted for the locale |
%X | time as formatted for the locale |
%y | 2 digit year of the century number |
%Y | 4 digit year of the century number |
%z | time zone name or abbreviation |
%Z | time zone name or abbreviation |
%% | percent sign |
# | when used with a numeric format, removes any leading zeros, e.g., %#I:%M will display 17:00 hours as "5:00 PM" |
# | when used with the %x format, converts the date to the locale's long representation, e.g, %#x will convert "03/14/95" to "Tuesday, March 14, 1995" |
# | when used with the %c format, converts the date and time to the locale's long format, e.g, %#c will convert "03/14/95 12:41:29" to "Tuesday, March 14, 1995, 12:41:29" |
Format (rightclick)menu's & tooltips
More font and color settings apply to the rightclickmenu (optional displayed by adding a button that pops them up).
[MenuFont] Name=trebuchet ms File=trebuc.ttf Size=10 Bold=0 Italic=0 Red=0 Green=0 Blue=0 Shadow=2 ShadowRed=121 ShadowGreen=148 ShadowBlue=173 HighlightRed=255 HighlightGreen=255 HighlightBlue=255
Same rules apply as with [DefaultFont], MouseOverRGB properties do not apply here though. The HighlightRGB properties define textcolor of the item in menu that's hovered.
Another part of menu colors is defined in a different section of the .ini, though:
[MainMenu] HiliteRed=151 HiliteGreen=175 HiliteBlue=197 NormalRed=151 NormalGreen=175 NormalBlue=197 DisabledRed=79 DisabledGreen=115 DisabledBlue=148
Why here ? Well, [MainMenu] used to be a button section only (button that pops up this menu); this is only part of the properties that can be set for this section.
The HiliteRGB properties define color of background of a hovered item, while the NormalRGB properties define backgroundcolor of menu and items not hovered. The DisabledRGB properties finally, are for textcolor of any menu item not currently available.
Additionally, you can define background- and fontcolor of the provided tooltips by adding them to [background] section:
[Background] TipTextRed=0 TipTextGreen=0 TipTextBlue=0 TipBkgndRed=255 TipBkgndGreen=255 TipBkgndBlue=255
Adding pilemat images
Now, when playing, it's conveniënt having some indication where cards are supposed to go, and if applicable, which rank restrictions there are for a pile. Yazzle provides the option to display two versions (more are planned), a regular one and one for piles that have restrictions - typically displaying the rank of the card that should be added there first. Both have to be seperate images and behave much like the background.bmp. In main.ini, both require a seperate section (one or both will not be displayed if not set, though you can point both to same .bmp):
[PileMatPlain]|[PileMatSuits] Image=pilematplain.bmp HasTransparency=1 CenterTiled=1 TopLeftWidth=3 TopRightWidth=3 TopHeight=3 BottomLeftWidth=3 BottomRightWidth=3 BottomHeight=3 LeftTopHeight=3 LeftBottomHeight=3 LeftWidth=3 RightTopHeight=3 RightBottomHeight=3 RightWidth=3
For the options to tile or center the pilemat (they get resized depending on cardset), refer back to main window section, behavior is the same. For transparency, there's more options in this case: transparency section.
Inevitably, you'll also want to create an image to display the ranks on the pilemat, when there's restrictions. Another section in main.ini needed:
[PileMatRanks] Image=ranks.bmp ;Alpha=ranks_alpha.bmp HasTransparency=1 TransparencyRed=0 TransparencyGreen=0 TransparencyBlue=0
The image has to contain 13 equal sized blocks, each containing a rank, in this order: A 2 3 4 5 6 7 8 9 10 J Q K. For transparency, again refer to transparency section.

Adding buttons
Every Yazzle option is available in its rightclick menu. You can make any or all of them available as a button on your skin. Most simple is display them at your background image. Check out the included ‘XP’ skin. The buttons are drawn on background.bmp, in main.ini it states:
[Close] X=21 Y=6 W=16 H=16 C=2
This is what we saw with the textfields. The close button is 21 px from right side (C=2, topright corner), and 6 px from top. It's also 16x16 px and clicking that area should close Yazzle. Simple.
Yet, you can have buttons with effects when hovered, and being pushed. For this, you need to create an appropiate image. The image contains either 1, 2, 3 (regular buttons) or 6 (buttons that toggle an option) versions of the same button, in a horizontal ‘filmstrip’.

In main.ini, you need to add a new section for every button you want shown:
[ButtonName] X=# Y=# C=# Image=button_for_this_action.bmp Images=#
Buttonname is the section header, and has to be a known command. Here's the list (all but ‘PlayMenu’ are demonstrated in plastique skin):
A gripper
There's an additional ‘button’, [Gripper]. This one will produce an area that will, when hovered, show a resize cursor and enable you to resize Yazzle.
[MainMenu] | [PlayMenu] | [GameHelp] | [Minimize] |
[Maximize]* | [Close] |
[NewGame] | [PauzeGame] |
[ReplayGame] | [PlayPrevGame] |
[PlayGame#] | [PlayNextGame] |
[UndoMove] | [FoundationMove] |
[HighlightNext] | [LockPosition]* |
[ToggleMusic]* | [ToggleSound]* |
X and Y are the numbers that define horizontal and vertical placement of the button respectivily, in pixels. Due to Yazzle being resizable, these values get set in relation to one of the corners. ‘C’ tells Yazzle from which corner to start calculating, Topleft (1), Topright (2), Bottomleft (3) or Bottomright (4). No need for negative values, Yazzle reads them upwards and leftwards when corner is ‘4’, for instance.
Finally, ‘Images=#’ tells Yazzle how many variations of the button you put in (# being either 1, 2, 3 or 6), so it can calculate width and height of the button, and what to display when hovered etc. You could stick with one image for all buttons, stick to 3 versions for the toggle buttons, but you can only add so much versions the command can handle.
Regular buttons can have 1, 2 or 3 frames, order being normal - hovered - down. Toggle buttons (marked* above) can have either 3, unchecked - ? - checked, or 6, unchecked - unchecked hovered - unchecked down - checked - checked hovered - checked down.
Transparency & alphablending
We saw main background could have transparent parts. There's 3 ways to add transparency to the pilemats, pilemat ranks, buttons, splash screens and dialogs (shadow effect) too. First, most simple is to use magenta for a plain non-visibility again. You only need to add this line at appropiate section:
[SectionName] HasTransparency=1
Second still creates a plain non-visibility. Now you can use any color in the image, for example black(RGB 0 0 0). Few more lines to add:
[SectionName] HasTransparency=1 TransparencyRed=0 TransparencyGreen=0 TransparencyBlue=0

Third is more sophisticated, and uses two images. First is full-color, and has all parts that need being displayed. The second image is greyscale and is laid over first as a mask. If a pixel in mask is black, matching pixel in first image is fully not shown. If it's white, it's shown 100%. Anything in between, from white to black, is increasingly blended with background.
[SectionName] Image=button.bmp Alpha=button_alpha.bmp
You can use this to blend in buttons on non-solid backgrounds, smoothen font display on pilemats, add effects to your splash screens and shadow to menu's.

Splash- & pauze screen
By default, Yazzle gets 'dimmed' (a native Windows effect) when pauzed or not having focus. Optionally, you can have a custom pauze screen displayed, and also a loading screen at startup of Yazzle. The dimming effect still gets displayed underneath the screen, but can also be turned off:
[Background] DimPlayingArea=0
The screens require new images. Rules for these are quite alike those for other images, with notable exception that they're displayed in Playingarea, and centered by default. Only new value is 'stretch=0|1'. Default is no (0). Have a quick look over example, you just need to add new sections in main.ini, can have transparency and even build them like background and pilemats are drawn:
[PauseDialog] Image=pauze.bmp Alpha=pauze_alpha.bmp Stretch=0 [SplashDialog] Image=splash.bmp Stretch=1 TopLeftWidth=618 TopRightWidth=0 TopHeight=355 BottomLeftWidth=0 BottomRightWidth=578 BottomHeight=54
Dialogs
Ideally, in the end, Yazzle will have the option to have all dialogs (options, card deck choice, skin selection etc) skinned - they are displayed centered over whole of main window (fixed). For now, only main messagebox is (the one telling you've won, how results where and what to do next). Preparing for future though, this one is done with a new .ini file, messagebox.ini. Format is alike main.ini, and nothing inside that will scare you if you've come this far. You'll need one bitmap (exactly as gonna be displayed) of the dialog and - optionally - one to handle alphablending:
Tooltips
If you applied custom tooltip colors for main window, copy and apply them here too - [Background] section. Usability wise, mostly a good choice to use same colors, yet dialog could have much contrast with main window in your skin.
[General] Name=plastique Author=plastic Description=messagebox [Background] Image=dialog.bmp Alpha=dialog_alpha.bmp
After this there's 3 things to have displayed on the dialog, message itself and a 'yes' and 'no' button; they're called [Button1] and [Button2] here, respectivily. Not much to explain, they follow same rules as textfields and buttons in main window:
[MessageText] X=15 Y=15 W=394 H=60 HorzCentered=1 TopAligned=1 [Button1] X=180 Y=83 Image=yes.bmp Images=3 [Button2] X=218 Y=83 Image=no.bmp Images=3
A note about the .bmp for the alphablending effect. You could blend the dialog in or something, but most skinners will use this opportunity to add a shadow beneath their dialog. Do this by reserving space for the shadow in the dialog bitmap, and use a color to have the blending tinted in skins' colors. Then create the alpha bitmap, with real dialog part pure white, background black, then create the shadow effect alike here:

Adding additional bitmaps
Occasionally, you might find a need to display additional bitmaps on the skin. You could, ofcourse, add them to your background bitmap, but if you need to place it more flexible (using percentual values, to have it next to text/buttons aligned likewise, or even fixed, but not wanting your background image to be huge), here's how. First, you need an extra line in [Background] section, defining number of images you want displayed. After that, create new sections [Pic1], [Pic2] etc. They somewhat follow same rules as any button. They do not allow multiple states, but they do listen to transparency values. The 'plastique' skin uses two of these, one to be shown before gamenumber, one acting as seperator between move/score counters (explore).
Put into perspective
Not all extra imaging is better off as a seperately added bitmap. You'll notice the seperators between sections in both title- as bottombar in 'plastique' skin. Could have been seperate images, but adding them to button images gave much more pixel precize results, and does the job too. Just something to consider.
[Background] PicCount=2 [Pic1] XP=46 Y=27 C=3 Image=nr.bmp [Pic2] XP=75 Y=27 C=3 Image=score.bmp
Conclusion (perspective)
What's been described, is a mature, tested skinning format. Intentions are it will grow. Don't expect your skins to be broken, do expect extra options (no deadline involved whatsoever). As indicated, more pilemat differencing and more dialogs to be skinned are planned. Maybe more. But go ahead and have a go, you're safe.