Articles   Members Online:
-Article/Tip Search
-News Group Search over 21 Million news group articles.
-Delphi/Pascal
-CBuilder/C++
-C#Builder/C#
-JBuilder/Java
-Kylix
Member Area
-Home
-Account Center
-Top 10 NEW!!
-Submit Article/Tip
-Forums Upgraded!!
-My Articles
-Edit Information
-Login/Logout
-Become a Member
-Why sign up!
-Newsletter
-Chat Online!
-Indexes NEW!!
Employment
-Build your resume
-Find a job
-Post a job
-Resume Search
Contacts
-Contacts
-Feedbacks
-Link to us
-Privacy/Disclaimer
Embarcadero
Visit Embarcadero
Embarcadero Community
JEDI
Links
How to load and launch a Control Panel applet Turn on/off line numbers in source code. Switch to Orginial background IDE or DSP color Comment or reply to this aritlce/tip for discussion. Bookmark this article to my favorite article(s). Print this article
28-Aug-02
Category
System
Language
Delphi 3.x
Views
139
User Rating
No Votes
# Votes
0
Replies
0
Publisher:
DSP, Administrator
Reference URL:
DKB
			Author: Tomas Rutkauskas 

How to load and launch a Control Panel applet

Answer:

1   {
2   Unit AppletLauncher
3   
4   Version:
5   1.0  Created: 23.08.98, 11:14:39
6   Last Modified: 23.08.98, 11:14:39
7   
8   Author : P. Below
9   Project: Win32 utilities
10  Delphi version: 3.x (not tested on 4.x)
11  
12  Description:
13  Provides a class to load and launch a control panel applet. The applet is loaded 
14  when an
15  instance of this class is created and unloaded when it is destroyed. Applet dialogs 
16  are not
17  shown unless explicitely requested. The required API definitions are obtained from 
18  the Delphi
19  unit CPL. Processing is complicated by the fact that even Win32 applets may not 
20  respond to
21  CPL_NEWINQUIRE. This requires storage for both old (CPL_INQUIRE) and new style info
22  records. For a dialog only one of the list will contain a valid pointer to an info 
23  record, the other
24  will contain Nil in that slot.
25  
26  Note:
27  There are several errors in the win32 docs for the return values of CPL_ messages. 
28  Generally
29  the CPlApplet entry point will return 0 (False) if the function fails and <> 0 
30  (TRUE) if it succeeds.
31  The docs indicate the inverse.
32  }
33  
34  unit AppletLauncher;
35  
36  interface
37  
38  uses
39    Classes, Windows, CPL, Graphics, Sysutils;
40  
41  type
42    TAppletLauncher = class
43    private
44      hCPL: HMODULE; { applet module handle }
45      hParent: HWND; { container window handle }
46      CPlApplet: TCPlApplet; { applet entry point }
47      FDialogCount: Integer; { number of dialogs available }
48      FDialogData: TList; { stores TNewCPLnfo records for the dialogs }
49      FOldDialogData: TList; { stores TCPlInfo records for the dialog }
50      FAppletName: string; { filename of applet }
51    protected
52      function GetDialogNames(index: Integer): string;
53      function GetDialogInfotext(index: Integer): string;
54      function GetDialogIcon(index: Integer): HICON;
55      function GetDeleteIcon(index: Integer): Boolean;
56      function DialogLData(index: Integer): Longint;
57      function LoadCPLResourceString(strid: Integer): string;
58      procedure ValidateIndex(index: Integer); virtual;
59    public
60      constructor Create(anAppletName: string; hwndParent: HWND);
61      destructor Destroy; override;
62      procedure ShowDialog(index: Integer);
63      property DialogCount: Integer read FDialogCount;
64      property DialogNames[index: Integer]: string read GetDialogNames; default;
65      property DialogInfotext[index: Integer]: string read GetDialogInfotext;
66      property DialogIcons[index: Integer]: HIcon read GetDialogIcon;
67      property DeleteIcon[index: Integer]: Boolean read GetDeleteIcon;
68      property AppletName: string read FAppletName;
69    end;
70  
71    EAppletError = class(Exception);
72  
73  implementation
74  
75  resourcestring { change to Const for Win16 }
76    errCannotLoadApplet = 'TAppletLauncher: cannot load applet %s, reason: %s.';
77    errInvalidApplet = 'TAppletLauncher: %s is not a control panel applet, it does ' 
78  + 'not export
79      the CPlApplet entry point.'
80      errAppletInitializationFailed = 'TAppletLauncher: initialization of applet %s 
81  failed.'
82    errAppletHasNoDialogs = 'TAppletLauncher: applet %s provides no dialogs.';
83    errCannotGetDialogInfo = 'TAppletLauncher: applet %s does not respond to 
84  CPL_INQUIRE, '
85      'the launcher is unable to obtain the required information about ' +
86      'the applets dialogs.';
87    errSelectDialogFailed = 'TAppletLauncher: applet %s failed to open dialog #%d 
88  (%s).'
89    errIndexOutOfBounds = 'TAppletLauncher: dialog index %d is invalid for applet %s, 
90  '+
91      'the allowed range is 0..%d.';
92  
93    {Methods of TAppletLauncher}
94  
95    {
96    Constructor TAppletLauncher.Create
97  
98    Parameters:
99    anAppletName:
100   file name of the applet to load. This name must contain the CPL extention and can 
101 contain a
102   full path, if the applet does not reside in the windows or system directories.
103   hwndParent:
104   handle of window that serves as control panel replacement. Use the main forms 
105 handle, for
106   example. This window is used as parent for the applets dialogs. If 0 is passed we 
107 use the
108   active window as parent.
109 
110   Call method: static
111 
112   Description:
113   Loads the applet DLL, creates the internal list and fills it with information 
114 records for the dialogs
115   the applet provides. Several messages are send to the applets entry point during 
116 construction.
117 
118   Error Conditions:
119   An exception will be raised if the applet could not be loaded or if it does not 
120 respond in the
121   expected way to the send messages. The object is destroyed automatically in this 
122 case.
123   }
124 
125 constructor TAppletLauncher.Create(anAppletName: string; hwndParent: HWND);
126 var
127   i: Integer;
128   pData: PNewCPlInfo;
129   pOldData: PCPlInfo;
130 begin
131   inherited Create;
132   if hwndParent = 0 then
133   begin
134     hwndparent := GetActiveWindow;
135   end;
136   hParent := hwndParent;
137   { Try to load the applet DLL.  }
138   hCPL := LoadLibrary(Pchar(anAppletName));
139   if hCPL = 0 then
140   begin
141     { Error, applet not found. Note: change logic for Win16! }
142     raise EAppletError.CreateFmt(errCannotLoadApplet, [anAppletName,
143       SysErrorMessage(GetLastError)]);
144   end;
145   FAppletName := anAppletName;
146   { Find applet entry point }
147   @CPlApplet := GetProcAddress(hCPL, 'CPlApplet');
148   if @CPlApplet = nil then
149   begin
150     { Entry point not found, this is not a control panel applet! }
151     raise EAppletError.CreateFmt(errInvalidApplet, [anAppletName]);
152   end;
153   { Send CPL_INIT to the applet }
154   if CPlApplet(hParent, CPL_INIT, 0, 0) = 0 then
155   begin
156     { Applet failed to initialize, bail out. }
157     raise EAppletError.CreateFmt(errAppletInitializationFailed, [anAppletName]);
158   end;
159   { Get number of dialogs the applet supports }
160   FDialogCount := CPlApplet(hParent, CPL_GETCOUNT, 0, 0);
161   if FDialogCount = 0 then
162   begin
163     raise EAppletError.CreateFmt(errAppletHasNoDialogs, [anAppletName]);
164   end;
165   { Create list for the dialog information }
166   FDialogData := TList.Create;
167   FDialogData.Capacity := FDialogCount;
168   FOldDialogData := TList.Create;
169   FOldDialogData.Capacity := FDialogCount;
170   { Get the information for the dialogs }
171   for i := 0 to FDialogCount - 1 do
172   begin
173     New(pData);
174     FillChar(pData^, Sizeof(pData^), 0);
175     pData^.dwSize := Sizeof(pData^);
176     if CPlApplet(hParent, CPL_NEWINQUIRE, i, longint(pData)) = 0 then
177     begin
178       { Failed, try CPL_INQUIRE instead }
179       Dispose(pData);
180       New(pOldData);
181       if CPlApplet(hParent, CPL_INQUIRE, i, longint(pOldData)) = 0 then
182       begin
183         { Failed also, bail out }
184         Dispose(pOldData);
185         raise EAppletError.CreateFmt(errCannotGetDialogInfo, [anAppletName]);
186       end
187       else
188       begin
189         FOldDialogData.Add(pOldData);
190         FDialogData.Add(nil);
191       end;
192     end { If }
193     else
194     begin
195       { CPL_NEWINQUIRE succeeded, store the data }
196       FDialogData.Add(pData);
197       FOldDialogData.Add(nil);
198     end;
199   end;
200   { Setup is complete }
201 end;
202 
203 {
204 Destructor TAppletLauncher.Destroy
205 
206 Parameters: none
207 
208 Call method: virtual, overridden
209 
210 Description:
211 Releases memory for the dialog data records, destroys the list holding the records, 
212 tells the
213 applet to clean up its act and finally unloads the applet. The destructor can be 
214 called on
215 a partially initialized object if an exception is raised in the constructor.
216 
217 Error Conditions: none
218 }
219 
220 destructor TAppletLauncher.Destroy;
221 var
222   i: Integer;
223 begin
224   { Tell applet to clean up its dialogs and release the dialog data, if 
225 initialization
226   completed successfully }
227   if Assigned(FDialogData) then
228   begin
229     for i := 0 to FDialogData.Count - 1 do
230     begin
231       CPlApplet(hParent, CPL_STOP, i, DialogLData(i));
232       if Assigned(FDialogData[i]) then
233       begin
234         Dispose(pNewCPlInfo(FDialogData[i]));
235       end;
236     end;
237     FDialogData.Free;
238   end;
239   if Assigned(FOldDialogData) then
240   begin
241     for i := 0 to FOldDialogData.Count - 1 do
242     begin
243       if Assigned(FOldDialogData[i]) then
244       begin
245         Dispose(pCPlInfo(FOldDialogData[i]));
246       end;
247     end;
248     FOldDialogData.Free;
249   end;
250   { Tell applet to clean up, if load was successful. Note: this code is executed 
251 even if CPL_INIT
252   failed, I don't know if this may cause a problem. }
253   if Assigned(@CPlApplet) then
254   begin
255     CPlApplet(hParent, CPL_EXIT, 0, 0);
256   end;
257   { Unload the applet, if it was loaded }
258   if hCPL <> 0 then
259   begin
260     FreeLibrary(hCPL);
261   end;
262   inherited Destroy;
263 end;
264 
265 {
266 Procedure TAppletLauncher.ShowDialog
267 
268 Parameters:
269 index: dialog index, has to be in the range 0..DialogCount-1
270 
271 Call method: static
272 
273 Description:
274 Tells the applet to open the requested dialog.
275 
276 Error Conditions:
277 Exceptions will be raised if the passed index is out of bounds or the applet fails 
278 to launch the dialog.
279 }
280 
281 procedure TAppletLauncher.ShowDialog(index: Integer);
282 begin
283   ValidateIndex(index);
284   if CPlApplet(hParent, CPL_DBLCLK, index, DialogLData(index)) = 0 then
285   begin
286     raise EAppletError.CreateFmt(errSelectDialogFailed, [FAppletName, index, 
287 DialogNames[index]]);
288   end;
289 end;
290 
291 {
292 Function TAppletLauncher.GetDialogNames
293 
294 Parameters:
295 index: dialog index, has to be in the range 0..DialogCount-1
296 
297 Returns:
298 the szname field of the dialog info record for this dialog.
299 
300 Call method: static
301 
302 Description:
303 This method implements read access to the DialogNames property.
304 
305 Error Conditions:
306 An exceptions will be raised if the passed index is out of bounds.
307 }
308 
309 function TAppletLauncher.GetDialogNames(index: Integer): string;
310 begin
311   ValidateIndex(index);
312   if Assigned(FDialogData[index]) then
313   begin
314     result := Strpas(pNewCPlInfo(FDialogData[index])^.szName);
315   end
316   else
317     result := LoadCPLResourceString(pCPlInfo(FOldDialogData[index])^.idName);
318 end;
319 
320 {
321 Function TAppletLauncher.GetDialogInfotext
322 
323 Parameters:
324 index: dialog index, has to be in the range 0..DialogCount-1
325 
326 Returns:
327 the szinfo field of the dialog info record for this dialog.
328 
329 Call method: static
330 
331 Description:
332 This method implements read access to the DialogInfotext property.
333 
334 Error Conditions:
335 An exceptions will be raised if the passed index is out of bounds.
336 }
337 
338 function TAppletLauncher.GetDialogInfotext(index: Integer): string;
339 begin
340   ValidateIndex(index);
341   if Assigned(FDialogData[index]) then
342   begin
343     result := Strpas(pNewCPlInfo(FDialogData[index])^.szInfo);
344   end
345   else
346     result := LoadCPLResourceString(pCPlInfo(FOldDialogData[index])^.idInfo);
347 end;
348 
349 {
350 Function TAppletLauncher.GetDialogIcon
351 
352 Parameters:
353 index: dialog index, has to be in the range 0..DialogCount-1
354 
355 Returns:
356 the icon handle for the icon to display for this dialog. Note that the handle can 
357 be 0!
358 Use DrawIconEx to display this icon on a canvas, or create a TIcon and assign the
359 return value to its Handle property.
360 
361 Call method: static
362 
363 Description:
364 This method implements read access to the DialogIcons property.
365 PROBLEM ALERT!
366 For applets that respond to CPL_NEWINQUIRE the icon handle is owned by the applet 
367 and
368 must not be deleted by the application. For old-style applets that respond only to 
369 CPL_INQUIRE,
370 however, the icon is created from a resource and the application must delete it to 
371 prevent a
372 resource leak! Check the DeleteIcon property to determine what to do.
373 
374 Error Conditions:
375 An exceptions will be raised if the passed index is out of bounds.
376 }
377 
378 function TAppletLauncher.GetDialogIcon(index: Integer): HICon;
379 begin
380   ValidateIndex(index);
381   if Assigned(FDialogData[index]) then
382   begin
383     result := pNewCPlInfo(FDialogData[index])^.hIcon;
384   end
385   else
386     result := LoadIcon(hCPL, 
387 MakeIntResource(pCPlInfo(FOldDialogData[index])^.idIcon));
388 end;
389 
390 {
391 Function TAppletLauncher.GetDeleteIcon
392 
393 Parameters:
394 index: dialog index, has to be in the range 0..DialogCount-1
395 
396 Returns:
397 True if caller needs to delete an icon retrieved via DialogIcons for this index, 
398 false otherwise.
399 
400 Call method: static
401 
402 Description:
403 See Problem Alert entry under GetDialogIcon.
404 
405 Error Conditions:
406 An exceptions will be raised if the passed index is out of bounds.
407 }
408 
409 function TAppletLauncher.GetDeleteIcon(index: Integer): Boolean;
410 begin
411   ValidateIndex(index);
412   Result := not Assigned(FDialogData[index]);
413 end;
414 
415 {
416 Procedure TAppletLauncher.ValidateIndex
417 
418 Parameters:
419 index: index to validate
420 
421 Call method: virtual
422 
423 Error Conditions:
424 raises an exception if the passed index is out of bounds. You can override this 
425 method to
426 change the behaviour.
427 }
428 
429 procedure TAppletLauncher.ValidateIndex(index: Integer);
430 begin
431   if (index < 0) or (index >= FDialogCount) then
432   begin
433     raise EAppletError.CreateFmt(errIndexOutOfBounds, [index, FAppletName, 
434 FDialogCount - 1]);
435   end;
436 end;
437 
438 {
439 Function TAppletLauncher.DialogLData
440 
441 Parameters:
442 index: dialog index, has to be in the range 0..DialogCount-1
443 
444 Returns:
445 the ldata member of the dialog data.
446 
447 Call method: static
448 
449 Description:
450 Helper function to deal with the different data record formats we can have.
451 
452 Error Conditions: none
453 }
454 
455 function TAppletLauncher.DialogLData(index: Integer): Longint;
456 begin
457   if Assigned(FDialogData[index]) then
458     Result := pNewCPlInfo(FDialogData[index])^.ldata
459   else
460     Result := pCPlInfo(FOldDialogData[index])^.ldata
461 end;
462 
463 {
464 Function TAppletLauncher.LoadCPLResourceString
465 
466 Parameters:
467 strid: resource id of string to load
468 
469 Returns:
470 the string
471 
472 Call method: static
473 
474 Description:
475 Helper function to get a resource string from the applet.
476 
477 Error Conditions: none
478 }
479 
480 function TAppletLauncher.LoadCPLResourceString(strid: Integer): string;
481 begin
482   SetLength(result, 1024);
483   SetLength(result, LoadString(hCPL, strid, @result[1], 1024));
484 end;
485 
486 end.


			
Vote: How useful do you find this Article/Tip?
Bad Excellent
1 2 3 4 5 6 7 8 9 10

 

Advertisement
Share this page
Advertisement
Download from Google

Copyright © Mendozi Enterprises LLC