Zitat:
procedure DrawCellsgPI(Sender: tobject; ACol, ARow: Integer; Rect: TRect; State: TGridDrawState);
DrawCellsgPI ist eine "standalone"-Prozedur, keine Methode eines Objects. Ein Zeiger auf eine solche Prozedur ist ein simpler Pointer mit der Code-Adresse der Prozedure, also sizeof(pointer) groß.
Zitat:
var sgPI : TStringGrid; // StringGrid für ProgrammInfo
begin
sgPI := TStringGrid.Create(nil);
sgPI.Parent := Form1;
sgPI.ondrawcell := DrawCellsgPI; // !!! Hier ist der Fehler !!!
OnDrawCell ist wie alle Events in der
VCL eine Methoden-Referenz. Eine Methoden-Referenz ist ein Record aus zwei Pointern, es gibt dafür sogar einen eigenen Typ in der System-
Unit:
Delphi-Quellcode:
TMethod = record
Code, Data: Pointer;
end;
Code enthält die Code-Adresse der Methode, Data die Addresse des Objektes, zu dem die Methode gehört. Es gibt noch einen weiteren Unterschied zwischen standalone-Prozeduren und Objekt-Methoden: letztere haben einen zusätzlichen Parameter, der nicht in der Deklaration genannt wird, nämlich Self, in dem der Compiler bei einem Aufruf der Methode die Addresse des Objektes übergibt, dessen Methode aufgerufen wird.
Deine DrawCellsgPI-Prozedur ist also nicht kompatibel mit der Signatur eines event handlers für OnDrawCell. Wenn Du also den Kode zur Anzeige deiner Programminfo aus der Formklasse heraushalten willst (ein durchaus lobenswertes Vorhaben
) mußt Du DrawCellsgPI mit den Erwartungen des Compilers kompatibel machen. Dafür gibt es zwei prinzipielle Ansätze:
1. Mach aus der Prozedur eine public class method einer Klasse, z. B.
Delphi-Quellcode:
type
TProgrammInfo = class
public
class procedure DrawCellsgPI(Sender: tobject; ACol, ARow: Integer; Rect: TRect; State: TGridDrawState);
end;
...
sgPI.ondrawcell := TProgrammInfo.DrawCellsgPI;
Eine class method (so sie denn nicht als static deklariert wurde) hat auch einen impliziten Self-Parameter, die Signatur passt also.
2. Trickse den Compiler aus.
Dazu mußt Du die Deklaration von DrawCellsgPI so ändern:
procedure DrawCellsgPI(Self, Sender: tobject; ACol, ARow: Integer; Rect: TRect; State: TGridDrawState);
Die Zuweisung des Eventhanders ist dann etwas aufwendiger aber machbar:
Delphi-Quellcode:
var
sgPI : TStringGrid; // StringGrid für ProgrammInfo
M : TMethod;
begin
sgPI := TStringGrid.Create(nil);
sgPI.Parent := Form1;
M.Code := @DrawCellsgPI;
M.Data := nil;
sgPI.ondrawcell := TDrawCellEvent(M);
Option 1 ist meiner Meinung nach die bessere Variante, da Du in dieser Helferklasse ja noch mehr Code bündeln kannst.