控件与动态创建控件问题! (10分)

  • 主题发起人 desertsmoke
  • 开始时间
D

desertsmoke

Unregistered / Unconfirmed
GUEST, unregistred user!
程序中动态创建控件,如一中所示。自己做了两个控件:TRJ和TNewRJ,TNewRJ是从
TRJ派生来的,只是在TRJ的基础上加了一个标签TLabel,在接口部分的Uses中引用RJ
后动态创建控件一切正常,但是引用NewRJ后,就会产生错误,如下:
---------------------------
Debugger Exception Notification
---------------------------
Project Project1.exe raised exception class EClassNotFound with message
'Class TLabel not found'. Process stopped. Use Step or Run to continue.
---------------------------
OK Help
---------------------------
也就是说FindClass('TLabel')失败!
哪位大虾知道这是怎么回事,怎么引起的,如何解决?

------------------------------------------------------------------------------
一、动态创建控件单元

unit Unit1;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, ExtCtrls, ROUNDLED, buttons, ComCtrls, DB, DBClient,
MConnect, SConnect, RJ, NewRJ;

const
TCClass :Array[1..3] of TPersistentClass=(TImage, TLabel, TShape);
type
TForm1 = class(TForm)
Button1: TButton;
procedure Button1Click(Sender: TObject);
procedure FormCreate(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;

var
Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
var
NewControl:TObject;
begin
NewControl:= (TComponentClass(FindClass('TLabel'))).Create(Self);//这句失败!!!
(NewControl as Tlabel).Parent := self;
NewControl:= (TComponentClass(FindClass('TRJ'))).Create(Self);
(NewControl as TRJ).Parent := self;
......

end;

procedure TForm1.FormCreate(Sender: TObject);
begin
RegisterClasses(TCClass); //可能这里就是失败的!
end;

end.

********************************************************************
二、控件单元

unit NewRJ;

interface

uses
Windows, Messages, SysUtils, Classes, Controls, ExtCtrls, RJ, QStdCtrls,
Graphics, Forms, Dialogs, stdctrls;

type
TLabelPosition = (lpAbove, lpBelow);
TNewRJ = class(TRJ)
ShowLabel:TLabel;
private
{ Private declarations }
......

************************************
注:解决并说明问题者单独给200分。
 
斑竹来帮忙啊!怎么老也不见二位露面?!
 
各位大虾请出手!
 
1.给出完整的控件单元才能有办法解决啊
2.参考一下Delphi6的TLabelledEdit,照搬过来应该就可以了,功能和你想做的这个一样。
 
我也是这么做的——SetParent
代码如下:
————————————————————————————————————————
unit NewRJ;
end.
 
你为什么非得用这句创建呢?
NewControl:= (TComponentClass(FindClass('TLabel'))).Create(Self);
直接放在窗体上或者用NewControl := TNewRJ.Create(Self)都不会出问题呀,看不出两者有什么区别。

另外,我把
RegisterClasses(TCClass);改为
RegisterClasses([TImage, TLabel, TShape]);
就不出问题了,你试试,我想这里的问题可能在于开放数组参数和常量数组是不能互传的,或者传递的过程中出了BUG。
 
首先谢谢Traveller!

NewControl:= (TComponentClass(FindClass('TLabel'))).Create(Self);
的原因是因为,在数据库中存储很多种设备的面板元素信息,元素(控件)的种类很多,如果
用NewControl := TNewRJ.Create(Self)这种形式,每种控件都得有一个Create!代码可能又
长又不容易维护。
关于TCClass数组,我想问题可能不在这里,因为不用TNewRJ就不会有问题。
 
我这里改为
RegisterClasses([TImage, TLabel, TShape]);
也还是老样子

 
我想你可以改成这样:
定义:
type
TCtrlClass = class of TControl;
const
CTClasses: Array [0..2] of TCtrlClass = (TShape, TImage, TLabel);

创建:
var
i: Integer;
CtrlList: Array [0..2] of TControl;
begin
for i := Low(CGUIClasses) to High(CGUIClasses) do
CtrlList := CGUIClasses.Create(Self);
end;
效果一样,而且这个方法比较标准。

P.S.我又试了一下,完全用你的代码来创建我这里也不出异常,很奇怪。
 
这样做可能很难符合我的要求:我这里一个面板种可能只有2种控件,每种控件可能有20—30
个,也可能有20种控件,每种有20—30个也说不定。
另外:之所以你这里成功的原因我想是因为你没有引用NewRJ单元,我这里也是在引入NewRJ
后才出现问题的,如果去掉NewRJ就一切正常了,我以前也正是这么做的,而且运行良好,后
来有了新的需求,对控件做了扩展(继承了TRJ)后便产生了此问题。还有其他几个都是同样的
问题。
 
'Class TLabel not found'.
本来NewRJ中未USE了单元 Forms便不会出现上述错误,是不是修改后未重新编译。
 
to:chao_jian
重新编译过了,而且在其它原先未安装此控件的机器上安装测试,也有同样的问题!
 
type中加入label1:tlabel(label1与你那个label的名字相同)
 
to:DJ6674
跟这个没关系
 
众人拾柴火焰高!请大家广开言路,分不是问题。
 
我。。。。。。
 
建议你试着把基类从TRJ改为TEdit看看,因为我这里没有TRJ,所以改为TEdit,结果没有出问题。
 
to:Traveller
老兄留个Mail,我把TRoundLed和TNewRoundLed发给你,顺便帮我看一下,TNewRoundLed是有问题
的,但不知问题出在那里?!
 
atraveller@sina.com,不过我可不保证能够解决哦 :D
我以前制作复合控件的时候也遇到过类似的问题,但是不是因为动态创建,普通的使用方式也出问题,但是忘了当时是怎么解决的了。
 
其实你可以自己实现一个FindClassEx来代替FindClass,这样就不用再RegisterClasses了,代码如下:

function FindClassEx(ClassList: Array of TClass; ClassName: string): TClass;
var
i: Integer;
begin
Result := nil;
// 首先在类列表里查找
for i := Low(ClassList) to High(ClassList) do
begin
if ClassList.ClassNameIs(ClassName) then
begin
Result := ClassList;
Break;
end;
end;
// 如果没有找到指定名称的类,那么调用系统的FindClass
if Result = nil then
Result := FindClass(ClassName);
end;

其中ClassList可以是你自己定义的一个常量数组,比如:
type
TCtrlClass = class of TControl;
const
CTClasses: Array [0..2] of TCtrlClass = (TShape, TImage, TLabel);
 
顶部