Click here to Skip to main content
Click here to Skip to main content

Using Themer To Skin Forms and Controls

, 16 Aug 2007
Rate this:
Please Sign up or sign in to vote.
Using Themer To Skin Forms and Controls
Screenshot - themed.jpg

Introduction

This is my first article, so please bear with me on this...

Themer is a component control that allows you to easily apply a group of settings to controls and, optionally, handle those controls' events.

Themer comes from the idea of CSS for web pages. The basic idea is Themer can apply it's settings to a Group, a specific control, or all controls of a certain type. Themer uses an XML file to keep its list of theme information. You can easily change the theme file to another file (for example, if you want to allow the user to change the theme or skin of your application).

How Themer Works

Themer includes a special class, clsThemeWriter, which you can use to easily create your theme files.

Using the clsThemeWriter, you save a list of properties and/or events that you want to have themed. You can set these properties to be applied to a group, control name, or control type.

During application execution, Themer will loop through each Control on your form. Themer will apply the settings in the Theme file, first using Control Type (example System.Windows.Forms.Button), then GroupName, and finally Control ID. If nothing is found, Themer continues to the next Control on the form.

Once a match has been found for the Control in the Theme file, Themer will apply all property settings in the Theme file to the current Control. Examples of settings could be Text, BackColor, ForeColor, and Size. Next, Themer will check if any events have been registered in the Theme file. If so, Themer will hook those events.

If you want a control on your form to not be themed, you can use the extended properties provided by the component control ThemerBase to specify that a control should not implement theming.

If Themer finds a property or event in the theme file, but the current Control does not have this property/event, Themer will skip that property/event.

NOTE: This control relies on Case Sensitivity. Therefore, property names, event names, etc. must be properly capitalized when creating the theme file.

clsThemeWriter

The clsThemeWriter class handles all the work of creating a theme file. When you create the class, you can pass in the location where the Theme should be saved. You can also pass in the location of an existing Theme file, in which case the file will simple be updated.

clsThemerWriter tw = new clsThemerWriter(@"c:\temp2\theme2.theme");

Groups, Controls, and Control Types

Theme information can be applied to a group, a specific control, and/or all controls of a specific type. The order of applying properties is Control Type, GroupName, Control Name. Once a match has been found, Themer will apply the settings from the. If you create a ControlName setting and a GroupName setting that could both apply to ObjectX, both settings will be applied to ObjectX.

ThemerType

This Enum specifies which setting type should be applied to this instance of the clsThemeWriter.

  • UseGroup – this flag specifies that clsThemeWriter is creating a GroupName setting. All settings in this instance will apply to all controls which have their GroupName property set to the same value in clsThemeWriter.GroupName
    • Set the GroupName property if you set the UseGroup flag
  • UseControlName – this flag specifies that clsThemeWriter is creating a ControlName setting. All settings in this instance will apply to any control whose Name property is the same as clsThemeWriter.ControlName
    • Set the ControlName property if you set the UseControlName flag
  • UseControlType – this flag specifies that clsThemeWriter is creating a Control Type setting. All controls which match this Type will have their properties updated
    • Set the ControlType property if you set the UseControlType flag
    • NOTE: You must use the full name of the control (including namespace), such as System.Windows.Forms.Button

PropertyList

The list of properties for the Control(s) which should be updated. This list is of type Themer.ThemeWriter.TWHelperItem. For each item in this list, set the following TWHelperItem properties:

  • ItemName – the name of the Control's property to update (such as Text or ForeColor). CASE SENSITIVE
  • ItemValue – the object value to assign to the Control's property (such as "123" or Color.Black). Must be serializable

EventList

The list of events which should be hooked on the Control(s). This list is of type Themer.ThemeWriter.TWHelperItem. For each item in this list, set the following TWHelperItem properties:

  • ItemName – the name of the Control's Event (such as Click or DoubleClick)
  • TargetMethodName – the name of the Method that will receive event notification (this is a method you will create. This is explained in more detail in the next section).

Saving the Theme File

Once you have created a theme item (group, control name, or control type), you need to call UpdateThemeFile, passing in the TWHelper object. You will call UpdateThemeFile for each theme item you want to add.

Applying a Theme to Your Form - ThemerBase

Once you have created one or more theme files, it is time to apply the theme to your form. Drop the ThemerBase component control on your form.

New Properties Added to Form Controls

You will notice all the Controls on your form will have two new properties:

  • ApplyTheme – when true, theme will be applied to this control if one is found in the theme file
    • When false, this Control will be skipped during theming
  • ThemerGroupName – the name of the group. All Controls in a group will have the same settings applied.
    • Set to an empty string or GlobalGroup if you don't want the control to be in a Group.

ThemerBase Properties

ThemerBase has two properties you need to set:

  • ThemePath – this is the path of the theme file.
  • ThrowErrors – When set to true, errors are allowed to propogate from Themer. The few instances of errors being thrown would be, for example, an error with the theme xml file.
    • Setting this property to false will suppress most errors in Themer.
    • Default is true

ThemerBase Events

When you created the theme file, you had the option to add events to hook on the object. To hook into the events, you need to create a special class that will receive the events you want to hook. On the form holding the ThemerBase control, set the EventObject to the new class you created.

The new class you create will contain methods as defined in the themer file. These methods must match the delegate definition for which they are being hooked, or an error will be raised.

For example, if you want to hook the Click event of a button, in the themer file, add Click to the event list (TargetMethod = "Click_Hooked", for example). In your new class, create a method:

public void Click_Hooked (object sender, EventArgs e)

Now, when the button is clicked, Click_Hooked will be called as well.

Changing Themes

You can dynamically change the theme of your form by changing the ThemePath. Once you have changed ThemePath, you will need to call ThemerBase.ApplyTheme() to implement the new theme. This allows you to give users the option to change themes and have those changes applied immediately!

Using the code

Here is a sample project to demonstrate how you can easily change control properties with Themer. The sample let's users choose between two templates (Template1 and Template2). The templates are first created, then loaded with ApplyTheme(). Each control is given a group name (Group1 or Group2). The button and label belong to Group1, while the textbox and groupbox belong to Group2.

This example demonstrates how to write settings to the themer file and how to apply those settings to a form.

        
            /// <span class="code-SummaryComment"><summary>
</span>
            /// Build and apply the first theme
            /// <span class="code-SummaryComment"></summary>
</span>
            private void button1_Click(object sender, EventArgs e)
            {
                string filename = @"c:\temp2\theme1.theme";
                clsThemerWriter tw = new clsThemerWriter(filename);

                // Group 1
                TWHelper twh = new TWHelper("Group1", "", "", ThemerType.UseGroup);
                twh.PropertyList.Add(new TWHelperItem("Text", "Theme1 - Group1"));
                twh.PropertyList.Add(new TWHelperItem("BackColor", Color.LightBlue));

                // writing group 1
                tw.UpdateThemeFile(twh);

                // Group 2
                twh = new TWHelper("Group2", "", "", ThemerType.UseGroup);
                twh.PropertyList.Add(new TWHelperItem("Text", "Theme1 - Group2"));
                twh.PropertyList.Add(new TWHelperItem("ForeColor", Color.Purple));

                // writing group 2
                tw.UpdateThemeFile(twh);

                this.themerBase1.ThemePath = filename;
                this.themerBase1.ApplyTheme();
            }

            /// <span class="code-SummaryComment"><summary>
</span>
            /// Build and apply the second theme
            /// <span class="code-SummaryComment"></summary>
</span>
            private void cmdTheme2_Click(object sender, EventArgs e)
            {
                string filename = @"c:\temp2\theme2.theme.theme";
                clsThemerWriter tw = new clsThemerWriter(filename);

                // Group 1
                TWHelper twh = new TWHelper("Group1", "", "", ThemerType.UseGroup);
                twh.PropertyList.Add(new TWHelperItem("Text", "Theme2 - Group1"));
                twh.PropertyList.Add(new TWHelperItem("BackColor", Color.LemonChiffon));

                // writing group 1
                tw.UpdateThemeFile(twh);

                // Group 2
                twh = new TWHelper("Group2", "", "", ThemerType.UseGroup);
                twh.PropertyList.Add(new TWHelperItem("Text", "Theme2 - Group2"));
                twh.PropertyList.Add(new TWHelperItem("ForeColor", Color.Red));

                // writing group 2
                tw.UpdateThemeFile(twh);

                this.themerBase1.ThemePath = filename;
                this.themerBase1.ApplyTheme();
            }
    

Points of Interest

Themer is a very versatile control. You can easily create a variety of skins for your project and quickly change them dynamicaly as the user desires.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here

Share

About the Author

merlin981
Software Developer (Senior)
United States United States
Winner - Best Mobile App - AT&T Developer Summit, Las Vegas, 2013
 
My personal resume can be found at: http://www.philippiercedeveloper.com
 
My game portfolio can be found at: http://www.rocketgamesmobile.com
 
About Philip Pierce:
 
I am a software developer with twenty years experience in game development, mobile, web, desktop, server, and database. My extensive background highlights an expertise in rapid application development using the latest Microsoft, Mobile, and Game Development technologies, along with the ability to create AI for games and business software, redesign existing software, develop multi-threaded software, and create client/server applications.

Comments and Discussions

 
GeneralMy vote of 1 PinmemberIndustrialMan13-Jan-10 9:06 
GeneralMy vote of 1 PinmemberAshutosh Bhawasinka23-Jul-09 21:57 
GeneralWell done for writing this up PinmemberDaniel Vaughan31-Dec-07 5:51 
GeneralProblem with sample PinmemberAmar Chaudhary27-Sep-07 5:48 
GeneralRe: Problem with sample Pinmembermerlin98127-Sep-07 7:18 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Terms of Use | Mobile
Web01 | 2.8.1411023.1 | Last Updated 16 Aug 2007
Article Copyright 2007 by merlin981
Everything else Copyright © CodeProject, 1999-2014
Layout: fixed | fluid