Author: Tomas Rutkauskas
I want to develop an own Application for Win9x Control Panel. First I thought I
just have to rename an *.exe File to *.cpl, but that doesn't work. Now I heard,
*.cpl files are Dynamic Link Libraries. So, which functions do I have to implement
into my DLL interface?
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.
1 library TestCpl;
2
3 {$IFDEF WIN32}
4 uses
5 SysUtils, Windows, Messages;
6
7 {$ELSE}
8
9 uses
10 SysUtils, WinTypes, WinProcs, Messages;
11
12 {$ENDIF}
13 {$IFDEF WIN32}
14 {$R TCPL32.RES}
15 {$ELSE}
16 {$R TCPL16.RES}
17 {$ENDIF}
18
19 const
20 NUM_APPLETS = 1;
21
22 {$IFDEF WIN32}
23 const
24 CPL_DYNAMIC_RES = 0;
25 {$ENDIF}
26 const
27 CPL_INIT = 1;
28 const
29 CPL_GETCOUNT = 2;
30 const
31 CPL_INQUIRE = 3;
32 const
33 CPL_SELECT = 4;
34 const
35 CPL_DBLCLK = 5;
36 const
37 CPL_STOP = 6;
38 const
39 CPL_EXIT = 7;
40 const
41 CPL_NEWINQUIRE = 8;
42 {$IFDEF WIN32}
43 const
44 CPL_STARTWPARMS = 9;
45 {$ENDIF}
46 const
47 CPL_SETUP = 200;
48
49 {$IFNDEF WIN32}
50 type
51 DWORD = LongInt;
52 {$ENDIF}
53
54 type
55 TCplInfo = record
56 idIcon: integer;
57 idName: integer;
58 idInfo: integer;
59 lData: LongInt;
60 end;
61 PCplInfo = ^TCplInfo;
62
63 type
64 TNewCplInfoA = record
65 dwSize: DWORD;
66 dwFlags: DWORD;
67 dwHelpContext: DWORD;
68 lData: LongInt;
69 IconH: HIcon;
70 szName: array[0..31] of char;
71 szInfo: array[0..63] of char;
72 szHelpFile: array[0..127] of char;
73 end;
74 PNewCplInfoA = ^TNewCplInfoA;
75
76 {$IFDEF WIN32}
77 type
78 TNewCplInfoW = record
79 dwSize: DWORD;
80 dwFlags: DWORD;
81 dwHelpContext: DWORD;
82 lData: LongInt;
83 IconH: HIcon;
84 szName: array[0..31] of WChar;
85 szInfo: array[0..63] of WChar;
86 szHelpFile: array[0..127] of WChar;
87 end;
88 PNewCplInfoW = ^TNewCplInfoW;
89 {$ENDIF}
90
91 type
92 TNewCplInfo = TNewCplInfoA;
93 type
94 PNewCplInfo = ^TNewCplInfoA;
95
96 function CPlApplet(hWndCPL: hWnd; iMEssage: integer; lParam1: longint;
97 lParam2: longint): Longint{$IFDEF WIN32} stdcall;
98 {$ELSE}; export;
99 {$ENDIF}
100 begin
101 case iMessage of
102 CPL_INIT:
103 begin
104 Result := 1;
105 exit;
106 end;
107 CPL_GetCount:
108 begin
109 Result := NUM_APPLETS;
110 exit;
111 end;
112 CPL_Inquire:
113 begin
114 PCplInfo(lParam2)^.idIcon := 2;
115 PCplInfo(lParam2)^.idName := 1;
116 PCplInfo(lParam2)^.idInfo := 2;
117 PCplInfo(lParam2)^.lData := 0;
118 Result := 1;
119 exit;
120 end;
121 CPL_NewInquire:
122 begin
123 PNewCplInfo(lParam2)^.dwSize := sizeof(TNewCplInfo);
124 PNewCplInfo(lParam2)^.dwHelpContext := 0;
125 PNewCplInfo(lParam2)^.lData := 0;
126 PNewCplInfo(lParam2)^.IconH := LoadIcon(hInstance, MakeIntResource(2));
127 lStrCpy(@PNewCplInfo(lParam2)^.szName, 'TestCPL');
128 lStrCpy(PNewCplInfo(lParam2)^.szInfo, 'My Test CPL');
129 PNewCplInfo(lParam2)^.szHelpFile[0] := #0;
130 Result := 1;
131 exit;
132 end;
133 CPL_SELECT:
134 begin
135 Result := 0;
136 exit;
137 end;
138 CPL_DBLCLK:
139 begin
140 WinExec('Notepad.exe', SW_SHOWNORMAL);
141 Result := 1;
142 exit;
143 end;
144 CPL_STOP:
145 begin
146 Result := 0;
147 exit;
148 end;
149 CPL_EXIT:
150 begin
151 Result := 0;
152 exit;
153 end
154 else
155 begin
156 Result := 0;
157 exit;
158 end;
159 end;
160 end;
161
162 exports CPlApplet name 'CPlApplet';
163
164 begin
165 end.
|