Ja, Sie tun etwas falsch. :)
Einige Aspekte eines fensterbasierten Steuerelements erfordern, dass das Steuerelement in seinem Containerfenster platziert wird. Dies spiegelt normalerweise eine Anforderung in der zugrunde liegenden Fensterklasse selbst wider (nicht die VCL-Klasse, sondern das MS Windows-Fensterobjekt, das das Steuerelement darstellt).
In diesem Fall müssen Sie nur Ihre Zuordnung der Parent-Eigenschaft bewegen, so dass es, bevor Sie die Font.Style auftritt versuchen zu ändern:
DatEdit.OnEnter := CtrlInputProc;
DatEdit.OnExit := CtrlExitProc;
DatEdit.Enabled := false;
DatEdit.Parent := Canvas;
DatEdit.Font.Style := DatEdit.Font.Style + [fsItalic];
Ich weiß nicht, ob die Schriftart erfolgreich gesetzt werden kann Kursiv auf diese Weise oder nicht, aber dies sollte zumindest Ihre Ausnahme ansprechen.
UPDATE: Ich habe bestätigt, dass die Schriftart auf diese Weise kursiv geschrieben werden kann, solange Sie zuerst die Steuerung Parent gesetzt haben. (Ich habe Delphi 2009, aber ich würde überrascht, wenn es nicht in Delphi 5 funktioniert hat)
FYI: Ich würde stark eine andere Wahl des Namens für das „Canvas“ Control Panel empfehlen.
Addendum: -------
Es ist der Aufruf von InvalidateRect() im CMFontChanged() Nachrichten-Handler, der einen Fenstergriff erfordert (was wiederum erfordert, dass die Kontrolle unterzogen werden).
Wenn Sie absolut in der Lage sein müssen, um den Elternteilnach Modifizieren der Font, könnten Sie Ihre eigene Steuerklasse von TDateTimePicker ableiten und eine Antwort auf die CMFontChanged() Nachricht implementieren, unterdrückt das ererbte Verhalten, wenn die Steuerung übergeordnet ist:
type
TMyDateTimePicker = class(TDateTimePicker)
protected
procedure CMFontchanged(var Message: TMessage); message CM_FONTCHANGED;
end;
procedure TMyDateTimePicker.CMFontchanged(var Message: TMessage);
procedure AdjustHeight;
var
DC: HDC;
SaveFont: HFont;
SysMetrics, Metrics: TTextMetric;
begin
DC := GetDC(0);
try
GetTextMetrics(DC, SysMetrics);
SaveFont := SelectObject(DC, Font.Handle);
GetTextMetrics(DC, Metrics);
SelectObject(DC, SaveFont);
finally
ReleaseDC(0, DC);
end;
Height := Metrics.tmHeight + (GetSystemMetrics(SM_CYBORDER) * 8);
end;
begin
if HasParent then
inherited
else
AdjustHeight;
end;
Beachten Sie, dass die AdjustHeight() proc edure wird reproduziert von einem privaten Verfahren von TDateTimePicker. Wenn Sie nur den Font.Style ändern, müssen Sie diesen Code möglicherweise nicht reproduzieren und ihn entfernen und den Aufruf, aber wenn Sie andere Eigenschaften des Font ändern, dann sollte dies sicherstellen, dass das Steuerelement richtig dimensioniert ist .
Wenn Sie nennen geerbt der private AdjustHeight() Mechanismus aufgerufen wird, so dass keine Notwendigkeit besteht in diesem Fall die lokale Kopie dieses Verfahrens zu nennen.
Das Einfügen dieser Komponente in Parent wird später von purpouse ausgeführt. Ich erstelle oft Kontrollen (sogar Nachkommen von TFrame) und setze sie viel später auf Parent. Was ist seltsam für mich - in der gleichen Anwendung verwende ich fast den gleichen Code zu TEdit oder TComboBox ... und es funktioniert. Warum benötigt TDateTimePicker also Parent beim Korrigieren von Font.Style, während TEdit nicht? – smok1
BTW: Der Name "Canvas" wird höchstwahrscheinlich ersetzt werden. – smok1
Ein kurzer Blick auf die Quelle zeigt, dass der Hauptunterschied zwischen einem TEdit und einem TDateTimePicker darin besteht, dass das Ändern der Schriftart eines TDateTimePicker (TDateTimePicker.CMFontChanged() in ComCtrls) dazu führt, dass das Steuerelement sich selbst ungültig macht Fenstergriff. Um dieses Fensterhandle zu erhalten, muss das zugrundeliegende Fensterobjekt erstellt werden. Dazu muss das Containerfenster bekannt sein. Dies könnte vermieden werden, indem auf das Vorhandensein eines Fensterhandle getestet wird und nur ungültig gemacht wird, wenn das Fensterhandle vorhanden ist. Diese Verfeinerung ist jedoch nicht Teil der aktuellen Implementierung. – Deltics