Mega Code Archive

 
Categories / Delphi / Examples
 

Control panel applets

Question: How do I create a Control Panel Applet? Answer: Creating a Control Panel Applet is a straight forward process. Simply create a Dynamic Link Library with the extension of .cpl (Control Panel Library) and place it in the Windows system directory. Each cpl file can support multiple control panel applets. The cpl will have a single function entry point called CPlApplet() that must be exported by name. All the following control panel messages will come through this single entry point: Message: CPL_INIT - Sent to indicate CPlApplet() was found. Return TRUE to continue the loading process. CPL_GETCOUNT - Return the number of applets supported by the cpl. CPL_INQUIRE - Sent for information about each applet supported by the cpl.lParam1 contains the zero based applet number for the inquiry. lParam2 points to a TCplInfo structure. The idIcon field of the TClpInfo structure should be initialized with the resource id for an icon to display, and the idName and idInfo fields should be initialized with the resource string id for the name and description string id.lData can contain applet defined data for use by the applet. CPL_SELECT - Sent when the applet's icon has been selected by the user. lParam1 contains the applet number that was selected. lParam2 contains the applet's user defined lData value. CPL_DBLCLK - Sent when the applet's icon has been double-clicked. lParam1 contains the applet number. lParam2 contains the applet's user defined lData value. This message initiates the display of the applet's dialog box. CPL_STOP - Sent for each applet when the control panel is exiting. lParam1 contains the applet number. lParam2 contains the applet's user defined lData value. Any applet specific cleaning up should be performed during this call. CPL_EXIT - Sent prior to the control panel call to FreeLibrary. Non-applet specific cleaning up should be performed during this call. CPL_NEWINQUIRE - Same as CPL_INQUIRE except lParam2 is a pointer to a NEWCPLINFO structure. Your control panel library will need some additional resources to function. You will need to create a resource file containing a string table containing both the name and description of your applet(s) and icons for each applet in your cpl. You can create a res file from a .rc (resource script file) using the BRCC.EXE or BRCC32.EXE command line resource compiler, or a WYSIWYG resource editor like Borland's Resource Workshop. Example .rc file containing a string table with two strings and a pointer to a icon file resource: STRINGTABLE { 1, "TestApplet" 2, "My Test Applet" } 2 ICON C:\SOMEPATH\CHIP.ICO To compile the .rc file to a .res file that can be linked with your application, simply type on the dos command line the full path to the resource compiler, and the full path to the name of the .rc file to compile. Here is an example: c:\Delphi\Bin\brcc32.exe c:\Delphi\MyRes.rc When the compiler is finished, you should have a new file with the same name as the .rc file you've compiled, only with an extension of ".res". If you are developing for multiple platforms, you should create both a 16 and 32 bit res file for linkage with your application. The following is an example of a control panel applet that executes a secondary executable in response to the CPL_DBLCLK message. You can adapt the code to show a form or dialog box as well. The example is coded to compile for Win16 and Win32 environments. To build the project, you will need to compile the above .rc file to a res file named either: TCPL32.RES or TCPL16.RES. Example: library TestCpl; {$IFDEF WIN32} uses SysUtils, Windows, Messages; {$ELSE} uses SysUtils, WinTypes, WinProcs, Messages; {$ENDIF} {$IFDEF WIN32} {$R TCPL32.RES} {$ELSE} {$R TCPL16.RES} {$ENDIF} const NUM_APPLETS = 1; {$IFDEF WIN32} const CPL_DYNAMIC_RES = 0; {$ENDIF} const CPL_INIT = 1; const CPL_GETCOUNT = 2; const CPL_INQUIRE = 3; const CPL_SELECT = 4; const CPL_DBLCLK = 5; const CPL_STOP = 6; const CPL_EXIT = 7; const CPL_NEWINQUIRE = 8; {$IFDEF WIN32} const CPL_STARTWPARMS = 9; {$ENDIF} const CPL_SETUP = 200; {$IFNDEF WIN32} type DWORD = LongInt; {$ENDIF} type TCplInfo = record idIcon : integer; idName : integer; idInfo : integer; lData : LongInt; end; PCplInfo = ^TCplInfo; type TNewCplInfoA = record dwSize : DWORD; dwFlags : DWORD; dwHelpContext : DWORD; lData : LongInt; IconH : HIcon; szName : array [0..31] of char; szInfo : array [0..63] of char; szHelpFile : array [0..127] of char; end; PNewCplInfoA = ^TNewCplInfoA; {$IFDEF WIN32} type TNewCplInfoW = record dwSize : DWORD; dwFlags : DWORD; dwHelpContext : DWORD; lData : LongInt; IconH : HIcon; szName : array [0..31] of WChar; szInfo : array [0..63] of WChar; szHelpFile : array [0..127] of WChar; end; PNewCplInfoW = ^TNewCplInfoW; {$ENDIF} type TNewCplInfo = TNewCplInfoA; type PNewCplInfo = ^TNewCplInfoA; function CPlApplet(hWndCPL : hWnd; iMEssage : integer; lParam1 : longint; lParam2 : longint) : LongInt {$IFDEF WIN32} stdcall; {$ELSE} ; export; {$ENDIF} begin case iMessage of CPL_INIT : begin Result := 1; exit; end; CPL_GetCount : begin Result := NUM_APPLETS; exit; end; CPL_Inquire : begin PCplInfo(lParam2)^.idIcon := 2; PCplInfo(lParam2)^.idName := 1; PCplInfo(lParam2)^.idInfo := 2; PCplInfo(lParam2)^.lData := 0; Result := 1; exit; end; CPL_NewInquire : begin PNewCplInfo(lParam2)^.dwSize := sizeof(TNewCplInfo); PNewCplInfo(lParam2)^.dwHelpContext := 0; PNewCplInfo(lParam2)^.lData := 0; PNewCplInfo(lParam2)^.IconH := LoadIcon(hInstance, MakeIntResource(2)); lStrCpy(@PNewCplInfo(lParam2)^.szName, 'TestCPL'); lStrCpy(PNewCplInfo(lParam2)^.szInfo, 'My Test CPL'); PNewCplInfo(lParam2)^.szHelpFile[0] := #0; Result := 1; exit; end; CPL_SELECT : begin Result := 0; exit; end; CPL_DBLCLK : begin WinExec('Notepad.exe', SW_SHOWNORMAL); Result := 1; exit; end; CPL_STOP : begin Result := 0; exit; end; CPL_EXIT : begin Result := 0; exit; end else begin Result := 0; exit; end; end; end; exports CPlApplet name 'CPlApplet'; begin end.