【发布时间】:2019-11-29 15:11:20
【问题描述】:
我想创建一个可以自动调整其宽度的复选框,就像 TLabel 一样。
UNIT cvCheckBox;
{ It incercepts CMTextChanged where it recomputes the new Width}
INTERFACE
USES
Winapi.Windows, Winapi.Messages, System.Classes, Vcl.Graphics, Vcl.Controls, Vcl.StdCtrls;
TYPE
TcCheckBox = class(TCheckBox)
private
FAutoSize: Boolean;
procedure AdjustBounds;
procedure setAutoSize(b: Boolean); reintroduce;
procedure CMFontChanged(var Message: TMessage); message CM_FONTCHANGED;
procedure CMTextChanged(var Message: TMessage); message CM_TEXTCHANGED;
protected
procedure Loaded; override;
public
constructor Create(AOwner: TComponent); override;
published
//property Caption read GetText write SetText;
property AutoSize: Boolean read FAutoSize write setAutoSize stored TRUE;
end;
IMPLEMENTATION
CONST
SysCheckWidth: Integer = 21; // In theory this can be obtained from the "system"
constructor TcCheckBox.Create(AOwner : TComponent);
begin
inherited Create(AOwner);
FAutoSize:= TRUE;
end;
procedure TcCheckBox.AdjustBounds;
VAR
DC: HDC;
Canvas: TCanvas;
begin
if not (csReading in ComponentState) and FAutoSize then
begin
// this caused the problem [solution provided by Dima]
if HandleAllocated then // Deals with the missing parent during Creation
begin
// We need a canvas but this control has none. So we need to "produce" one.
Canvas := TCanvas.Create;
DC := GetDC(Handle);
TRY
Canvas.Handle := DC;
Canvas.Font := Font;
Width := Canvas.TextWidth(Caption) + SysCheckWidth + 4;
Canvas.Handle := 0;
FINALLY
ReleaseDC(Handle, DC);
Canvas.Free;
END;
end;
end;
end;
procedure TcCheckBox.setAutoSize(b: Boolean);
begin
if FAutoSize <> b then
begin
FAutoSize := b;
if b then AdjustBounds;
end;
end;
procedure TcCheckBox.CMTextChanged(var Message:TMessage);
begin
Invalidate;
AdjustBounds;
end;
procedure TcCheckBox.CMFontChanged(var Message:TMessage);
begin
inherited;
if AutoSize
then AdjustBounds;
end;
procedure TcCheckBox.Loaded;
begin
inherited Loaded;
AdjustBounds;
end;
end.
但是我有一个问题。放置在 PageControl 的非活动选项卡中的复选框不会自动重新计算其大小。换句话说,如果我有两个包含复选框的选项卡,则在应用程序启动时,只有当前打开的选项卡中的复选框会正确调整大小。当我单击另一个选项卡时,复选框将具有原始大小(在设计时设置的那个)。
我确实在程序启动时设置了整个表单的字体大小(在 Form Create 之后,使用 PostMessage(Self.Handle, MSG_LateInitialize) )。
procedure TForm5.FormCreate(Sender: TObject);
begin
PostMessage(Self.Handle, MSG_LateInitialize, 0, 0);
end;
procedure TForm5.LateInitialize(var message: TMessage);
begin
Font:= 22;
end;
为什么非活动标签中的复选框没有宣布字体已更改?
【问题讨论】:
-
显然,问题出在
AjustBounds方法的if HandleAllocated then。因为自然原因TPageControl(节省资源)不分配非活动页面,直到您选择适当的选项卡。您可以通过编译您的应用程序并调用放置在非活动页面上的MyCheckBox.HandleAllocated轻松检查它。这就是AdjustBounds方法无效的原因。 -
@Dima - 它奏效了。如果您发表评论作为答案,我会接受。
标签: delphi checkbox delphi-xe7 autoresize