Delphi 使IDE崩溃的新自定义组件
这是我第一次尝试创建一个组件,我想我应该从一个非常基本的LED(灯泡而不是文本)开始,在阅读了几篇文章后,我想到了以下代码(这是可行的),我关闭了IDE(XE10.1更新2)当尝试在一个新的空白应用程序中使用该组件时,IDE在添加控件时崩溃,任何人都可以帮助:Delphi 使IDE崩溃的新自定义组件,delphi,crash,ide,components,Delphi,Crash,Ide,Components,这是我第一次尝试创建一个组件,我想我应该从一个非常基本的LED(灯泡而不是文本)开始,在阅读了几篇文章后,我想到了以下代码(这是可行的),我关闭了IDE(XE10.1更新2)当尝试在一个新的空白应用程序中使用该组件时,IDE在添加控件时崩溃,任何人都可以帮助: unit ZaxLED; interface uses Windows, Messages, Controls, Forms, Graphics, ExtCtrls, Classes, math; type TZaxLED
unit ZaxLED;
interface
uses
Windows, Messages, Controls, Forms, Graphics, ExtCtrls, Classes, math;
type
TZaxLED = class(TGraphicControl)
private
{ Private declarations }
FColorOn: Tcolor;
FColorOff: Tcolor;
Color: Tcolor;
FStatus: Boolean;
FOnChange: TNotifyEvent;
procedure SetColorOn(Value: Tcolor);
procedure SetColorOff(Value: Tcolor);
function GetStatus: Boolean;
procedure SetStatus(Value: Boolean);
protected
{ Protected declarations }
procedure Paint; override;
public
{ Public declarations }
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
procedure SetBounds(ALeft, ATop, AWidth, AHeight: Integer); override;
published
{ Published declarations }
property width default 17;
property height default 17;
property Align;
property Anchors;
property Constraints;
property ColorOn: Tcolor read FColorOn write SetColorOn default clLime;
property ColorOff: Tcolor read FColorOff write SetColorOff default clGray;
property Status: Boolean read GetStatus write SetStatus default True;
property OnChange: TNotifyEvent read FOnChange write FOnChange;
end;
procedure Register;
implementation
procedure Register;
begin
RegisterComponents('Samples', [TZaxLED]);
end;
{ TZaxLED }
constructor TZaxLED.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
width := 17;
height := 17;
ColorOn := clLime;
ColorOff := clGray;
Status := False;
Color := ColorOff;
end;
destructor TZaxLED.Destroy;
begin
inherited Destroy;
end;
function TZaxLED.GetStatus: Boolean;
begin
Result := FStatus;
end;
procedure TZaxLED.Paint;
var
Radius, xCenter, YCenter: Integer;
begin
if csDesigning in ComponentState then
begin
Canvas.Pen.Style := psDot;
Canvas.Brush.Style := bsClear;
Canvas.Rectangle(ClientRect);
end;
Canvas.Brush.Color := Color;
Radius := Floor(width / 2) - 2;
xCenter := Floor(width / 2);
YCenter := Floor(height / 2);
Canvas.Ellipse(xCenter - Radius, YCenter - Radius, xCenter + Radius,
YCenter + Radius);
end;
procedure TZaxLED.SetBounds(ALeft, ATop, AWidth, AHeight: Integer);
begin
if Autosize and (Align in [alNone, alCustom]) then
inherited SetBounds(ALeft, ATop, width, height)
else
inherited SetBounds(ALeft, ATop, AWidth, AHeight);
end;
procedure TZaxLED.SetColorOff(Value: Tcolor);
begin
FColorOff := Value;
if not Status then
ColorOff := Value;
end;
procedure TZaxLED.SetColorOn(Value: Tcolor);
begin
FColorOn := Value;
if Status then
ColorOn := Value;
end;
procedure TZaxLED.SetStatus(Value: Boolean);
begin
if Value <> FStatus then
begin
FStatus := Value;
if FStatus then
Color := ColorOn
else
Color := ColorOff;
if Assigned(FOnChange) then
FOnChange(Self);
end;
end;
end.
让我们考虑这个代码:
procedure TZaxLED.SetColorOff(Value: Tcolor);
begin
FColorOff := Value;
if not Status then
ColorOff := Value;
end;
属性
ColorOff
的赋值将调用SetColorOff
方法。这将再次分配一个ColorOff
属性。因为没有办法打破这个分配周期,所有的事情都会很快以堆栈溢出而告终。我发现您的代码有很多问题
- 您的
子句需要清理。不要在实际不使用的单元上创建依赖项。仅由组件内部代码使用的单元应移至uses
部分的实现
子句。使用
部分的接口
子句应仅指满足公共接口直接使用的类型/引用所需的单元uses
- 当已有继承的
属性时,将声明Color
数据成员。此数据成员是多余和不必要的,因为其唯一目的是将所选的Color
颜色从状态
传送到SetStatus()
,这是不必要的,因为Paint()
可以(并且应该)直接确定该颜色值Paint()
属性用Status
值True声明,但该属性在构造函数中初始化为Falsedefault
和ColorOn
属性设置程序递归调用自己,而不是触发重新绘制以便显示新的状态图像ColorOff
属性设置程序也未触发重新绘制状态
unit ZaxLED;
interface
uses
Classes, Controls, Graphics;
type
TZaxLED = class(TGraphicControl)
private
{ Private declarations }
FColorOn: TColor;
FColorOff: TColor;
FStatus: Boolean;
FOnChange: TNotifyEvent;
procedure SetColorOn(Value: TColor);
procedure SetColorOff(Value: TColor);
procedure SetStatus(Value: Boolean);
protected
{ Protected declarations }
procedure Paint; override;
public
{ Public declarations }
constructor Create(AOwner: TComponent); override;
procedure SetBounds(ALeft, ATop, AWidth, AHeight: Integer); override;
published
{ Published declarations }
property Width default 17;
property Height default 17;
property Align;
property Anchors;
property Constraints;
property ColorOn: TColor read FColorOn write SetColorOn default clLime;
property ColorOff: TColor read FColorOff write SetColorOff default clGray;
property Status: Boolean read FStatus write SetStatus default False;
property OnChange: TNotifyEvent read FOnChange write FOnChange;
end;
procedure Register;
implementation
uses
Math;
procedure Register;
begin
RegisterComponents('Samples', [TZaxLED]);
end;
{ TZaxLED }
constructor TZaxLED.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
FColorOn := clLime;
FColorOff := clGray;
FStatus := False;
Width := 17;
Height := 17;
end;
procedure TZaxLED.Paint;
var
Radius, xCenter, YCenter: Integer;
begin
if csDesigning in ComponentState then
begin
Canvas.Pen.Style := psDot;
Canvas.Brush.Style := bsClear;
Canvas.Rectangle(ClientRect);
end;
if FStatus then
Canvas.Brush.Color := FColorOn
else
Canvas.Brush.Color := FColorOff;
Radius := Floor(Width / 2) - 2;
xCenter := Floor(Width / 2);
YCenter := Floor(Height / 2);
Canvas.Ellipse(xCenter - Radius, YCenter - Radius, xCenter + Radius, YCenter + Radius);
end;
procedure TZaxLED.SetBounds(ALeft, ATop, AWidth, AHeight: Integer);
begin
if AutoSize and (Align in [alNone, alCustom]) then
begin
AWidth := Width;
AHeight:= Height;
end;
inherited SetBounds(ALeft, ATop, AWidth, AHeight);
end;
procedure TZaxLED.SetColorOff(Value: TColor);
begin
if FColorOff <> Value then
begin
FColorOff := Value;
if not FStatus then Invalidate;
end;
end;
procedure TZaxLED.SetColorOn(Value: TColor);
begin
if FColorOn <> Value then
begin
FColorOn := Value;
if FStatus then Invalidate;
end;
end;
procedure TZaxLED.SetStatus(Value: Boolean);
begin
if Value <> FStatus then
begin
FStatus := Value;
Invalidate;
if Assigned(FOnChange) then
FOnChange(Self);
end;
end;
end.
单元ZaxLED;
接口
使用
类、控件、图形;
类型
Tzaxld=类(Tgraphic控件)
私有的
{私有声明}
FColorOn:TColor;
FColorOff:TColor;
FStatus:布尔型;
FOnChange:TNotifyEvent;
程序SetColorOn(值:TColor);
程序设置颜色关闭(值:t颜色);
程序SetStatus(值:布尔值);
受保护的
{受保护的声明}
程序漆;推翻
公众的
{公开声明}
构造函数创建(AOwner:TComponent);推翻
过程设置边界(ALeft、top、AWidth、ahheight:Integer);推翻
出版
{已发布声明}
属性宽度默认值17;
属性高度默认值17;
属性对齐;
地产锚;
财产限制;
属性ColorOn:TColor read FColorOn write SetColorOn default clLime;
属性ColorOff:t颜色读取FColorOff写入设置ColorOff默认值clGray;
属性状态:布尔读取FStatus写入SetStatus default False;
属性OnChange:TNotifyEvent read FOnChange write FOnChange;
结束;
程序登记册;
实施
使用
数学;
程序登记册;
开始
注册表组件('Samples',[TZaxLED]);
结束;
{TZaxLED}
构造函数TZaxLED.Create(所有者:TComponent);
开始
继承的创建(AOOwner);
FColorOn:=clLime;
FColorOff:=clGray;
FStatus:=假;
宽度:=17;
高度:=17;
结束;
程序TZaxLED.油漆;
变量
半径,X中心,Y中心:整数;
开始
如果csDesigning处于组件状态,则
开始
Canvas.Pen.Style:=psDot;
Canvas.Brush.Style:=bsClear;
画布。矩形(ClientRect);
结束;
如果是这样的话
Canvas.Brush.Color:=FColorOn
其他的
Canvas.Brush.Color:=FColorOff;
半径:=地板(宽度/2)-2;
xCenter:=楼层(宽度/2);
中心:=楼层(高度/2);
椭圆(X中心-半径,Y中心-半径,X中心+半径,Y中心+半径);
结束;
过程TZaxLED.SetBounds(ALeft、top、AWidth、ahheight:整数);
开始
如果自动调整大小并(在[alNone,alCustom]中对齐),则
开始
宽度:=宽度;
ahheight:=高度;
结束;
继承的挫折(阿列夫特、顶、宽、高);
结束;
程序TZaxLED.SetColorOff(值:TColor);
开始
如果是FColorOff值,则
开始
FColorOff:=值;
如果不是FStatus,则无效;
结束;
结束;
程序TZaxLED.SetColorOn(值:TColor);
开始
如果是FColorOn值,则
开始
FColorOn:=值;
如果是FStatus,则无效;
结束;
结束;
程序TZaxLED.SetStatus(值:布尔值);
开始
如果值为FStatus,则
开始
FStatus:=值;
使无效
如果指定(更改),则
改变(自我);
结束;
结束;
结束。
我取出了If-Then线路,但它仍然崩溃了您是否更改了所有属性?它们都表现出相同的行为。在关闭IDE(去吃午饭)和启动新测试应用程序的IDE之间,没有任何更改,我已卸载该软件包并通过组件菜单重新安装,但仍然相同(快速松开头发)刚刚更新了代码,似乎在工作,但LED在设计或运行时没有改变颜色,我是否需要在所有更改(颜色等)中执行绘制功能,因为您必须在设置状态后重新绘制控件。例如,调用Invalidate
。
unit ZaxLED;
interface
uses
Classes, Controls, Graphics;
type
TZaxLED = class(TGraphicControl)
private
{ Private declarations }
FColorOn: TColor;
FColorOff: TColor;
FStatus: Boolean;
FOnChange: TNotifyEvent;
procedure SetColorOn(Value: TColor);
procedure SetColorOff(Value: TColor);
procedure SetStatus(Value: Boolean);
protected
{ Protected declarations }
procedure Paint; override;
public
{ Public declarations }
constructor Create(AOwner: TComponent); override;
procedure SetBounds(ALeft, ATop, AWidth, AHeight: Integer); override;
published
{ Published declarations }
property Width default 17;
property Height default 17;
property Align;
property Anchors;
property Constraints;
property ColorOn: TColor read FColorOn write SetColorOn default clLime;
property ColorOff: TColor read FColorOff write SetColorOff default clGray;
property Status: Boolean read FStatus write SetStatus default False;
property OnChange: TNotifyEvent read FOnChange write FOnChange;
end;
procedure Register;
implementation
uses
Math;
procedure Register;
begin
RegisterComponents('Samples', [TZaxLED]);
end;
{ TZaxLED }
constructor TZaxLED.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
FColorOn := clLime;
FColorOff := clGray;
FStatus := False;
Width := 17;
Height := 17;
end;
procedure TZaxLED.Paint;
var
Radius, xCenter, YCenter: Integer;
begin
if csDesigning in ComponentState then
begin
Canvas.Pen.Style := psDot;
Canvas.Brush.Style := bsClear;
Canvas.Rectangle(ClientRect);
end;
if FStatus then
Canvas.Brush.Color := FColorOn
else
Canvas.Brush.Color := FColorOff;
Radius := Floor(Width / 2) - 2;
xCenter := Floor(Width / 2);
YCenter := Floor(Height / 2);
Canvas.Ellipse(xCenter - Radius, YCenter - Radius, xCenter + Radius, YCenter + Radius);
end;
procedure TZaxLED.SetBounds(ALeft, ATop, AWidth, AHeight: Integer);
begin
if AutoSize and (Align in [alNone, alCustom]) then
begin
AWidth := Width;
AHeight:= Height;
end;
inherited SetBounds(ALeft, ATop, AWidth, AHeight);
end;
procedure TZaxLED.SetColorOff(Value: TColor);
begin
if FColorOff <> Value then
begin
FColorOff := Value;
if not FStatus then Invalidate;
end;
end;
procedure TZaxLED.SetColorOn(Value: TColor);
begin
if FColorOn <> Value then
begin
FColorOn := Value;
if FStatus then Invalidate;
end;
end;
procedure TZaxLED.SetStatus(Value: Boolean);
begin
if Value <> FStatus then
begin
FStatus := Value;
Invalidate;
if Assigned(FOnChange) then
FOnChange(Self);
end;
end;
end.