在Delphi 5中将TDateTimePicker.Font.Style设置为斜体时出错

smo*_*ok1 1 delphi vcl dynamic-controls delphi-5

是否可以将TDateTimePicker的字体设置为斜体?我在这段代码中这样做

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;
Run Code Online (Sandbox Code Playgroud)

每次代码执行最后一行时,都会抛出一个带有消息的EInvalidOperation异常:

„Control” has no parent window.
Run Code Online (Sandbox Code Playgroud)

这是Delphi 5的功能,还是我做错了什么?

Del*_*ics 7

是的,你做错了什么.:)

基于窗口的控件的某些方面要求将控件放在其容器窗口上.这通常反映了底层Window类本身的一些要求(不是VCL类,而是表示控件的MS Windows窗口对象).

在这种情况下,只需移动Parent属性的赋值,使其在您尝试更改Font.Style之前发生:

  DatEdit.OnEnter := CtrlInputProc;
  DatEdit.OnExit := CtrlExitProc;
  DatEdit.Enabled := false;
  DatEdit.Parent := Canvas;
  DatEdit.Font.Style := DatEdit.Font.Style + [fsItalic];
Run Code Online (Sandbox Code Playgroud)

我不知道是否可以通过这种方式将字体成功设置为斜体,但这至少应该解决您的异常问题.

更新:我已经确认,只要您首先设置控件Parent,就可以以这种方式将字体设为斜体.(我使用的是Delphi 2009,但如果它在Delphi 5中不起作用,我会感到惊讶)

仅供参考:我强烈建议为"Canvas"面板控件选择不同的名称.

附录:-------

它是在CMFontChanged()消息处理程序中调用InvalidateRect(),该处理程序需要一个窗口句柄(这又需要控件成为父级).

如果您修改Font 之后绝对需要能够设置Parent ,则可以从TDateTimePicker派生自己的控件类,并实现对CMFontChanged()消息的响应,该消息禁止继承行为,除非控件是父级:

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;
Run Code Online (Sandbox Code Playgroud)

请注意,AdjustHeight()过程是从TDateTimePicker私有方法重现的.如果您只是更改Font.Style,您可能不需要重现此代码并可以删除它并调用它,但如果您更改Font的其他属性,那么这应该确保控件的大小正确.

当您调用inherited时,将调用私有的AdjustHeight()机制,因此在这种情况下无需调用该过程的本地副本.