I copied the source LabeledEdit example with a TBoundLabel in components I'm writing to attach a convenient label to. They work fine but I'm getting issues loading the .dfm form (seemingly when my component is on another such as a CategoryPanel):
Class TBoundLabel not found
object Form2: TForm2
Left = 0
Top = 0
Caption = 'Form2'
ClientHeight = 518
ClientWidth = 635
Color = clBtnFace
Font.Charset = DEFAULT_CHARSET
Font.Color = clWindowText
Font.Height = -11
Font.Name = 'Tahoma'
Font.Style = []
OldCreateOrder = False
PixelsPerInch = 96
TextHeight = 13
object CategoryPanelGroup1: TCategoryPanelGroup
Left = 0
Top = 70
Width = 635
Height = 448
VertScrollBar.Tracking = True
Align = alClient
HeaderFont.Charset = DEFAULT_CHARSET
HeaderFont.Color = clWindowText
HeaderFont.Height = -11
HeaderFont.Name = 'Tahoma'
HeaderFont.Style = []
TabOrder = 0
object CategoryPanel1: TCategoryPanel
Top = 0
Caption = 'CategoryPanel1'
TabOrder = 0
end
object CategoryPanel2: TCategoryPanel
Top = 200
Caption = 'CategoryPanel2'
TabOrder = 1
object SubLabel: TBoundLabel
Width = 78
Height = 13
Caption = 'LabelledCombo1'
end
object LabelledCombo1: TLabelledCombo
Left = 152
Top = 80
Width = 145
Height = 21
LabelRotulo.Width = 78
LabelRotulo.Height = 13
LabelRotulo.Caption = 'LabelledCombo1'
TabOrder = 0
end
end
end
object Panel1: TPanel
Left = 0
Top = 0
Width = 635
Height = 41
Align = alTop
Caption = 'Panel1'
TabOrder = 1
end
object ToolBar1: TToolBar
Left = 0
Top = 41
Width = 635
Height = 29
Caption = 'ToolBar1'
TabOrder = 2
end
end
Source for the LabelledCombo:
unit LabelledComboU;
interface
uses
WinApi.Windows,
WinApi.Messages,
System.SysUtils,
System.Math,
System.UITypes,
System.StrUtils,
System.Classes,
System.Types,
VCL.Forms,
VCL.ExtCtrls,
VCL.Controls,
VCL.Consts,
VCL.Dialogs,
VCL.ImgList,
VCL.Samples.Spin,
VCL.StdCtrls,
VCL.GraphUtil,
VCL.Graphics,
VCL.THemes,
VCL.Styles;
type
TLabelledCombo = class(TCustomComboBox)
private
FLabel: TBoundLabel;
FLabelPosition: TLabelPosition;
FLabelSpacing: Integer;
procedure SetLabelPosition(const Value: TLabelPosition);
procedure SetLabelSpacing(const Value: integer);
protected
procedure SetParent(AParent: TWinControl); override;
procedure Notification(AComponent: TComponent; Operation: TOperation); override;
procedure SetName(const Value: TComponentName); override;
procedure CMVisiblechanged(var Message: TMessage);
message CM_VISIBLECHANGED;
procedure CMEnabledchanged(var Message: TMessage);
message CM_ENABLEDCHANGED;
procedure CMBidimodechanged(var Message: TMessage);
message CM_BIDIMODECHANGED;
public
constructor Create(AOwner: TComponent); override;
procedure SetBounds(ALeft: Integer; ATop: Integer; AWidth: Integer; AHeight: Integer); override;
procedure SetupInternalLabel;
published
property LabelRotulo: TBoundLabel read FLabel;
property LabelPosition: TLabelPosition read FLabelPosition write SetLabelPosition default lpAbove;
property LabelSpacing: Integer read FLabelSpacing write SetLabelSpacing default 3;
property Align;
property AutoComplete default True;
property AutoCompleteDelay default 500;
property AutoDropDown default False;
property AutoCloseUp default False;
property BevelEdges;
property BevelInner;
property BevelKind default bkNone;
property BevelOuter;
property Style; { Must be published before Items }
property Anchors;
property BiDiMode;
property CharCase;
property Color;
property Constraints;
property Ctl3D;
property DoubleBuffered;
property DragCursor;
property DragKind;
property DragMode;
property DropDownCount;
property Enabled;
property ExtendedUI default False;
property Font;
property ImeMode;
property ImeName;
property ItemHeight;
property ItemIndex default -1;
property MaxLength;
property ParentBiDiMode;
property ParentColor;
property ParentCtl3D;
property ParentDoubleBuffered;
property ParentFont;
property ParentShowHint;
property PopupMenu;
property ShowHint;
property Sorted;
property TabOrder;
property TabStop;
property Text;
property TextHint;
property Touch;
property Visible;
property StyleElements;
property StyleName;
property OnChange;
property OnClick;
property OnCloseUp;
property OnContextPopup;
property OnDblClick;
property OnDragDrop;
property OnDragOver;
property OnDrawItem;
property OnDropDown;
property OnEndDock;
property OnEndDrag;
property OnEnter;
property OnExit;
property OnGesture;
property OnKeyDown;
property OnKeyPress;
property OnKeyUp;
property OnMeasureItem;
property OnMouseEnter;
property OnMouseLeave;
property OnSelect;
property OnStartDock;
property OnStartDrag;
property Items; { Must be published after OnMeasureItem }
end;
implementation
{ TLabelledCombo }
procedure TLabelledCombo.CMBidimodechanged(var Message: TMessage);
begin
if FLabel <> nil then
FLabel.BiDiMode := BiDiMode;
end;
procedure TLabelledCombo.CMEnabledchanged(var Message: TMessage);
begin
inherited;
if FLabel <> nil then
FLabel.Enabled := Enabled;
end;
procedure TLabelledCombo.CMVisiblechanged(var Message: TMessage);
begin
inherited;
if FLabel <> nil then
FLabel.Visible := Visible;
end;
constructor TLabelledCombo.Create(AOwner: TComponent);
begin
inherited;
FLabelPosition := lpAbove;
FLabelSpacing := 3;
SetupInternalLabel;
end;
procedure TLabelledCombo.Notification(AComponent: TComponent;
Operation: TOperation);
begin
inherited Notification(AComponent, Operation);
if (AComponent = FLabel) and (Operation = opRemove) then
FLabel := nil;
end;
procedure TLabelledCombo.SetBounds(ALeft, ATop, AWidth, AHeight: Integer);
begin
inherited SetBounds(ALeft, ATop, AWidth, AHeight);
SetLabelPosition(FLabelPosition);
end;
procedure TLabelledCombo.SetLabelPosition(const Value: TLabelPosition);
var
P: TPoint;
begin
if FLabel = nil then Exit;
FLabelPosition := Value;
case Value of
lpAbove:
P := Point(Left, Top - FLabel.Height - FLabelSpacing);
lpBelow:
P := Point(Left, Top + Height + FLabelSpacing);
lpLeft : P := Point(Left - FLabel.Width - FLabelSpacing,
Top + ((Height - FLabel.Height) div 2));
lpRight: P := Point(Left + Width + FLabelSpacing,
Top + ((Height - FLabel.Height) div 2));
end;
FLabel.SetBounds(P.x, P.y, FLabel.Width, FLabel.Height);
end;
procedure TLabelledCombo.SetLabelSpacing(const Value: integer);
begin
FLabelSpacing := Value;
SetLabelPosition(FLabelPosition);
end;
procedure TLabelledCombo.SetName(const Value: TComponentName);
var
LClearText: Boolean;
begin
if (csDesigning in ComponentState) and (FLabel <> nil) and
((Flabel.GetTextLen = 0) or
(CompareText(FLabel.Caption, Name) = 0)) then
FLabel.Caption := Value;
LClearText := (csDesigning in ComponentState) and (Text = '');
inherited SetName(Value);
if LClearText then
Text := '';
end;
procedure TLabelledCombo.SetParent(AParent: TWinControl);
begin
inherited SetParent(AParent);
if FLabel = nil then exit;
FLabel.Parent := AParent;
FLabel.Visible := True;
end;
procedure TLabelledCombo.SetupInternalLabel;
begin
if Assigned(FLabel) then exit;
FLabel := TBoundLabel.Create(Self);
FLabel.FreeNotification(Self);
// FLabel.FocusControl := Self;
end;
end.
This is the barest test which reproduces the problem, a LabelledCombo on a CategoryPanel. (On a form I am not getting grief.)
I tried deleting the reference to Sublabel and resaving the .DFM but it comes back again. I can't see what to fix: the source is identical to that of TLabeledEdit except that TBoundLabel is not in my Unit. Do I need to copy the source of that too into my component unit?
Mike
The problem is that you are trying to re-use TBoundLabel - which has been designed specifically to be used from within TCustomLabeledEdit only. Using it elsewhere will lead to unwanted side effects. In the code below (taken from VCL.ExtCtrls.pas) you can easily see that TBoundLabel is basically bound to TCustomLabeledEdit.
If that is a smart design, is a different question though.