Die Funktion "CPlApplet"


Die Funktion "CPlApplet" dient, wie bereits in den vorigen Kapiteln erwähnt, als Vermittler zwischen der Anwendung und dem System. Das System sendet Nachrichten an die Anwendung, auf die Sie reagieren müssen. Ich möchte Ihnen hier die grundlegende Kommunikation schrittweise demonstrieren. Das bedeutet, der hier gezeigte Code ist also Teil der Funktion "CPlApplet"

function CPlApplet(hwndCpl: HWND; uMsg: UINT; lp1, lp2: LPARAM):
  longint; stdcall;
begin
  Result := 1;
case uMsg of // Nachrichtenbearbeitung { ... }
else Result := 0; end; end;

Und wie Sie sehen können gibt es eigentlich auch keine großen Unterschiede zur bisher bekannten Nachrichtenbearbeitung von Fenstern und Dialogen.
Doch weiter im Text.

  1. Zuerst empfängt Ihre Anwendung die Nachricht "CPL_INIT". Das ist das Signal dafür, dass die Systemsteuerung aufgerufen wurde und sich nun bemüht, die einzelnen Module zu laden. Sie haben hier die Möglichkeit, weiteren Code zur Initialisierung Ihrer Anwendung zu schreiben. Wichtig ist, dass Sie mit dem Rückgabewert Eins antworten, wenn Ihre Anwendung geladen werden soll. Geben Sie Null als Ergebnis der Nachricht zurück, beendet das System die Kommunikation mit Ihrem Programm und lädt es auch nicht.
    Da in meinem Beispiel Eins der Standardwert ist, reicht es hier aus, die Property Sheets (dazu im nächsten Punkt) zu initialisieren:
    CPL_INIT:
      InitPropertySheet;
  2. Die zweite Nachricht ist "CPL_GETCOUNT". Hier geben Sie als Reaktion die Anzahl der in Ihrer Anwendung enthaltenen Einzelmodule zurück. Das hört sich verwirrend an? Ist es aber nicht. Ihre Anwendung kann nämlich aus mehreren Teilen bestehen. Das Beispiel etwa besitzt neben dem Originaldialog aus dem Dialog-Tutorial einen zweiten Dialog und ein Property Sheet. Diese drei "Module" sollen nun separat in der Systemsteuerung angezeigt werden, und darum muss das Rückgabeergebnis in dem Fall auch 3 lauten.
    Allerdings können Sie es sich auch einfacher machen. Dazu muss ich ein wenig auf den nächsten Punkt vorgreifen. Ich habe ein Record mit folgendem Aufbau definiert:
    type
      CPL_MODULES = record
        icon,			// Ressourcen-ID des Symbols
        name,			// Ressourcen-ID des Modulnamens (String-ID)
        description,		// Ressourcen-ID der Beschreibung (String-ID)
        dlgtemplate : integer;	// Ressourcen-ID des Dialogs
        dlgproc     : pointer;	// Zeiger auf Dialogprozedur
      end;
    Dieses Record findet sich in der Variablen "CplModules" wieder, die als Array deklariert ist
    var
      CplModules : array[0..2]of CPL_MODULES;
    Kurz gesagt kann ich daher die Größe dieses Arrays als Ergebnis auf die Nachricht "CPL_GETCOUNT" benutzen:
    CPL_GETCOUNT:
      Result := length(CplModules);
  3. Die nächste Nachricht, "CPL_INQUIRE", ist von der Anzahl der Einzelmodule abhängig. Das bedeutet, dass sie entsprechend oft aufgerufen wird. Bei unseren drei Modulen also dreimal.
    Sie müssen hier das Symbol, den Namen und eine erklärende Beschreibung für jedes Modul zurückliefern. Und genau da kommt das o.g. Record ins Spiel. Wie Sie sehen können enthält es integer-Werte für die drei genannten Eigenschaften. Das heißt, Sie müssen an der Stelle also die entsprechenden Ressourcen-IDs angeben. Welches Modul gerade abgefragt wird, das erfahren Sie mit Hilfe von lp1 aus dem Funktionskopf. Dieser Zähler ist null-basierend und entspricht damit auch dem Bereich der Variable "CplModules".
    Nun müssen die Daten aber noch irgendwie an das System übermittelt werden. Hier ist lp2 (aus dem Funktionskopf) wichtig. Diese Variable enthält einen Zeiger auf ein Record vom Typ TCplInfo, das wir mit unseren Werten füllen müssen. Dank der o.g. Variable geht das recht einfach und schnell:
    CPL_INQUIRE:
      begin
        PCplInfo(lp2)^.idIcon := CplModules[lp1].icon;
        PCplInfo(lp2)^.idName := CplModules[lp1].name;
        PCplInfo(lp2)^.idInfo := CplModules[lp1].description;
        PCplInfo(lp2)^.lData  := 0;
      end;


Wenn bis hier alles geklappt hat, dann müsste die Systemsteuerung nun auch Ihre drei neuen Module anzeigen.



Wenn der Anwender eins auswählt, wird die Nachricht "CPL_DBLCLK" gesendet. In dieser Nachricht sorgen Sie dann dafür, dass die jeweiligen Dialoge angezeigt werden. Auch hier wird in der Variablen lp1 der Index des gewünschten Moduls übermittelt, so dass im Fall meines Beispiels lediglich geprüft werden muss, ob dieser Wert 2 ist. Dann soll nämlich der Property Sheet-Dialog angezeigt werden, was aber einen anderen Befehl voraussetzt. In allen anderen Fällen kann ich "DialogBox" benutzen und mit Hilfe von "CplModules" die richtige Dialogressource und die richtige Dialogprozedur laden

CPL_DBLCLK:
  if(lp1 = 2) then PropertySheet(psh)
    else DialogBox(hInstance,MAKEINTRESOURCE(CplModules[lp1].dlgtemplate),
      hwndCpl,CplModules[lp1].dlgproc);



Prinzipiell reicht das bereits aus, um eine funktionierende Anwendung für die Systemsteuerung zu erstellen. Es gibt aber noch zwei weitere wichtige Nachrichten, auf die Sie im Bedarfsfall reagieren können. Etwa, um belegte Ressourcen o.ä. freizugeben. Diese Nachrichten sind

WertBedeutung
CPL_STOPDiese Nachricht wird gesendet, bevor die Systemsteuerung die geladenenen CPL-Dateien wieder freigibt. Sie ist von der Anzahl der in der CPL-Datei enthaltenen Module abhängig und wird entsprechend oft gesendet.
CPL_EXITWird nach "CPL_STOP" und vor dem Freigeben der Systemsteuerung gesendet.