Vergiss das mit dem Ableiten vom Panel am besten schnell wieder. Ich habe exakt genau dieselbe Klamotte für unser Büro vor ein paar Jahren gemacht - also zu 100% genau das was du machen willst - und es kommt zu 100% der Punkt, wo ein unabdingbar rechteckciges undurchsichtiges Etwas einem so RICHTIG in die Suppe spuckt.
Alles was im Wesentlichen einfach nur eine Anzeige sein soll (aber durchaus auch Klick-Ereignisse bietet) wird von TGraphicControl abgeleitet und nichts anderem. Das zeichnet brav auf den Canvas des Parents (üblicherweise ein Formular oder Frame oder Panel) und bringt alles an Basisfunktionalität mit.
Auch von TShapes innerhalb dieser Komponenten würde ich Abstand nehmen. Das sauberste ist es einfach alles von Hand zu malen, und SO viel aufwendiger ist das gar nicht. Mal ein grobes Gerüst:
Delphi-Quellcode:
TVisuBase = class(TGraphicControl)
private
protected
procedure Paint; override;
public
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
published
property Visible;
property Anchors;
property Align;
property Cursor;
property ShowHint;
property OnClick;
property OnContextPopup;
property OnDblClick;
property OnMouseDown;
property OnMouseMove;
property OnMouseUp;
property OnMouseWheel;
property OnMouseWheelDown;
property OnMouseWheelUp;
property OnResize;
end; // Die letzten hier nur um sie im Property-Editor sichtbar zu machen. In TGraphicControl sind diese Member alle nur public, nicht published.
implementation
constructor TVisuBase.Create(AOwner: TComponent);
begin
inherited;
// Ab hier Initialisierungen, aber bitte NICHT TShapes und so, und schon gar nicht als lokale Variablen!!
end;
destructor TVisuBase.Destroy;
begin
// Hier deine Freigaben
inherited;
end;
procedure TVisuBase.Paint;
begin
inherited; // <--- Wichtig!!!
// Hier nun deine Zeichenroutine. Beispiel: Ein Rotes Rechteck mit 5px Abstand zum Rand der Komponente.
Canvas.Brush.Color := clRed;
Canvas.Brush.Style := bsSolid;
Canvas.FillRect(Rect(5, 5, Width-5, Height-5));
end;
Es ist wichtig die überschriebene Methode "Paint" hier zu nehmen, da diese immer aufgerufen wird, wenn Windows der Meinung ist es müsste neugezeichnet werden (Message wmPaint). Man selbst löst dies z.B. durch VisuBase.Repaint; oder VisuBase.Refresh; oder VisuBase.Invalidate; aus, wie mit allen anderen visuellen Komponenten auch. Und mache dich auf
jeden Fall damit vertraut alles via "Canvas." zu malen - oder zumindest nichts aus weiteren Komponenten zusammenzusetzen - weil das kann nach hinten raus richtig eklig werden. (Speziell wenn man nachher mit der Zeichenreihenfolge rum machen muss und sich schöne zirkuläre Überlappungen ergeben oder auch Komponenten auf Basis von TWinControl können lustige Sachen machen, etc. pp.)
Ich selbst hatte mir noch eine Zwischenklasse gebaut die von TGraphicControl abgeleitet ist, von der dann alle meine Visu-Klassen ableiten. Das hing aber damit zusammen, das hinter dem ganzen noch ein etwas komplexeres Datenbanksystem steht, mit dem ohnehin alle Komponenten hantieren müssen, so dass es Sinn machte diese Gemeinsamkeit in einen Zwischenschritt zu kapseln. Das aber nur als Anregung, falls es bei dir auch etwas größeres werden soll, nicht nur eine einmalige kleine Maschinensteuerung. (Wir entwickeln damit z.B. ganze Leitsysteme für recht große Anlagen weltweit agierender Konzerne.)
Gedanklich bin ich aber schon längst dabei etwas auf HTML5 zusammenzuspinnen für die Zukunft, aber die Zeit müsste man für sowas erstmal haben
"When one person suffers from a delusion, it is called insanity. When a million people suffer from a delusion, it is called religion." (Richard Dawkins)