创建类似TLabeledEdit的TCombobox与TLabel的复合控件的问题? (200分)

  • 主题发起人 主题发起人 阿韬
  • 开始时间 开始时间

阿韬

Unregistered / Unconfirmed
GUEST, unregistred user!
看了TLabeledEdit控件,它一个TLabel和TEdit组合起来的,我想创建一个TCombobox和
TEdit组合起来的控件,不知道该怎么进行下去。我写了代码如下,其中
FBoundLabel.FocusControl := Self这句编译通不过,如果注释掉这句,编译通过,但是
将此控件放到form上的时候看不到Label。
哪位大虾指点一下啊。。。。

TLabelPosition = (lpAbove, lpBelow, lpLeft, lpRight);
TLableCombobox = class(TCombobox)
private
FBoundLabel: TBoundLabel;
FLabelSpacing: Integer;
FShowLabel: Boolean;
FLabelPosition: TLabelPosition;
procedure SetLabelPosition(const Value: TLabelPosition);
procedure SetLabelSpacing(const Value: Integer);
procedure SetShowLabel(Value: Boolean);
protected
public
constructor Create(AOwner: TComponent); override;
property BoundLabel: TBoundLabel read FBoundLabel;
procedure SetBounds(ALeft: Integer; ATop: Integer; AWidth: Integer; AHeight: Integer); override;
procedure SetupInternalLabel;
property LabelSpacing: Integer read FLabelSpacing write SetLabelSpacing;
property LabelPosition: TLabelPosition read FLabelPosition write SetLabelPosition;
published
property ShowLabel: Boolean read FShowLabel write SetShowLabel default True;
end;


//------------------------TLableCombobox---------------------------

procedure TLableCombobox.SetShowLabel(Value: Boolean);
begin
FShowLabel := Value;
FBoundLabel.Visible := FShowLabel;
end;

procedure TLableCombobox.SetLabelSpacing(const Value: Integer);
begin
FLabelSpacing := Value;
SetLabelPosition(FLabelPosition);
end;

procedure TLableCombobox.SetLabelPosition(const Value: TLabelPosition);
var
P: TPoint;
begin
if FBoundLabel = nil then exit;
FLabelPosition := Value;
case Value of
lpAbove: P := Point(Left, Top - FBoundLabel.Height - FLabelSpacing);
lpBelow: P := Point(Left, Top + Height + FLabelSpacing);
lpLeft: P := Point(Left - FBoundLabel.Width - FLabelSpacing,
Top + ((Height - FBoundLabel.Height) div 2));
lpRight: P := Point(Left + Width + FLabelSpacing,
Top + ((Height - FBoundLabel.Height) div 2));
end;
FBoundLabel.SetBounds(P.x, P.y, FBoundLabel.Width, FBoundLabel.Height);
end;

procedure TLableCombobox.SetupInternalLabel;
begin
if Assigned(FBoundLabel) then exit;
FBoundLabel := TBoundLabel.Create(Self);
FBoundLabel.FreeNotification(Self);
FBoundLabel.FocusControl := Self; [red]//此处编译时候报错,提示Undeclared identifier: 'FocusControl '[/red]
end;

procedure TLableCombobox.SetBounds(ALeft, ATop, AWidth, AHeight: Integer);
begin
inherited SetBounds(ALeft, ATop, AWidth, AHeight);
SetLabelPosition(FLabelPosition);
end;

constructor TLableCombobox.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
FShowLabel := True;
FLabelPosition := lpAbove;
FLabelSpacing := 3;
SetupInternalLabel;
end;

 
我也遇到过同样的问题, 不知你用的Delphi是哪一版本的?
 
我用的delphi6,这个FBoundLabel.FocusControl 应该是有的。可是就是编译不通过。
 
我现在用的是Delphi5, 我也看了TLabeledEdit控件, 在delphi6中有一个
SetSubComponent之类的函数将FBoundLabel设为子组件, FocusControl的作用是
在按下Label上的加速键时定位,编译不通过先屏蔽试试。
要看到Label必须设置它的Parent属性。
 
TBoundLabel没有公布FocusControl属性要自已公布
TMyBoundLabel = class(TBoundLabel)
published
property FocusControl;
end;

unit MylabelEdit;

interface

uses
Windows, Messages, SysUtils, Classes, StdCtrls, ExtCtrls, Controls;

type

TMyBoundLabel = class(TBoundLabel)
published
property FocusControl;
end;

TMylabelComboBox = class(TCustomComboBox)
private
FEditLabel: TMyBoundLabel;
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
{ Public declarations }
constructor Create(AOwner: TComponent); override;
procedure SetBounds(ALeft: Integer; ATop: Integer; AWidth: Integer; AHeight: Integer); override;
procedure SetupInternalLabel;
property ComboBoxLabel: TMyBoundLabel read FEditLabel;
property LabelPosition: TLabelPosition read FLabelPosition write SetLabelPosition;
property LabelSpacing: Integer read FLabelSpacing write SetLabelSpacing;
end;

TLabeledComboBox = class(TMylabelComboBox)
published
property Anchors;
property AutoSize;
property BevelEdges;
property BevelInner;
property BevelKind;
property BevelOuter;
property BiDiMode;
property CharCase;
property Color;
property Constraints;
property Ctl3D;
property DragCursor;
property DragKind;
property DragMode;
property ComboBoxLabel;
property Enabled;
property Font;
property ImeMode;
property ImeName;
property LabelPosition;
property LabelSpacing;
property MaxLength;
property ParentBiDiMode;
property ParentColor;
property ParentCtl3D;
property ParentFont;
property ParentShowHint;
property PopupMenu;
property ShowHint;
property TabOrder;
property TabStop;
property Text;
property Visible;
property OnChange;
property OnClick;
property OnContextPopup;
property OnDblClick;
property OnDragDrop;
property OnDragOver;
property OnEndDock;
property OnEndDrag;
property OnEnter;
property OnExit;
property OnKeyDown;
property OnKeyPress;
property OnKeyUp;
property OnMouseDown;
property OnMouseMove;
property OnMouseUp;
property OnStartDock;
property OnStartDrag;
end;

procedure Register;

implementation

procedure Register;
begin
RegisterComponents('Standard', [TLabeledComboBox]);
end;

{ TMylabelComboBox }

procedure TMylabelComboBox.CMBidimodechanged(var Message: TMessage);
begin
inherited;
FEditLabel.BiDiMode := BiDiMode;
end;

procedure TMylabelComboBox.CMEnabledchanged(var Message: TMessage);
begin
inherited;
FEditLabel.Enabled := Enabled;
end;

procedure TMylabelComboBox.CMVisiblechanged(var Message: TMessage);
begin
inherited;
FEditLabel.Visible := Visible;
end;

constructor TMylabelComboBox.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
FLabelPosition := lpAbove;
FLabelSpacing := 3;
SetupInternalLabel;
end;

procedure TMylabelComboBox.Notification(AComponent: TComponent;
Operation: TOperation);
begin
inherited Notification(AComponent, Operation);
if (AComponent = FEditLabel) and (Operation = opRemove) then
FEditLabel := nil;
end;

procedure TMylabelComboBox.SetBounds(ALeft, ATop, AWidth,
AHeight: Integer);
begin
inherited SetBounds(ALeft, ATop, AWidth, AHeight);
SetLabelPosition(FLabelPosition);
end;

procedure TMylabelComboBox.SetLabelPosition(const Value: TLabelPosition);
var
P: TPoint;
begin
if FEditLabel = nil then exit;
FLabelPosition := Value;
case Value of
lpAbove: P := Point(Left, Top - FEditLabel.Height - FLabelSpacing);
lpBelow: P := Point(Left, Top + Height + FLabelSpacing);
lpLeft : P := Point(Left - FEditLabel.Width - FLabelSpacing,
Top + ((Height - FEditLabel.Height) div 2));
lpRight: P := Point(Left + Width + FLabelSpacing,
Top + ((Height - FEditLabel.Height) div 2));
end;
FEditLabel.SetBounds(P.x, P.y, FEditLabel.Width, FEditLabel.Height);
end;

procedure TMylabelComboBox.SetLabelSpacing(const Value: Integer);
begin
FLabelSpacing := Value;
SetLabelPosition(FLabelPosition);
end;

procedure TMylabelComboBox.SetName(const Value: TComponentName);
begin
if (csDesigning in ComponentState) and ((FEditlabel.GetTextLen = 0) or
(CompareText(FEditLabel.Caption, Name) = 0)) then
FEditLabel.Caption := Value;
inherited SetName(Value);
if csDesigning in ComponentState then
Text := '';
end;

procedure TMylabelComboBox.SetParent(AParent: TWinControl);
begin
inherited SetParent(AParent);
if FEditLabel = nil then exit;
FEditLabel.Parent := AParent;
FEditLabel.Visible := True;
end;

procedure TMylabelComboBox.SetupInternalLabel;
begin
if Assigned(FEditLabel) then exit;
FEditLabel := TMyBoundLabel.Create(Self);
FEditLabel.FreeNotification(Self);
FEditLabel.FocusControl := Self;
end;

end.
 
lb_icesea79,按照你写的基本可以实现了。但是还有一个小问题。
我的这个控件命名为:
combox: TLableCombobox;

我在设计期间把combox的LabelPosition属性设置为lpLeft,运行的时候它的Label看不全
,只有看到前面2个字符。如果用代码设置它的LabelPosition为lpLeft就可以看到全部的
Label,请问这是为什么啊?
我跟踪发现第一次run的时候SetLabelPosition函数中的FBoundLabel.Width为0,所以
lpLeft: P := Point(Left - FBoundLabel.Width - FLabelSpacing,
Top + ((Height - FBoundLabel.Height) div 2));
执行后这个P.x 实际就是 Point(Left - 0 - FLabelSpacing,
Top + ((Height - FBoundLabel.Height) div 2));

如果用程序设置
combox.LabelPosition := lpLeft的时候,
这时候跟踪进去就可以看到FBoundLabel.Width的值不是0,所以P.x就计算对了,能够看到
Label。


 
to 阿韬
将TLabeledComboBox改为TLableCombobox就行了,
2.版本6.0没有你说的情况呀
 
lb_icesea79, 还是不行啊。我把我的整个代码贴出来吧。你帮我看看。多谢了。

TLabelPosition = (lpAbove, lpBelow, lpLeft, lpRight);

TMyBoundLabel = class(TBoundLabel)
published
property FocusControl;
end;

TLableCombobox = class(TCombobox)
private
FBoundLabel: TMyBoundLabel;
FLabelSpacing: Integer;
FShowLabel: Boolean;
FLabelPosition: TLabelPosition;
procedure SetLabelPosition(const Value: TLabelPosition);
procedure SetLabelSpacing(const Value: Integer);
procedure SetShowLabel(Value: Boolean);
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 LabelSpacing: Integer read FLabelSpacing write SetLabelSpacing;
property LabelPosition: TLabelPosition read FLabelPosition write SetLabelPosition;
property BoundLabel: TMyBoundLabel read FBoundLabel;
property ShowLabel: Boolean read FShowLabel write SetShowLabel default True;

end;



//------------------------TLableCombobox---------------------------

procedure TLableCombobox.SetShowLabel(Value: Boolean);
begin
FShowLabel := Value;
FBoundLabel.Visible := FShowLabel;
end;

procedure TLableCombobox.SetLabelSpacing(const Value: Integer);
begin
FLabelSpacing := Value;
SetLabelPosition(FLabelPosition);
end;

procedure TLableCombobox.SetLabelPosition(const Value: TLabelPosition);
var
P: TPoint;
begin
if FBoundLabel = nil then exit;
FLabelPosition := Value;
case Value of
lpAbove: P := Point(Left, Top - FBoundLabel.Height - FLabelSpacing);
lpBelow: P := Point(Left, Top + Height + FLabelSpacing);
lpLeft: P := Point(Left - FBoundLabel.Width - FLabelSpacing,
Top + ((Height - FBoundLabel.Height) div 2));
lpRight: P := Point(Left + Width + FLabelSpacing,
Top + ((Height - FBoundLabel.Height) div 2));
end;
FBoundLabel.SetBounds(P.x, P.y, FBoundLabel.Width, FBoundLabel.Height);
end;

procedure TLableCombobox.SetupInternalLabel;
begin
if Assigned(FBoundLabel) then exit;
FBoundLabel := TMyBoundLabel.Create(Self);
FBoundLabel.FreeNotification(Self);
FBoundLabel.FocusControl := Self;
SetLabelSpacing(FLabelSpacing);
end;

procedure TLableCombobox.SetBounds(ALeft, ATop, AWidth, AHeight: Integer);
begin
inherited SetBounds(ALeft, ATop, AWidth, AHeight);
SetLabelPosition(FLabelPosition);
end;

procedure TLableCombobox.SetName(const Value: TComponentName);
begin
if (csDesigning in ComponentState) and ((FBoundLabel.GetTextLen = 0) or
(CompareText(FBoundLabel.Caption, Name) = 0)) then
FBoundLabel.Caption := Value;
inherited SetName(Value);
if csDesigning in ComponentState then
Text := '';
end;

procedure TLableCombobox.CMBidimodechanged(var Message: TMessage);
begin
inherited;
FBoundLabel.BiDiMode := BiDiMode;
end;

procedure TLableCombobox.CMEnabledchanged(var Message: TMessage);
begin
inherited;
FBoundLabel.Enabled := Enabled;
end;

procedure TLableCombobox.CMVisiblechanged(var Message: TMessage);
begin
inherited;
FBoundLabel.Visible := FShowLabel;
end;

procedure TLableCombobox.Notification(AComponent: TComponent;
Operation: TOperation);
begin
inherited Notification(AComponent, Operation);
if (AComponent = FBoundLabel) and (Operation = opRemove) then
FBoundLabel := nil;
end;

procedure TLableCombobox.SetParent(AParent: TWinControl);
begin
inherited SetParent(AParent);
if FBoundLabel = nil then exit;
FBoundLabel.Parent := AParent;
FBoundLabel.Visible := FShowLabel;
end;

constructor TLableCombobox.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
FShowLabel := True;
FLabelPosition := lpAbove;
FLabelSpacing := 3;
SetupInternalLabel;
end;
 
to阿韬:
可以把你的东西发到我信箱里吗?
xdengni0326@sina.con.cn
谢谢!
 
to阿韬:
我没有写过组件,给我一份好吗?谢谢!
 
老兄:帮忙呀
 
to阿韬:
我没有写过组件,给我一份好吗?谢谢!
wqt0318@sohu.com
 
我的代码都贴出来了啊。把这个存成一个pas文件就可以了啊。

哪位大虾指点我一下啊。
 
有没有人帮我啊。。。。
 
还是没有解决这个小问题,不过主要部分是解决了。多谢了。散分。
 
后退
顶部