Control Panel Applets


A control Panel application is a DLL that is named with a .cpl file extension and that exports the function CPlApplet to handle CPL_INIT, CPL_GETCOUNT, CPL_NEWINQURE, CPL_STOP, and CPL_EXIT messages (the definitions are in %_WINCEROOT%\PUBLIC\COMMON\OAK\INC\cpl.h)

The main control panel application is control.exe (%_WINCEROOT%\PUBLIC\WCESHELLFE\OAK\CTLPNL\CONTROL): it creates the control panel window, enumerates the .cpl files in the \\Windows directory and populates the list view with the applets included in the .cpl files.

When you double click on an icon, control.exe calls ShellExecuteEx to spawn an instance of ctlpnl.exe (%_WINCEROOT%\PUBLIC\WCESHELLFE\OAK\CTLPNL\CTLPNL)
passing on the command line the .cpl file name and the applet index (a .cpl file can contain more than an applet).

The online docs (http://msdn.microsoft.com/en-us/library/ee502286.aspx) describe how to create a control panel application in a very straighforward way but it’s worth taking a look to how MS programmers did their work. The main control panel application is cplmain.cpl (%_WINCEROOT%\PUBLIC\WCESHELLFE\OAK\CTLPNL\CPLMAIN)
which includes great part of the standard control panel applets (communication, keyboard, system etc). It’s built to be easily extended adding new applets and can easily adapted (cloning it) to create your ‘own’ main control panel.

The main file –cplmain.cpp– handles all the .cpl specific stuff like implementing the CPlApplet function, messages processing, running the applets etc.
This code can handle n applets that are expected to be a Property Sheet with a certain number of tabs, from one to  5 (this value is a #define so can be changed).

Every applet is described by the following structure (%_WINCEROOT%\PUBLIC\WCESHELLFE\OAK\CTLPNL\CPLMAIN\cplglobl.h):

typedef struct CPLAPPLETINFO
{
    LPCTSTR pszMutex;     
    LPCTSTR pszLaunchCplCallback;  
    BOOL fPwdProtect;   
    int  rcidIcon;    
    int  idsName;    
    int  idsDesc;    
    int  idsTitle;    
    int     cctrlFlags;    
    const CPLTABINFO* rgptab[MAX_TABS];
}
CPLAPPLETINFO, *PCPLAPPLETINFO;
  •  
    • pszMutex: the name of a mutex used to avoid more than one instance of the same applet
    • pszLaunchCplCallback: if this is not NULL cplmain will call this function which returns a BOOL value indicating if the applet has to be run or not. It’s useful to perform runtime operations like adding or removing a tab or change the layout according to the screen orientation
    • fPwdProtect: if this flag is set the user will be requested to authenticate before cplmain displays the applet
    • rcidIcon: the resource ID for the icon which is displayed for the applet in the control panel list view
    • idsName: the resource ID for the string displayed with the applet icon in the list view
    • idsDesc: the resource ID for the string describing the applet (you can see it when you choose the ‘details’ view)
    • idsTitle: the resource ID for the string displayed as the title of the applet
    • cctrlFlags: if the applet uses some specific common controls you can specify them there using the same flags of INITCOMMONCONTROLSEX structure: cplmain will call InitCommonControlsEx on behalf of the applet
    • rgptab: an array of structures describing each tab of the applet (see below)

Every tab is defined by the following structure:

typedef struct
{
    int  idsTitle;
    int  iddDlg;
    LPCTSTR pszDlg;
    const int* rgBoldStatics;
    int  iNumStatics;
    BOOL fSip;
    LPCTSTR pszHelp;
}
CPLTABINFO, *PCPLTABINFO;
  •  
    • idsTitle: the resource ID for the string displayed as the title of the tab
    • iddDlg: the resource ID for the dialog template used for the tab
    • pszDlg: a string with the name of the dialog procedure for the tab. It’s a string rather than a DLGPROC so, at runtime, the control panel can detect if a tab is present or not (useful for componentization as it’s done in the actual cplmain)
    • rgBoldStatics: an array of resource ID’s of controls that you want to apper with a bold font
    • iNumStatics: the length of the above array
    • fSip: this flag indicates if the tab wants the SIP to appear or not
    • pszHelp: a string which ‘points’ to the help documentation (for example L”file:applet.htm#thistab_help”)

The cplmain.cpp file expects an array of CPLAPPLETINFO named rgApplets and providentially the array is not defined in cplmain.cpp but in an included file (cpltable.cpp).

Then: if you want a powerful framework for your control applets you can create a DLL (remember the CPL=1 directive in the sources file to set the correct extension) which includes cplmain.cpp and another bunch of files from %_WINCEROOT%\PUBLIC\WCESHELLFE\OAK\CTLPNL\CPLMAIN (like cplglobl.h for example).
Once you fill your own cpltable.cpp file with the relevant structures and create the resources files ‘all’ you need is to implement the applet logic as you would do for a dialog box. 

As a footnote: remember that your .cpl file must export:

  •  
    • CPlApplet
    • The dialog procedure for each tab of the applets
    • the pszLaunchCplCallback function for the applets that use it

Obviously looking at the actual implementation of cplmain to retrieve further details (the registry entries used here and there, for example) is extremely useful if not necessary!

Advertisements
This entry was posted in Windows Embedded CE, Windows Embedded Compact and tagged , , , . Bookmark the permalink.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s