是的,你做错了什么。 :)
基于窗口的控件的某些方面要求将控件放置在它的容器窗口上。这通常反映了底层 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];
我不知道字体是否可以通过这种方式成功设置为斜体,但这至少应该解决您的异常。
更新:我已经确认可以通过这种方式将字体设置为斜体,只要你先设置了控件Parent。 (我使用的是 Delphi 2009,但如果它在 Delphi 5 中不起作用,我会感到惊讶)
仅供参考:我会强烈为“画布”面板控件推荐一个不同的名称选择。
附录:--------
在 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;
请注意,AdjustHeight() 过程是从 TDateTimePicker 的 private 方法复制而来的。如果您只更改 Font.Style 您可能不需要重现此代码并且可以删除它和对它的调用,但是如果您更改 Font 的其他属性那么这应该确保控件的大小正确。
当您调用 inherited 时,将调用私有 AdjustHeight() 机制,因此在这种情况下无需调用该过程的本地副本。