Question

Is it possible to set TDateTimePicker’s font to italic? I am doing it in this code

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;

And every time code executes last line, an EInvalidOperation exception is thrown with a message:

„Control” has no parent window.

Is this Delphi 5 feature, or am I doing something wrong?

Was it helpful?

Solution

Yes, you are doing something wrong. :)

Some aspects of a window based control require that the control be placed on it's container window. This usually reflects some requirement in the underlying Window Class itself (not the VCL class, but the MS Windows window object representing the control).

In this case, simply move your assignment of the Parent property so that it occurs BEFORE you attempt to change the Font.Style :

  DatEdit.OnEnter := CtrlInputProc;
  DatEdit.OnExit := CtrlExitProc;
  DatEdit.Enabled := false;
  DatEdit.Parent := Canvas;
  DatEdit.Font.Style := DatEdit.Font.Style + [fsItalic];

I don't know if the font can be successfully set to italic in this way or not, but this should at least address your exception.

UPDATE: I have confirmed that the font can be made italic in this way, as long as you have first set the control Parent. (I used Delphi 2009 ,but I'd be surprised if it didn't work in Delphi 5)

FYI: I would strongly recommend a different choice of name for that "Canvas" panel control.

Addendum: -------

It is the call to InvalidateRect() in the CMFontChanged() message handler that requires a Window Handle (which in turn requires that the control be parented).

If you absolutely need to be able to set the Parent after modifying the Font, you could derive your own control class from TDateTimePicker and implement a response to the CMFontChanged() message that suppresses the inherited behaviour unless the control is parented:

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;

Note that the AdjustHeight() procedure is reproduced from a private method of TDateTimePicker. If you are only changing the Font.Style you may not need to reproduce this code and can remove it and the call to it, but if you alter other properties of the Font then this should ensure that the control is correctly sized.

When you call inherited the private AdjustHeight() mechanism is invoked so there is no need to call the local copy of that procedure in that case.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top