2004. november 15., hétfő
How to develop a Control Panel applet
Problem/Question/Abstract:
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.
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.
Feliratkozás:
Megjegyzések küldése (Atom)
Nincsenek megjegyzések:
Megjegyzés küldése