A Control Panel Applet Framework

Submitted on: 1/3/2015 7:05:00 PM
By: Len Holgate (from psc cd)  
Level: Intermediate
User Rating: By 3 Users
Compatibility: Microsoft Visual C++
Views: 3636
     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. But what are control panel applets and how do you write one?

This article has accompanying files
				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 we 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.

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!

winzip iconDownload article

Note: Due to the size or complexity of this submission, the author has submitted it as a .zip file to shorten your download time. Afterdownloading it, you will need a program like Winzip to decompress it.Virus note:All files are scanned once-a-day by Planet Source Code for viruses, but new viruses come out every day, so no prevention program can catch 100% of them. For your own safety, please:
  1. Re-scan downloaded files using your personal virus checker before using it.
  2. NEVER, EVER run compiled files (.exe's, .ocx's, .dll's etc.)--only run source code.

If you don't have a virus scanner, you can get one at many places on the net

Report Bad Submission
Use this form to tell us if this entry should be deleted (i.e contains no code, is a virus, etc.).
This submission should be removed because:

Your Vote

What do you think of this article (in the Intermediate category)?
(The article with your highest vote will win this month's coding contest!)
Excellent  Good  Average  Below Average  Poor (See voting log ...)

Other User Comments

 There are no comments on this submission.

Add Your Feedback
Your feedback will be posted below and an email sent to the author. Please remember that the author was kind enough to share this with you, so any criticisms must be stated politely, or they will be deleted. (For feedback not related to this particular article, please click here instead.)

To post feedback, first please login.