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

Control Panel Applet Framework

By , 24 Feb 2000
 
  • Download source files - 10 Kb
  • The problem

    The Windows Control Panel is the ideal way to allow a user to alter settings for an application that runs in the background, or automatically. When I was exploring NT Services it seemed like a good idea to control my service using a control panel applet. But what are control panel applets and how do you write one? Well, after some exploring in the MSDN I discovered that control panel applets are just standard DLLs with a particular set of entry points and a .cpl extension. Place such a file in the Windows System directory and the next time you start up control panel your applet will be there. Having discovered what I needed to know I set about writing a control panel applet and once I'd done that, I turned the bulk of the code into a mini applet framework so I wouldn't have to write it ever again!

    Anatomy of a control panel applet

    Control panel applets are pretty old now, and no doubt some day soon they will be replace by fully fledged COM objects. In the mean time they're a reasonable first attempt at component based programming. A control panel applet is a DLL that presents a standard interface to the Control Panel application. When Control Panel starts it locates all the .cpl files in the Windows System directory and tries to load them as DLLs. If this works then it tries to locate a function called CPlApplet() in the newly loaded DLL. If the DLL has the function entry point then it's a control panel applet! But there's more, a single DLL can contain multiple applets and they each appear as a separate icon in Control Panel.

    CPlApplet() is a relatively simple function taking a window handle, a message and a couple of message specific parameters. Writing one is similar to writing a normal window proc and is reasonably well documented in MSDN and the VC++ online help. The framework that I produced provides an implementation of CPlApplet(), along with a DllMain() and wires these DLL entry points up to a class designed to be a base class for your applets. Simply derive from CJBControlPanelApplet, build a DLL with a .cpl extension and with the link with framework and you're done!

    What does CJBControlPanelApplet give you?

    To be a control panel applet your CPlApplet() entry point has to respond appropriately to messages from the Control Panel application. Most of these messages are mundane, housekeeping. CJBControlPanelApplet handles all of this for you and provides virtual functions that you can override if you want a little more control. If you wish, you only need handle one message, by providing an OnDoubleClick() handler for when your applet is activated and should do its stuff. Each of the standard CPL_ messages has a corresponding virtual message handler (except CPL_GETCOUNT which is handled entirely by the framework).

    Your derived class

    To implement your control panel applet you need to do the following:

    • include "ControlApplet.hpp" and publicly derive a class from CJBControlPanelApplet.
    • call the CJBControlPanelApplet constructor and pass resource IDs for the applet's icon, name and description.
    • implement the pure virtual function OnDoubleClick() - this is where your applet becomes live and can display a dialog or whatever.
    • create an instance of your applet class at global scope.
    • link with ControlApplet.cpp and include ControlApplet.def in your project. ControlApplet.cpp gives you the implementation of CJBControlPanelApplet and suitable DllMain() and CPlApplet() DLL entry point functions.

    If you wish you can also:

    • handle OnInit() - for resource acquisition, or start up code.
    • handle OnStop() - for resource release and shutdown code.
    • handle OnExit() - for last minute shut down code that wasn't put into OnStop() for some reason...
    • handle OnInquire() - if you really want to take over the filling in of the  LPCPLINFO structure... Or perhaps you want to use the standard OnNewInquire() functionality so you might want to return FALSE from here!
    • handle OnNewInquire() - if my handling of it doesn't suit you. For dynamic icons or descriptions perhaps?
    • handle OnStartWithParams() - if you want to do clever things when started with command line parameters by rundll.

    Note the handling of the poorly documented CPL_STARTWPARAMS has not been tested since I don't have access to Windows 95 and rundll doesn't seem to exist on NT4.

    Multiple applets in one DLL

    CJBControlPanelApplet implements a linked list of all active object instances. Every time the constructor is called it links the current object into the static list of all CJBControlPanelApplet objects. Whenever the DLL entry point processes a message it walks the static list of applets and passes the message to each in turn. All you need to do is declare an object of a type derived from CJBControlPanelApplet at global scope and as soon as the applet is loaded you object will be created and automatically wired up to the list and begin receiving messages.

    If you want to develop multiple applets as separate DLLs that's fine, if you change your mind and want to have them all in the same DLL then just link all the files together in one project and the framework does the rest for you. No code changes!

    See the article on Len's homepage for the latest updates.

    License

    This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

    About the Author

    Len Holgate
    Software Developer (Senior) JetByte Limited
    United Kingdom United Kingdom
    Member
    Len has been programming for over 30 years, having first started with a Sinclair ZX-80. Now he runs his own consulting company, JetByte Limited and has a technical blog here.
     
    JetByte provides contract programming and consultancy services. We can provide experience in COM, Corba, C++, Windows NT and UNIX. Our speciality is the design and implementation of systems but we are happy to work with you throughout the entire project life-cycle. We are happy to quote for fixed price work, or, if required, can work for an hourly rate.
     
    We are based in London, England, but, thanks to the Internet, we can work 'virtually' anywhere...
     
    Please note that many of the articles here may have updated code available on Len's blog and that the IOCP socket server framework is also available in a licensed, much improved and fully supported version, see here for details.

    Sign Up to vote   Poor Excellent
    Add a reason or comment to your vote: x
    Votes of 3 or less require a comment

    Comments and Discussions

     
    You must Sign In to use this message board.
    Search this forum  
        Spacing  Noise  Layout  Per page   
    GeneralThis is a complete working project that worked for me right away without any hassles.memberparandor23 Oct '10 - 10:24 
    Great work. Thanks for post.
     
    The debugging tip above helped me out and solved a problem I've had for a couple of days.
     
    Now on to moving this over to win mobile...
    Generaladding an item into control panel context menumemberemmmatty110 Jul '09 - 0:50 
    is there any way to add items to the context menu we see while right clicking on a control panel item?
    GeneralRe: adding an item into control panel context menumemberLen Holgate10 Jul '09 - 0:58 
    Not that I know of.
     
    Len Holgate
    www.jetbyte.com
    The right code, right now.

    GeneralSolves my problem! And here's how to debug an applet.membereldibi16 Jan '09 - 11:45 
    Thank you. This is exactly what I needed: Short, to the point, works out of the box. I am busily plugging away at my new control panel!
     
    A note on debugging the applet: In order to run the applet with the VS2005 debugger, I used these settings:
     
    Command:           rundll32.exe
    Command Arguments: shell32.dll,Control_RunDLL "ProjectPath\Debug\ControlApplet.cpl"
    where ProjectPath is the fully qualified path to the ControlApplet project folder. This way, the latest binary of the applet is loaded and my breakpoints are trapped correctly.
     
    modified on Monday, January 19, 2009 6:00 AM

    GeneralRe: Solves my problem! And here's how to debug an applet.memberLen Holgate10 Jul '09 - 0:58 
    Glad it worked for you, thanks for the debug tip!
     
    Len Holgate
    www.jetbyte.com
    The right code, right now.

    GeneralC#.NET versionmemberBas Steijvers9 May '06 - 22:19 
    Hi,
     
    Do you perhaps already created a C# version of this Control Panel Applet Framework. I want to create a control panel applet using C#, but I can not
    find any information or examples how to do so.
     

     
    Greetinx,
    Bas Steijvers
    AnswerRe: C#.NET versionmemberLen Holgate9 May '06 - 22:39 
    To create a C# control panel applet you'd probably have to host the CLR within a normal control panel applet and then load your C# applet into that. It's not something that I'd ever consider doing.
     
    Len Holgate
    www.jetbyte.com
    The right code, right now.

    GeneralRe: C#.NET versionmemberRipplingCreek13 Oct '06 - 6:22 
    First of all, I'd like to say we have used JetByte as consultants, and they are excellent. Highly competent.
     
    In response to the question above... what about just launching your .NET app from a win32 project built on this framework?
     
    Just a thought.
     
    -Steve
    QuestionHow to known status of CD_ROM door...memberthienlydochanh10 Jun '02 - 18:21 
    I want to be known status of CD_Rom door opening or closing by using function with VC++. You can ...?Frown | :(
     
    thienlydochanh
    AnswerRe: How to known status of CD_ROM door...memberaphazel23 Nov '09 - 20:34 
    I used to do this (and other media related stuff) using MCI API.

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

    Permalink | Advertise | Privacy | Mobile
    Web03 | 2.6.130523.1 | Last Updated 25 Feb 2000
    Article Copyright 2000 by Len Holgate
    Everything else Copyright © CodeProject, 1999-2013
    Terms of Use
    Layout: fixed | fluid