2009-08-24 21 views
1

Ist es möglich, TDateTimePicker Schriftart kursiv zu setzen? Ich tue es in diesem CodeFehler beim Festlegen von TDateTimePicker.Font.Style auf Kursiv in Delphi 5

var 
    DatEdit : TDateTimePicker; 
begin 
    //I know Canvas is a stupid name for TPanel 
    DatEdit:=TDateTimePicker.Create(Canvas); 

    DatEdit.OnEnter := CtrlInputProc; 
    DatEdit.OnExit := CtrlExitProc; 
    DatEdit.Enabled := false; 
    DatEdit.Font.Style := DatEdit.Font.Style + [fsItalic]; //this line creates an exception 
    DatEdit.Parent := Canvas; 

end; 

Und jedes Mal, Code ausführt letzte Zeile, eine EInvalidOperation Ausnahme mit einer Meldung ausgelöst wird:

„Control” has no parent window. 

Ist das Delphi 5-Funktion, oder ich tue etwas falsch ?

Antwort

7

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.

+0

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

+0

BTW: Der Name "Canvas" wird höchstwahrscheinlich ersetzt werden. – smok1

+0

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