Developing a \"Skin-Enabled\" Application
User interface design can be extremely difficult, and even if you come up with a design that is very popular, you can count on someone complaining about it. This article shows you how to create a user interface based on user-definable skins, so your users can choose for themselves what they like.
Applies to:
Microsoft Windows Powered Pocket PC 2000
A live network connection from your Pocket PC
Microsoft eMbedded Visual C++ version 3.0
VOImage class
Languages Supported
English
Creating the Skin Files
A "skin" is a collection of graphics files plus a text file, read by your application, which describes where various graphics should be placed on the user interface (UI). With the advent of landscape mode on the Pocket PC, there are currently two resolutions you should absolutely support: 240 x 320, also known as "portrait" or "standard" resolution, and 320 x 240, also known as "landscape" resolution. In this article, we use a simple calculator as our application model. The graphics described in the following steps are available for download at the Virtual Office Systems Web site.
Sample control list.
To create a skin for the calculator sample application:
List the types of objects your application will present to the user - including buttons, tabs, lists of items, and so on. For best results, I recommend sketching the interface and labeling the components, as shown in Figure 1.
Use Paint or another paint program (I use JASC Paintshop Pro) to create two graphics files. Make one 240 x 320 pixels and the other 320 x 240 pixels. Save them as PNG, GIF, or BMP files (depending on your paint program capabilities). These will serve as your background images.
Create a graphic that is 200 x 32 pixels. Make it a light-green rectangle to keep it simple. If you want to support landscape, make another similar display area that is 280 x 32 pixels.
Create graphics for the other items in the list. For this example, make all the buttons 32 x 32 pixels, except for the PLUS SIGN, which should be 32 x 78 pixels.
Create a text file named "Sample.Calculator.skin" that contains the following (if your filenames are different, make the appropriate changes):
[Head] SkinName=Sample Calculator Skin Author=Adam J. Tratt Description=Sample skin for calculator application [Graphics] Background=SampleCalc.gif Background.320x240=SampleCalcLS.gif Display=Display.gif Display.320x240=DisplayLS.gif Button0=0.gif Button1=1.gif Button2=2.gif Button3=3.gif Button4=4.gif Button5=5.gif Button6=6.gif Button7=7.gif Button8=8.gif Button9=9.gif ButtonPlus=Plus.gif ButtonMinus=Minus.gif ButtonTimes=Times.gif ButtonDivide=Divide.gif ButtonDecimal=Decimal.gif ButtinEqual=Equals.gif ButtonClear=Clear.gif // Areas are bounding rectangles x1,y1,x2,y2 [Areas] CalculatorDisplay=38,14,238,46 CalculatorDisplay.320x240=38,14,318,46 Button0=60,198,92,230 Button1=60,152,92,184 Button2=106,152,138,184 Button3=152,152,184,184 Button4=60,106,92,138 Button5=106,106,138,138 . Button6=152,106,184,138 Button7=60,60,92,92 Button8=106,60,138,92 Button9=152,60,184,92 ButtonPlus=152,198,230,230 ButtonMinus=198,106,230,138 ButtonTimes=14,106,46,138 ButtonDivide=14,152,46,184 ButtonDecimal=106,198,138,230 ButtonEqual=152,198,184,230 ButtonClear=2,14,34,46 [Fonts] CalculatorDisplay=Tahoma,10 [Colors] CalculatorDisplay=0,0,0
Note that in the "Areas" section, the buttons are at the same location in any resolution. In some of the values, you will notice that there are different coordinates for 240 x 320 than for 320 x 240. Our application must first look for a setting that is specific to the current resolution; if that value isn't found, the resolution is not specified. Using this method ensures that no matter what resolution your users are running, they will always get some sort of a display, but the skin creators can optimize the skins for specific resolutions.
Reading the Skin Files and Displaying the User Interface
You should provide at least one skin with any application; make sure that you give your users a menu selection or another method of selecting which skin they want to use! While it is beyond the scope of this article to walk you through every step involved in creating a complete UI, here are the main steps involved in reading the skin and displaying it to the user:
- Open the currently selected .SKIN file (see File I/O in a C++ Application on the Pocket PC for more information on reading files).
- In the processing of the WM_PAINT message, check to see if the graphics for the current skin have been loaded. If they haven't, load them now.
- Also in the WM_PAINT message, display any graphics at the coordinates listed in the "Areas" section of the file. For text areas, as with our "CalculatorDisplay" area, display the contents in the specified font and size within the coordinates listed in the "Areas" section.
- Process skin selection changes and ensure that if the user changes the skin, any loaded graphics, fonts, and other elements from previous skins are deleted from memory so that the new skin will be displayed correctly.
Processing Input Events (User Clicks) on the Skin
The ease of reacting to user clicks is probably the easiest and most impressive part of using skins. To process user clicks in a skin-based application:
- In the processing of the WM_LBUTTONUP message, check the area coordinates from the .SKIN file and translate the click into a function call for the button pressed. Sometimes (as is the case in the calculator example with the number buttons) it makes sense to call the same function with a different parameter, so in our example we might have a function called OnNumberPress(int nNumber).
- For list boxes, you will generally either restrict the list to a particular region of the screen and use a standard list box or, more commonly, use a paging method (display as many items as will fit in the specified region and offer a next and previous page graphic).
- Depending on the application, you may want to support tap-and-hold functions for certain controls as well. In the calculator, for example, you might want to support cut-and-paste operations on the calculator display area. You can tell which control is being affected the same way you do with the WM_LBUTTONUP processing.
Conclusion
By allowing your users to choose an interface that is completely external to your application, you not only give them the ability to choose their own look and feel, you give your application a fresh new lookâwithout writing a single additional line of code. Pocket PC users in particular are accustomed to colorful, expressive interfaces and above all, they are used to having choices ranging from the way they input text to their Today screen display. The day may soon come when single-interface applications are left behind...