关闭

有关Delphi控件开发讨论

8381人阅读 评论(1) 收藏 举报
本论总预算1000分, 想与此道高手结识, 有能者得之
请勿发表不相干言论, 分数只会分给内容最精辟正确之人; 没有具体言论者, 请勿回复; 相同意见, 只给第一个发表之人
以下是可以回答的方向, 供参考
1.  VCL控件开发的几个主要基类TComponent、TControl、TWinControl、TGraphicControl、TCustomControl的主要功能及各类用途!?
2.  ComponentState属性的用途
3.  如果有一个属性为指向另一个类的实例(如TDataSource的Dataset属性), 要注意的事项
4.  property宣告的具体心得及注意事项、Keyword Default及Stored的意义
5.  TControl与TWinControl的差异
6.  TWinControl中如何封装Windows窗体(或者说, Windows的消息通知(message call), 经过了什么过程, 成为Delphi的Method Call) ? Windows的消息处理机制?
或者另一个问法, 在一个Control中, 要处理消息(message), 除了定义消息函数 (procedure WMSetFocus(var Message: TWMSetFocus); message WM_SETFOCUS;) 外, 尚有那些方式?
7.  设计覆合式控件的注意事项

8.  对Windows基本窗体(Eidt, Button, ListBox....)的了解及说明?
  

来自:孔明.net, 时间:2002-5-2 16:23:00, ID:1080852
GZ  

来自:homejun, 时间:2002-5-2 20:59:00, ID:1081088
gz  

来自:临火, 时间:2002-5-3 11:36:00, ID:1081580
出生是很重要的,比如你是计算机专业的和不是计算机专业的,走的路是不经相同的.
选择一个合适的类继承,对以后的开发会省去很多的精力,选择在于你!  

来自:lorderic, 时间:2002-5-3 12:39:00, ID:1081636
to 臨火:
這個我知道; 可是如果不知道所繼承的類包含那些功能, 即使你繼承了, 也不知如何去運
用,且容易犯下錯誤, 並不自知, 或是採用了效率不好的方式!? 如果不瞭解TComponent、
TControl、TWinControl, 如何自稱知道如何去寫一個控件?

  

来自:swean_98, 时间:2002-5-3 18:39:00, ID:1082039
GZ  

来自:LDS75, 时间:2002-5-4 16:20:00, ID:1083285
你提的问题几句话说不清的,
你主要的问题是对VCL类不了解和在编程中使用类较少,我认为你应该看看这方面的书对VCL各类的说明。
参考书有清华出版的delphi4.0/5.0类详解。

  

来自:zhumoo, 时间:2002-5-4 17:05:00, ID:1083376
几句话说不清的  

来自:lorderic, 时间:2002-5-4 17:15:00, ID:1083389
To zhumoo, lds75
的確, 幾句話說不清楚; 以上的問題我也已有我的答案
我只是想借此拋磚引玉, 看看自己所瞭解夠不夠透澈; 順便認識一下各位高手;
如果有任何意見、心得、問題歡迎討論  

来自:Pan Ying, 时间:2002-5-5 18:21:00, ID:1084842
参见《Delphi高级开发指南》电子工业出版社
《Master Delphi》的配套书籍,
里面对控件的编写有一定的介绍  

来自:icool, 时间:2002-5-5 18:46:00, ID:1084874
谁知道怎样改造DBNavigator控件,使其颜色任意改变。要求Flat属性为True下实现。  

来自:Pipi., 时间:2002-5-5 20:05:00, ID:1085005
2. ComponentState属性的用途
这个属性其他的值比较少见具体用到,最常用的是判断是否包含 csDesigning ,
当然,只是开发vcl控件用到,通过判断这个值,可以判断当前是在delphi的设计中
还是程序的执行中。这个判断很重要,有时候在设计期是不做、或者要做一些事情的,
比如socket通讯控件,设置active:=true的时候,判断到当前包含 csDesigning ,
是不用实际连接的
  

来自:Pipi., 时间:2002-5-5 20:19:00, ID:1085026
1.  VCL控件开发的几个主要基类TComponent、TControl、TWinControl、TGraphicControl、TCustomControl的主要功能及各类用途!?
5.  TControl与TWinControl的差异
TComponent是所有控件的基类,不可视控件可以使用TComponent为基类
TControl是所有可视控件的基类,它提供左右宽高颜色字体等可视控件要用到的基本属性信息
TWinControl、TGraphicControl 都继承于 TControl
TGraphicControl 是没有HWND句柄的,他不是窗口来的,是delphi做的东西,它在父窗口
接收到WM_PAINT的时候,delphi会安排父窗口拥有的那些 GraphicControl 自己把自己画出来
(比如TLabel、TImage等)
TWinControl 是有窗口的控件,他们是父窗口属下的子窗口,自己处理消息,windows对他们进行管理
delphi只负责处理一些消息,比如TBitton、TEdit等  

来自:Pipi., 时间:2002-5-5 20:23:00, ID:1085031
3.  如果有一个属性为指向另一个类的实例(如TDataSource的Dataset属性), 要注意的事项
不需要特别注意什么,只是要判断 Assigned(属性) 看是不是已经赋值了而已
那个赋给值的控件如果在设计期被移动去,会自动把这个属性设置为nil的
在运行期释放了赋给值的对象,这个是不推荐的,应该由用户自己设置nil,你也不必费心  

来自:Pipi., 时间:2002-5-5 20:40:00, ID:1085044
4.  property宣告的具体心得及注意事项、Keyword Default及Stored的意义
Default实际是告诉delphi你在控件的constructor Create(o:TComponent)中对这个属性赋的初值,
(当然,其他的初始化过程也行,一般的做法是在create赋初值)
并不是说你设置了default的值delphi就会给你赋一个初值,
如果设置了default,你又没有在create设置相同的值,或者根本没有赋初值,那会出问题的
default的作用是,当没有Stored 限制的时候,或者Stored为true的时候
比如 default 123 ,delphi就知道了你这个控件在create的时候给了这个属性赋值123
所以,设计期当你设置这个控件的这个属性为123的时候,delphi就不浪费dfm空间了,他不用把
123保存在你的dfm文件了,因为你告诉他了,create的时候会赋值123,这个123就不用再保存了
如果设计期你设置非 123 ,那么和default值不一样,delphi会把你设置的值保存在dfm
作为资源连接进exe
当stored未设置的时候,是相当于 stored true 的
当stored为false的时候,不管你设计的值和default怎么样,这个值都不会保存进dfm
这个设置特别对密码属性有用,比如,设计期你可能要得到密码来连接数据库,但是你不想
把密码保存进dfm或者exe,这样不安全,你可以设置密码属性stored false,这样每次设计期
输入一次密码,你可以利用这个密码,但是他不会保存,下次打开delphi可以重新输入密码
  

来自:Pipi., 时间:2002-5-5 20:54:00, ID:1085075
补充,default在array类型的属性里面有另外的含义
比如 TStrings 的 Strings 属性
property Strings[Index: Integer]: string ...; default;
这样设置的作用是,我们一直用
Memo1.Lines[0] ,其实是执行 Memo1.Lines.Strings[0] ,Strings给当作了缺省属性  

来自:hbezwwl, 时间:2002-5-5 20:59:00, ID:1085085
楼主:
    既然是要抛玉引砖,先把你的玉拿出来大家看看才好.  

来自:yygw, 时间:2002-5-7 13:05:00, ID:1087438
to lorderic:
你能问出这些问题,说明你对VCL底层知识有一定了解,至少对此感兴趣。
我并不认为这些东西可以通过简单的几句话说清的,其实你只要好好研究一下Delphi自带的
Classes、Controls等单元,就什么都透了。
知识达到这个层次后,基本上都不需要看什么其它的资料了,几乎所有的东西都可以在VCL
源码中去领会、去分析、去创造。

如果对组件开发感兴趣,有空请关注一下CnPack开发计划:
http://cnpack.yeah.net  

来自:yygw, 时间:2002-5-7 13:23:00, ID:1087477
对 Pipi. 兄的补充:
1.VCL控件开发的几个主要基类TComponent、TControl、TWinControl、TGraphicControl、TCustomControl的主要功能及各类用途!?

TGraphicControl从TControl中派生而来,增加了 Canvas 属性处理 WM_PAINT 消息调用虚拟方法
Paint 以实现控件对画面的绘制。
Controls单元中源码如下:
procedure TGraphicControl.WMPaint(var Message: TWMPaint);
begin
  if Message.DC <> 0 then
  begin
    Canvas.Lock;
    try
      Canvas.Handle := Message.DC;
      try
        Paint;
      finally
        Canvas.Handle := 0;
      end;
    finally
      Canvas.Unlock;
    end;
  end;
end;

而在 CnPack 的界面类图形控件中,并不直接从TGraphicControl中派生,而从TControl中
派生,自己定义虚拟方法和处理重绘消息,以实现最底层的控件级 AlphaBlend 支持。
如下代码所示:
// 控件重绘消息
procedure TCnGraphicControl.WMPaint(var Msg: TWMPaint);
var
  Bmp: TCnBitmap;
begin
  if (csDesigning in ComponentState) and not FLoaded then
  begin
    FLoaded := True;          // 设计期第一次重绘调用 Loaded 方法
    Loaded;
  end;

  if AlphaBlend and (AlphaBlendValue = 0) then Exit; // 完全透明

  if FTransparent and FFullPaint then
    DoPaint;                  // 透明且完整刷新时每次重绘都更新

  if not AlphaBlend or (AlphaBlendValue = csMaxAlpha) then // 无半透明效果
  begin
    if Msg.DC <> 0 then
    begin
      Face.Lock;
      try
        Face.DrawTo(Msg.DC, 0, 0); // 画布绘制到目标DC
      finally
        Face.Unlock;
      end;
    end;
  end
  else
  begin                       // 部分透明效果
    Bmp := TCnBitmap.Create;
    try
      Bmp.LoadBlank(Width, Height);
      CopyParentImage(Self, Bmp); // 从父控件复制图像
      Bmp.AlphaDraw(Face, AlphaBlendValue, False); // Alpha混合
      Bmp.DrawTo(Msg.DC, 0, 0); // 绘制到目标DC
    finally
      Bmp.Free;
    end;
  end;
end;

TControl没有HWND,在重绘时调用父控件(TWinControl)的保护方法 PaintControls,而TGraphicControl
则继承了这一特性。事实上 TControl 和 TWinControl(也是派生自TControl) 的代码中有相当密切的联系。  

来自:delnus, 时间:2002-5-7 13:27:00, ID:1087487
我不要积分,只要和大家一起进步!
机械工业出版社,“delphi部件开发编程深入剖析“;
另外,以前有过这方面的讨论,你向前查查。
关于windows的基本控件如TButton,TEdit etc 可以看看微软核心编程技术丛书
清华大学出版社的,GDI(图形设备接口),不过是英文版的。
我这儿有控件开发的帮助文件,把你的EMail留下来。  

来自:yygw, 时间:2002-5-7 13:34:00, ID:1087502
2. ComponentState属性的用途
除了csDesigning,还有 csLoading 表示组件正在从流中装载属性,有时可用在属性写方法中。
csDestroying  表示组件正在被释放,在组件重绘方法中判断可以避免出现无法绘制Canvas的
错误。
csReading和csWriting  表示组件正在读或写属性。
其它的好象不常用。  

来自:yygw, 时间:2002-5-7 13:40:00, ID:1087510
3.如果有一个属性为指向另一个类的实例(如TDataSource的Dataset属性), 要注意的事项
如果这个类实例也是TComponent派生类,该属性变更时会调用虚拟方法
procedure Notification(AComponent: TComponent; Operation: TOperation); virtual;
override该方法可处理连接变更事件。  

来自:yygw, 时间:2002-5-7 20:25:00, ID:1087530
4.property宣告的具体心得及注意事项、Keyword Default及Stored的意义

default声明只能适用于数值、颜色、布尔等简单类型,如果要处理高级一些的属性,则需要用
Stored 跟一个函数方法(返回Boolean)名,在该方法中进行判断。

事实上,default、Stored的设计应该是为了减少DFM的存储内容,加快属性装载速度,而把一些不
怎么变化的属性在Create中赋初值,从这点上考虑会更容易理解。  

来自:yygw, 时间:2002-5-7 14:05:00, ID:1087551
6.TWinControl中如何封装Windows窗体(或者说, Windows的消息通知(message call), 经过了什么过程, 成为Delphi的Method Call) ? Windows的消息处理机制?
或者另一个问法, 在一个Control中, 要处理消息(message), 除了定义消息函数 (procedure WMSetFocus(var Message: TWMSetFocus); message WM_SETFOCUS;) 外, 尚有那些方式?

除了用message关键字处理特定消息,还有其它方法:
1)TControl中已定义了MouseDown、MouseMove这样的虚拟保护方法,直接override就行,不过只适用于少数消息。
2)直接override TWinControl控件消息处理主过程 WndProc,适合批量处理消息。
3)override在TObject中定义的虚拟方法 DefaultHandler,这是最后被调用的了。

  

来自:yygw, 时间:2002-5-7 14:17:00, ID:1087564
7.设计覆合式控件的注意事项
在published中声明一个TComponent属性,只能是链接到另一个组件,而不能由组件自己创建
一个实例拿来发布,如果你要在一个组件中包含另一个组件,一般来说,你需要在组件中声明
有用的属性并用代码连接到子组件中。

很多组件在设计期可创建新的组件到窗体上,这些组件有些使用带多个参数的构造器,一般用
RegisterNoIcon注册,象TField就是一个组件,但并不能放到窗体上。以前见过一个类似于QQ
面板控件的控件,也是用组件编辑器来创建用RegisterNoIcon注册的子控件的。
  

来自:yygw, 时间:2002-5-7 14:24:00, ID:1087577
5.TControl与TWinControl的差异

书上都把TGraphicControl和TWinControl描述为TControl的两大分支,其实从代码层来看,
TGraphicControl并没有实现太多东西,人们描述的很多TGraphicControl的功能其实都是
TControl本身的功能,而TGraphicControl和TWinControl的差异大部分也是TControl与
TWinControl的差异。

TControl和TWinControl的联系是相当密切的,从Controls.pas单元中可看得非常清楚。
TWinControl中引入了很多新的属性和方法,而在控件绘制等方面,二者有很多方法都是紧
密相连的。

  

来自:duanliandl, 时间:2002-5-7 14:33:00, ID:1087589
1.VCL控件开发的几个主要基类TComponent、TControl、TWinControl、
TGraphicControl、TCustomControl的主要功能及各类用途!?

TComponent:TComponent类直接由TPersistent类派生。TComponent地独特特征是它地属性能够
在设计浅见通过Object Inspector来控制,能够拥有其他组件。

TControl:TControl类定义了许多属性、方法和事件,一般用于可视控件。TControl本身没有什么
用处,你绝对不能创建它地派生类。大多数DELPHI的控件都是由TControl的派生类TWinControl
和TGraphicControl派生而来的。

TWinControl:标准窗口控件由TWinControl类派生。标准控件是你在大多数windows应用程序中
看到的用户界面。由于DELPHI封装了标准控件的行为,而不是通过WINDOWS API函数来实现它们,
你可以直接使用各种控件提供的属性。TWinControl对象有三个特征:它们有窗口句柄,能够接受输入
焦点,能够成为其他控件的父。

TGraphicControl:与TWinControl不同,TGraphicControl控件没有窗口句柄,因而不能接受输入
焦点。他们也不能是其他控件的父。

TCustomControl:一些TWinControl派生类的名称都是以TCustom开头,如TCustomComboBox、
TCustomEdit等等。自定义控件具有其他TWinControl派生类同样的功能,除了特殊的可视和交互
特征。这些以TCustom开头的派生类可以作为基类派生和创建你自己的自定义的控件。如果你是
组件编写者,你可以通过这些基类给自定义控件提供绘制自己的功能。

  

来自:yygw, 时间:2002-5-7 14:41:00, ID:1087603
to duanliandl:
>TControl:TControl类定义了许多属性、方法和事件,一般用于可视控件。TControl本身没有什么
用处,[red]你绝对不能创建它地派生类[/red]。

不要听书上说的,TControl的用处非常大,你一看TGraphicControl的源码就知。
TGraphicControl不过是处理了WM_PAINT消息,用Canvas来绘制罢了,如果你创建的控件不需要用
TCanvas,而使用自己的方法绘制,完全可以从TControl中直接派生!
我在 CnPack 界面控件中就这样做的,上面已放有代码了。
  

来自:yygw, 时间:2002-5-7 14:42:00, ID:1087606
[red]同志们,寻幽探密要靠自己啊![/red]  

来自:yygw, 时间:2002-5-7 14:49:00, ID:1087609
to duanliandl:
TCustomControl并不完全是你说的那个意思,它只是在TWinControl的基础上通过覆盖 PaintWindow
方法,引入了一个 Canvas 来允许控件直接绘制表面罢了(通过在 WM_PAINT 处理过程中为 ControlState
增加了 csCustomPaint 以允许自绘制)。就象 TGraphicControl 对 TControl 的扩充一样。  

来自:yygw, 时间:2002-5-7 15:24:00, ID:1087660
8.对Windows基本窗体(Eidt, Button, ListBox....)的了解及说明?

绝大部分对Windows标准窗口控件的封装代码在StdCtrls.pas单元中,一般它们通过覆盖
TWinControl的几个虚拟方法来工作:

1)窗体创建参数方法 CreateParams,如单选框的代码:
procedure TCustomCheckBox.CreateParams(var Params: TCreateParams);
const
  Alignments: array[Boolean, TLeftRight] of DWORD =
    ((BS_LEFTTEXT, 0), (0, BS_LEFTTEXT));
begin
  inherited CreateParams(Params);
  CreateSubClass(Params, 'BUTTON');
  with Params do
  begin
    Style := Style or BS_3STATE or
      Alignments[UseRightToLeftAlignment, FAlignment];
    WindowClass.style := WindowClass.style and not (CS_HREDRAW or CS_VREDRAW);
  end;
end;
事实上我们在写普通窗体的代码时也经常覆盖该方法来修改窗体属性,实现一些Delphi不
支持的功能。

2)创建窗口方法 CreateWnd,在TWinControl.CreateHandle中调用,控件在此对新创建
的窗口进行初始化,如单选框的代码:
procedure TCustomCheckBox.CreateWnd;
begin
  inherited CreateWnd;
  SendMessage(Handle, BM_SETCHECK, Integer(FState), 0);
end;

3)处理 CN_COMMAND 消息,该消息由 WM_COMMAND 转换而来,为Windows发给窗口的用户
消息,如按钮的代码:
procedure TButton.CNCommand(var Message: TWMCommand);
begin
  if Message.NotifyCode = BN_CLICKED then Click;
end;  

来自:Pipi., 时间:2002-5-7 18:14:00, ID:1087924
>假设你设置了property A: Integer read FA write SetA default 10;
>如果没有为 A 赋初值 10,你会在DFM文本中看到保存了属性 A 的值为 0,如果你在设计期刚好
>把 A 置为 10,则DFM中不保存。

那么,你想设置属性为10,最后运行的时候发现是0

〉有时我们把一个Boolean属性设为 default True,而在 Create 中将其初始化为 False,这样可
〉保证组件装载后该属性始终为 False。因为如果设计期为 True,属性不会保存,Create时自动被
〉置为 False,如果设计期为 False,则正好:)

如果你想运行的时候始终为某一个值,应该通过stored false,而不是这点小把戏  

来自:yygw, 时间:2002-5-7 19:01:00, ID:1087971
Pipi.兄教训得好,多谢!

第一点我是想举个反例,不过少写了几句话:)
第二点确实有卖弄之嫌,报歉。
不过我也是想通过它来说明我们不应被已有的框架所局限,应该善于独立思考和联想。
在追求事物本质的基础上,去做出更多的创新,即使错了也可获得大量的经验。

当然,大师级的程序员都已到了化腐朽为神奇的地步,而不是卖弄一些小技巧、小聪明。
唉!什么时候我也能达到反璞归真的境界呢:)

承教了!
  

来自:yygw, 时间:2002-5-7 21:34:00, ID:1088232
to Pipi.兄:
前面关于 default 的帖子是我的犯低级错误(已删掉),补充一点使用stored 和布尔函数
搭配使用的方法,希望将功补过:)

例子:
function IsFontStored: Boolean;
...
property Font: TFont read GetFont write SetFont stored IsFontStored;
...

function TMyControl.IsFontStored: Boolean;
begin
  Result := (Font.Name <> '宋体') or (Font.Size <> 9) or ...
end;

在 stored 关键字后接一个无参数、返回Boolean值的方法名,当设计期要保存窗体数据流时
会调用该方法来决定是否保存,可用来进行复杂的判断。

更进一步,通过对Classes单元中TFilter、TReader、TWriter和TComponent以及TypInfo单元
的分析,最终可发现,每一个发布属性都对应着一个这样的结构:
  PPropInfo = ^TPropInfo;
  TPropInfo = packed record
    PropType: PPTypeInfo;
    GetProc: Pointer;
    SetProc: Pointer;
    StoredProc: Pointer;
    Index: Integer;
    Default: Longint;
    NameIndex: SmallInt;
    Name: ShortString;
  end;
里面的GetProc、SetProc对应着属性的读、写方法,而StoredProc则是决定是否存储的方法。
Default就保存着简单类型属性的默认值。

从TWriter.WriteProperty的源码中可看出组件属性写入流中的大部分过程,不过有一点疑问:
代码中在保存简单类型属性时,只将数值与PropInfo.Default进行了判断而没有通过StoredProc
来决定,如子过程中的IsDefaultValue:
  procedure WriteOrdProp;
  var
    Value: Longint;

    function IsDefaultValue: Boolean;
    begin
      if AncestorValid then
        Result := Value = GetOrdProp(Ancestor, PropInfo) else
        Result := Value = PPropInfo(PropInfo)^.Default;
    end;

  begin
    Value := GetOrdProp(Instance, PropInfo);
    if not IsDefaultValue then
    begin
      WritePropPath;
      case PropType^.Kind of
        tkInteger:
          WriteIntProp(PPropInfo(PropInfo)^.PropType^, Value);
        tkChar:
          WriteChar(Chr(Value));
        tkSet:
          WriteSet(Value);
        tkEnumeration:
          WriteIdent(GetEnumName(PropType, Value));
      end;
    end;
  end;
而TWriter在保存TPersistent属性时,调用了WriteProperties方法,该方法调用了
IsStoredProp这个汇编过程来访问PropInfo.StoredProc过程以决定是否保存。

[red]问题:[/red]为什么我们对简单类型属性使用 stored IsXXXStored 这样的代码时,TWriter
也能够正确地判断是否要保存呢??

  

来自:lorderic, 时间:2002-5-8 8:30:00, ID:1088545
to yygw
你再看呼叫WriteProperty的WriteProperties, 就可以明白了  

来自:yygw, 时间:2002-5-8 12:47:00, ID:1089007
多谢,看来我还得再多花些时间来分析代码才行:)
有哪位师兄把System、Classes、SysUtils、Graphics、Controls等这几个核心单元全部看完了吗??  

来自:yygw, 时间:2002-5-8 13:18:00, ID:1089075
to lorderic:
看了你答的几个问题,确实对VCL底层有相当深入的研究,小弟佩服:)
看来我要再练两年才出来混了。  

来自:hamsoft, 时间:2002-5-9 1:00:00, ID:1090160
上面的代码我懒的看,关于vcl也不是一篇文章就可以讲明白的,建议去看有关的书籍。
或到网上下载此类资料。  

来自:zq67, 时间:2002-5-17 11:56:00, ID:1106366
我想将一个自己做的类封装成ActiveX控件,但这个控件是从TGraphicControl中继承的,显然不行,我在控件中用到了Canvas的许多属性,从TWinControl类继承的话,TWinControl类没有Canvas,我该怎么办,请各位高手指教。  

来自:lorderic, 时间:2002-5-19 15:35:00, ID:1110171
to zq67:
把它改由TCustomControl中繼承即可!
TCustomControl是繼承自TWinControl, 多加了Canvas
繼承自TWinControl後, 唯一要考慮的是, 要不要讓Control有GetFocus的能力;
預設TWinControl的TabStop是 False,而且點擊WinControl也無法使control GetFocus,
如果有需要GetFocus的話, 要由自己寫代碼處理  

来自:blackbeam, 时间:2002-5-19 15:41:00, ID:1110176
3.如果有一个属性为指向另一个类的实例(如TDataSource的Dataset属性), 要注意的事项
我最为困惑的就是此问题,不是要注意什么,而是怎么实现这样的属性?
《Delphi 5开发人员指南》上没有该内容,还请大家指教!  

来自:SandAhrow, 时间:2002-5-19 15:46:00, ID:1110187
创建一个Canvas,然后
Canvas.Handle:=GetDc(Self.Handle)  

来自:ngkai, 时间:2002-5-23 9:22:00, ID:1118432
1.所有要在面板上出现的构件都应继承自TComponent还有从Tcomponent开始有了owner这个构造参数,有了这个有意思的生存期,所有运行时可视的构件都继承自TControl,想要自己的构件有handle找TWincontrol吧,想要有handle和canvas找TCustomControl,不想要handle,只想要canvas找TGraphicControl吧;
2.componentstate可以用来标识组件所处的各种状态,根据它来做一些处理;用的最多的是看component是在runtime还是在design time,在design时要避免一些action出现。
3.我的观点是要判断这个类的实例是否为nil,还有要注意这个类的实例是由自身构造还是外部构造;
4.最好看具体的property行为,如果不需要在外部写值入property那么这个property最好还是readonly的,
default有两层意义:在property是ordinal时表示其初始值,当property是array时表示可以直接用object[i]来访问property,stored不用说了是要不要将property value放入.dfm中的意思;
5.说起来可以讲一篇文章,一句话TWinControl继承自TControl加一个最重要的东东就是handle;
6.delphi的将message call 通过将全局的windows窗口过程,很巧妙的化为了自身类的方法,最核心的函数是makeobjectinstance这个东东,还用到了链表,要处理消息除了定义函数还可以处理procedure WndProc(var Message: TMessage);这个类的窗口方法来得到;
7.注意对象的释放问题;
8.太多了不想说了。
  

来自:ZXW49362727, 时间:2002-5-23 9:49:00, ID:1118502
这么多!Delphi开发人员指南上全都有,好书呀好书。[:D]
另外多看看VCL的源码,比什么都强。
只要你能好好研究一下TListBox,TDataset之类的源代码,你就是高手了![8D]  

来自:zhukewen, 时间:2002-5-24 16:50:00, ID:1121858
[BLUE]1.VCL控件开发的几个主要基类TComponent、TControl、TWinControl、
TGraphicControl、TCustomControl的主要功能及各类用途!?[/BLUE]

TComponent继承于TPersistent,TPersistent继承于TObject.
TObject是delphi的基石,实现了类的创建、销毁、成员数据管理和程序指针
管理,同时实现了delphi方式的消息分配管理,TPersistent增加了对象拷贝
的能力,TComponent实现了按名字(Name)管理和按链表管理,因此,到TComponent
为止,已为可视化控件搭好了舞台.
TControl继承于TComponent,实现了管理自己的文本、尺寸和管理鼠标的功能,
只是不知道怎么表现自己。
TWinControl继承于TControl,拥有了自己的窗口,同时还具备了获得焦点和
管理键盘事件的能力。
TGraphicControl继承于TControl,增加了画布(Canvas),简化了绘制图形的
方法,是TControl的增强版。
TCustomControl继承于TWinControl,增加了画布(Canvas),简化了绘制图形的
方法,是TWinControl的增强版。
从他们的功能可以知道,TComponent主要用来生成非可视化控件,TControl和
TGraphicControl主要用来生成不需要键盘事件的可视化控件,TWinControl和
TCustomControl主要用来生成需要键盘事件的可视化控件。

[BLUE]2.ComponentState属性的用途[/BLUE]

ComponentState属性主要用来标志Component的状态,防止功能执行混乱。例如:
function TCustomCombo.GetItemIndex: Integer;
begin
  if [RED]csLoading in ComponentState[/RED] then
    Result := FItemIndex
  else
    Result := SendMessage(Handle, CB_GETCURSEL, 0, 0);
end;
另外要说的是,控件在运行期和设计期使用同一套代码,也要用到ComponentState。

[BLUE]3.如果有一个属性为指向另一个类的实例(如TDataSource的Dataset属性),
要注意的事项[/BLUE]

首先引用前要判断其是否已创建,其次要注意其状态的改变,因为你不改变它的
状态但是别人有可能改变它,在次要注意使用后的恢复,对象都是传址引用的,
所作的改变都会被保留下来,所以要注意恢复。

[BLUE]4.property宣告的具体心得及注意事项、Keyword Default及Stored的意义[/BLUE]

delphi中最让我佩服的就是property了,给一个property赋值或读取,就有可能
引发任何事情,让我觉得delphi的控件活了。

[BLUE]6.TWinControl中如何封装Windows窗体(或者说, Windows的消息通知
(message call), 经过了什么过程, 成为Delphi的Method Call) ? Windows的消
息处理机制?或者另一个问法, 在一个Control中, 要处理消息(message), 除了定义
消息函数 (procedure WMSetFocus(var Message: TWMSetFocus); message WM_SETFOCUS;)
外, 尚有那些方式?[/BLUE]

delphi首先向windows操作系统(OS)注册窗口,这样有什么事件就会被wndproc
函数得到。我wndproc最终调用其祖先类TObject的Dispatch函数,通过Dispatch
找到需要该消息的函数。因此,可以通过重载wndproc或dispatch来达到目的,
甚至可以使用操作系统的钩子函数。

  

来自:cee, 时间:2002-5-29 16:18:00, ID:1131047
关注  

来自:xeen, 时间:2002-5-29 17:28:00, ID:1131234
6:
1/消息首先到达接受消息的wndproc过程(如果wndproc过程被override),然后沿着继承路线
向上一直到达Tobject.wndproc.
所以我们开发组件时候要注意:如果要override 组件的wndproc过程,一定要在最后调用:
inherited,否则消息上传的路径被打断,一般会引起严重的错误。
如果要开发的控件还可能有子类,要把wndproc定义为虚拟方法(virtual;),以便它的子类
继承的时候可以覆盖它。
2/消息到达Tobject.wndproc后将调用Tobject.dispath方法派发消息,它根据消息号码将
调用最后代类中的消息处理方法.如果组件和它的基类中都没有对应消息号码的句柄方法,
就察看defaulthandler方法是否被覆盖,(defaulthandler也是定义在 Tobject
的virtual方法),如果都没有覆盖就一直到达tobject.defaulthandler简单的把消息吃掉。
所以覆盖defaulthandler的时候也应该调用inherited并声明为virtual.
3/delphi引入事件的概念,实际上事件就是处理消息过程的句柄,作为published属性可以在
设计期间访问。可以在wndproc或defaulthandler中根据消息号码调用相应的过程句柄(事件).
  

来自:魔鬼大师, 时间:2002-5-29 18:02:00, ID:1131336
看vcl源代码比较好  

来自:savenight, 时间:2002-5-29 23:14:00, ID:1131945
========================================
1.  VCL控件开发的几个主要基类TComponent、TControl、TWinControl、TGraphicControl、
TCustomControl的主要功能及各类用途!?

:目前还没有能力回答这个问题。
========================================
2.  ComponentState属性的用途
:用途就是描述控件的状态。由于自己做控件时很少遇到加上也不算难懂,我认为看看
vcl源代码了解一下应用就够了。
========================================
3 的内容被包含在7里了

========================================
4.  property宣告的具体心得及注意事项、Keyword Default及Stored的意义

 这个问题前面已经讨论的很多了,我也不多说了。
========================================

5.  TControl与TWinControl的差异

TControl为所有在运行期可视并可操作的控件的基类。
TWinControl为所有具有输入焦点(即有窗体句柄)的控件的基类。
---------------------------------------------------------------------
TControl的子类拥有诸如position,cursor,paint,mouse actions等等属性,方法和事件。
TWinControl的子类除了拥有TControl所有的事件,还有拥有OnEnter OnKeyDown OnKeyPress
OnKeyUp OnExit几个事件。
---------------------------------------------------------------------
TControl 的子类可以作为进入入坞点的子窗体。
TWinControl的子类可以作为入坞点;
---------------------------------------------------------------------
只有TWinControl的子类才能转换成ActiveX(当然并不是所有的都能转换)。

========================================
6.   TWinControl中如何封装Windows窗体(或者说, Windows的消息通知(message call),
经过了什么过程, 成为Delphi的Method Call) ? Windows的消息处理机制?或者另一个问法,

: 所有的Delphi类都有一个处理消息的内建机制--message handlers.
消息的派发过程是:event-->MainWndProc-->WndProc-->Dispatch-->Handler
   当一个事件event发生后,delphi会调用MainWndProc来处理,MainWndProc又调用虚拟的WndProc
(因为各个组件的处理信息可以定制,所以这里用了虚拟方法,具体到某个组件,它可以实现自己的
消息处理定制)。TWinControl的WndProc方法是个主角,在这里进行消息的筛选,trap掉不想处理的
消息,然后将要处理的消息传给TObject的Dispatch,由Dispatch来决定实际该调用哪个方法处理次
消息。Dispatch检查消息的Msg field,如果组件定义了针对次消息的处理(handler),那么就转到
handler;如果没有,就调用DefaultHandler。

在一个Control中, 要处理消息(message), 除了定义消息函数 (procedure WMSetFocus(var Message:
TWMSetFocus); message WM_SETFOCUS;) 外, 尚有那些方式?
: // // // // // // // // //
  protected
    procedure WndProc(var Message: TMessage); override;
 //。。。
procedure TForm1.WndProc(var Message: TMessage);
begin
  if Message.Msg=SN_Msg then
   showmessage('hello from WndProc');
  inherited;
end;


========================================
7.  设计覆合式控件的注意事项
(我对覆合式控件的概念不是很清楚,这里我把它当做是控件A包含B)

  我认为要分为两种情况:一种是要在A中创建B;另一种是A中引用B。

第一种较简单:
只要注意最后释放就行了,代码如下:
 TA=class(TComponent)
 private
 FB:TComponent;
 public
 constructor Create(AOwner: TComponent); override;
 destructor Destroy; override;
 end;
constructor TA.Create(AOwner: TComponent);
begin
  inherited;
  FB :=TComponent.Create(self);
end;

destructor TA.Destroy;
begin
  FreeAndNil(FB);
  inherited;
end;

第二种就是你说的TDataSource这种引用之类,要注意的是必须改写此控件的 Notification 方法。

这个答案有现成的,下面是从深度历险摘来的,正合适你用:)
译者: 陈宽达 原作者 :John M. Miano
TMyComponent = class (TComponent)
private
FDataSource: TDataSource;

procedure SetDataSource(Value: TDataSource);
protected
procedure Notification(AComponent: TComponent; Operation: TOperation); override;
published
property DataSource: TDataSource read FDataSource write SetDataSource;
end;

procedure TMyComponent.SetDataSource(Value: TDataSource);
begin
if Value <> FDataSource then
begin
FDataSource := Value;
// 告诉叁考构件说,当它被移除时记得通知我一声。
if FDataSource <> nil then FDataSource.FreeNotification(Self)
end;
end;

procedure TMyComponent.Notification(AComponent: TComponent; Operation:TOperation);
begin
inherited Notification(AComponent, Operation);
// 如果被移除的正是叁考构件,把FDataSource字段清除。
if (Operation = opRemove) and (AComponent = FDataSource) then
FDataSource := nil
end;

========================================
8.  对Windows基本窗体(Eidt, Button, ListBox....)的了解及说明?

不要忽视了tag属性。
它们最常被用作控件数组的。
  

来自:anqingrong, 时间:2002-5-30 0:39:00, ID:1132050
[red][b]To::LordEric[/b][/red]
我想有一点大[black]家可能忽略了----VMT.
以下的TVmt结构可以说是对VMT的一个具体描述
  PVmt = ^TVmt;
  TVmt = record
    SelfPtr:            TClass;
    IntfTable:          PInterfaceTable;
    AutoTable:          PAutoTable;
    InitTable:          PInitTable;
    TypeInfo:           PTypeInfo;
    FieldTable:         PFieldTable;
    MethodTable:        PMethodTable;
    DynMethodTable:     PDynMethodTable;
    ClassName:          PShortString;
    InstanceSize:       Integer;
    ClassParent:        ^TClass;
    SafeCallException:  Pointer; { The following hidden fields point to }
    AfterConstruction:  Pointer; { special virtual methods that are }
    BeforeDestruction:  Pointer; { inherited from TObject. }
    Dispatch:           Pointer;
    DefaultHandler:     Pointer;
    NewInstance:        Pointer;
    FreeInstance:       Pointer;
    Destroy:            Pointer;
    { Here begin the virtual method pointers.
      Each virtual method is stored as a code pointer, e.g.,
        VirtualMethodTable: array[0..Count] of Pointer;
      The compiler does not store the Count of the number of method
      pointers in the table. }
  end;

  IVmtInfo = interface
  ['{102C2541-160F-11D3-B1A8-00105AA9C2AD}']
    function GetFieldClassTable: Pointer;
    function GetClass(Index: Integer): TClass;
    function GetClassCount: Integer;
    function GetClassName: string;
    function GetClassType: TClass;
    function GetDynamicTable: Pointer;
    function GetDynamicAddress(Index: Integer): Pointer;
    function GetDynamicNumber(Index: Integer): SmallInt;
    function FindDynamicAddress(Number: SmallInt): POinter;
    function GetDynamicMethodCount: Integer;
    function GetFieldTable: Pointer;
    function GetField(Index: Integer): IVmtField;
    function GetFieldType(Index: Integer): TClass;
    function GetFieldCount: Integer;
    function GetMethodTable: Pointer;
    function GetMethod(Index: Integer): IVmtMethod;
    function GetMethodCount: Integer;
    function GetParentVmt: IVmtInfo;
    function GetInitTable: Pointer;
    function GetInitCount: Integer;
    function GetInitEntry(Index: Integer): IVmtInitEntry;
    function GetAutoTable: Pointer;
    function GetTypeInfo: PTypeInfo;
    function GetIntfTable: Pointer;
    function GetInterfaceCount: Integer;
    function GetInterfaceEntry(Index: Integer): TInterfaceEntry;
    function GetAutoCount: Integer;
    function GetAutoEntry(Index: Integer): IVmtAutoEntry;
    function GetVmt: Pointer;

    function GetInstanceSize:       Integer;
    function GetSafeCallException:  Pointer;
    function GetAfterConstruction:  Pointer;
    function GetBeforeDestruction:  Pointer;
    function GetDispatch:           Pointer;
    function GetDefaultHandler:     Pointer;
    function GetNewInstance:        Pointer;
    function GetFreeInstance:       Pointer;
    function GetDestroy:            Pointer;

    property Vmt: Pointer read GetVmt;

    property ParentVmt: IVmtInfo read GetParentVmt;
    property ClassName: string read GetClassName;

    property MethodTable: Pointer read GetMethodTable;
    property MethodCount: Integer read GetMethodCount;
    property Methods[Index: Integer]: IVmtMethod read GetMethod;

    property FieldTable: Pointer read GetFieldTable;
    property FieldCount: Integer read GetFieldCount;
    property Fields[Index: Integer]: IVmtField read GetField;
    property FieldType[Index: Integer]: TClass read GetFieldType;

    property FieldClassTable: Pointer read GetFieldClassTable;
    property ClassCount: Integer read GetClassCount;
    property Classes[Index: Integer]: TClass read GetClass;

    property DynamicTable: Pointer read GetDynamicTable;
    property DynamicMethodCount: Integer read GetDynamicMethodCount;
    property DynamicMethods[Index: Integer]: Pointer read GetDynamicAddress;
    property MessageNumbers[Index: Integer]: SmallInt read GetDynamicNumber;
    property Messages[Index: SmallInt]: Pointer read FindDynamicAddress;

    property InitTable: Pointer read GetInitTable;
    property InitializerCount: Integer read GetInitCount;
    property Initializer[Index: Integer]: IVmtInitEntry read GetInitEntry;

    property AutoTable: Pointer read GetAutoTable;
    property AutoCount: Integer read GetAutoCount;
    property AutoEntry[Index: Integer]: IVmtAutoEntry read GetAutoEntry;

    property IntfTable: Pointer read GetIntfTable;
    property InterfaceCount: Integer read GetInterfaceCount;
    property Interfaces[Index: Integer]: TInterfaceEntry read GetInterfaceEntry;

    property TypeInfo: PTypeInfo read GetTypeInfo;
  end;

  TVmtInfo = class(TInterfacedObject, IVmtInfo, IPrintable)
  private
    FVmt: PVmt;
    FInitRecord: IVmtInitRecord;
    function GetInitRecord: IVmtInitRecord;
  protected
    property Vmt: PVmt read fVmt;
    property InitRecord: IVmtInitRecord read GetInitRecord;
  public
    constructor Create(ClassRef: TClass);

    function GetInstanceSize:       Integer;
    function GetSafeCallException:  Pointer;
    function GetAfterConstruction:  Pointer;
    function GetBeforeDestruction:  Pointer;
    function GetDispatch:           Pointer;
    function GetDefaultHandler:     Pointer;
    function GetNewInstance:        Pointer;
    function GetFreeInstance:       Pointer;
    function GetDestroy:            Pointer;

    function GetFieldClassTable: Pointer;
    function GetClass(Index: Integer): TClass;
    function GetClassCount: Integer;
    function GetClassName: string;
    function GetClassType: TClass;
    function GetDynamicTable: Pointer;
    function GetDynamicAddress(Index: Integer): Pointer;
    function GetDynamicNumber(Index: Integer): SmallInt;
    function FindDynamicAddress(Number: SmallInt): Pointer;
    function GetDynamicMethodCount: Integer;
    function GetFieldTable: Pointer;
    function GetField(Index: Integer): IVmtField;
    function GetFieldType(Index: Integer): TClass;
    function GetFieldCount: Integer;
    function GetMethodTable: Pointer;
    function GetMethod(Index: Integer): IVmtMethod;
    function GetMethodCount: Integer;
    function GetParentVmt: IVmtInfo;
    function GetInitTable: Pointer;
    function GetInitCount: Integer;
    function GetInitEntry(Index: Integer): IVmtInitEntry;
    function GetAutoTable: Pointer;
    function GetAutoCount: Integer;
    function GetAutoEntry(Index: Integer): IVmtAutoEntry;
    function GetTypeInfo: PTypeInfo;
    function GetIntfTable: Pointer;
    function GetInterfaceCount: Integer;
    function GetInterfaceEntry(Index: Integer): TInterfaceEntry;
    function GetVmt: Pointer;
    procedure PrintToStream(Stream: TInfoStream);
  end;

constructor TVmtInfo.Create(ClassRef: TClass);
begin
  fVmt := PVmt(ClassRef);
  Dec(fVmt);
end;

function TVmtInfo.GetInitRecord: IVmtInitRecord;
begin
  if fInitRecord = nil then
    fInitRecord := TVmtInitRecord.Create(Vmt.InitTable);
  Result := fInitRecord;
end;

有了以上的代码可以取的组件的任何信息,Delphi也正是凭此信息而工作的,[b][red]我们的LordEric[/red][/b][black]可否对此做一个详细的解释[/black][/black],也希望各位前辈对此做一个补充!  

来自:lance2000, 时间:2002-5-30 15:34:00, ID:1133290
偶写了个很烂的东西,很希望能让高手看一下偶的源代码,并给偶
提出点意见.
http://www.delphibbs.com/delphibbs/dispq.asp?lid=1132511  

来自:mypine, 时间:2002-6-3 12:30:00, ID:1140232
1. VCL控件开发的几个主要基类TComponent、TControl、TWinControl、TGraphicControl、TCustomControl的主要功能及各类用途!?

>>VCL Framework无疑是我见过的最棒的Framework,听朋友说, Java Library也不逊色,但是一想到, 后者也是Borland实现的, 就不会有什么惊奇了, 我一向信任Borland的东西。下面我解释一下, Borland对VCL Framework中几个主要类的行为与责任的分布解释一下:

    TObject   封装对象的创建与释放(主要是内存的分配, 对象内方法指针的定向->因为有些方法是多态的,所以需要指向父类的方法;), 另外还承担消息分派的能力,这就使得我们可以轻松地定义与发送自定义的消息;

    TPersistent   顾名思义,在这里面定义了对象序列化(DefineProperties)及分配(Assign)的初步框架,没有任何实现;

    TComponent  是VCL中非常经典的地方。

    其一,虽然Object Pascal本身不具有GC(Garbage Collect)的能力,而在OOP设计中, 对象的生命周期可以是说非常重要的一个问题, Java通过GC解决了这个问题,而VCL框架从TComponent向下, 利用框架本身解决了这个问题, 那就是对象链, TComponent及其子孙, 都有一个属性是Owner,这就是对象链中指向创建者的指针,实际上 ,这也符合在没有GC的语言中的对象生命周期控制的基本原理——Who created, who Destroyed!

    其二, TComponent实现了真正的对象序列化能力,与TFiler与TStream形成关联;后者是VCL中设计得比较精彩的地方——对流化媒体类型与流化方式及流化内容的合理解耦。同时, 它也是Design - Time与Run - Time形成的基础。

    其三, Design-Time 与 Running - Time的实现, 如果你的类型从TComponent继承下来, 那么便具有了在Design - Time工作的能力了,如果从TComponent的祖先继承下来, 则不具有。 明显的标志是ComponentState这个只读属性。  


2. ComponentState属性的用途

>>顾名思义, 用在设计Component时,与当前对象状态密切的对象行为判断。
3. 如果有一个属性为指向另一个类的实例(如TDataSource的Dataset属性), 要注意的事项

>>主要的注意是对象的生命周期的控制,见上面的原则,当然,有的时候,也可能稍有变通, 特别是碰到公共单一对象(Singlon模式的产物)的时候。
4. property宣告的具体心得及注意事项、Keyword Default及Stored的意义

>>属性的宣告建议:

    其一,属性的读取建议在一般情况下使用Get与Set方法, 而不直接从变数中得到——增加了对对象状态控制的能力(可以参见TDataSet类中的Active属性的SetActive方法里面,形成了对AfterClose事件的支持。另外, 这两个过程在有的时候设计为具有多态的能力, 会带来更好的效果——在TCustomConnection中的GetConnected方法,因为该类型还有多个继承者, 从而, Connected这个属性便具有了在不同情况下的不同的"连接了的?"的能力)。

    其二,Default是指,对象流化的时候, 缺省的保存值, Stored是指是否被流化(默认为是);

 

5. TControl与TWinControl的差异

>>后者具有了句柄(Windows中的一种标识符类型,此外指窗口句柄), 因此从TWinControl开始,便具有了所谓的Parent属性。

 
6. TWinControl中如何封装Windows窗体(或者说, Windows的消息通知(message call), 经过了什么过程, 成为Delphi的Method Call) ? Windows的消息处理机制?
或者另一个问法, 在一个Control中, 要处理消息(message), 除了定义消息函数 (procedure WMSetFocus(var Message: TWMSetFocus); message WM_SETFOCUS;) 外, 尚有那些方式?

>>    复写WinProc


7. 设计覆合式控件的注意事项

>>  覆合式控件?  不明白!
8. 对Windows基本窗体(Eidt, Button, ListBox....)的了解及说明?

>> 来自于Common Control, M$会不定时的更新, 形成了Windows界面的标准窗口, 在VCL中被得到了封装, 来自了TWinControl的继承, 因此, 它们每一个实际上都是一个Form(具有句柄)。
  

来自:goddy, 时间:2002-6-5 13:49:00, ID:1144572
原是我們四樓的考題,我去應憑不知會不會要我呢  

来自:real_clq, 时间:2002-6-5 14:43:00, ID:1144692
什么叫“自认为”高手高手...你会来么?  

来自:icool, 时间:2002-6-5 22:19:00, ID:1145560
对于从TGraphicControl继存来的TSpeedButton类控件,怎样才能得到其父类的Canvas属性。  

来自:subsky, 时间:2002-6-16 13:35:00, ID:1166467
真TNND涨见识!!!!!   

来自:xuzhudi, 时间:2002-7-7 13:51:00, ID:1191904
to subsky: 真TNND涨见识!!!!!

不要这么粗鲁,要用文明用语啊, 呵呵

to all  多些上面的众多老师, 受教, 受教啊  

来自:飞雪轩主, 时间:2002-7-13 18:14:00, ID:1201025
lorderic老兄的风格比较像台湾人,我以前跟台湾士通(MII)的程序员合作时他们
就像你这样子,日本人又不太一样,他们比较关心企业营业过程(我们叫商业流程),
你的问题我这样解答你看合不合适:
问题1,2,3,4,5,8没有太多的规律,需要实际经验,原因很简单
1。object pascal没有ansi标准,因此使自由发展的,不受任何限制。
2.Delphi现在的架构的形成有其历史原因,从Win31到sdk到dde到ole到com到.net人们的
  观念变化很大,看到那一个部分一定要结合产生时的历史背景,VCL实际上是几个时代
  的思想汇集的成果。
3.delphi的工具特性要超过语言特性,只是没有PB(大陆人爱用),ACCESS(日本人爱用),
  vf(美国人爱用)体现的更明显。
4。delphi的设计师人员流动也很大,不同时期的设计有当时设计师的主管因素,目前公认
   开发成本在3000万台币以上的项目很少有1个人能够完完全全了解系统的全貌,delphi的
   情况也类似。
5.存在的,未必是有规律的,至少delphi现在这个样子,历史原因的因素比较大,将来delphi
  很可能同时受J2EE,DOT NET标准的双重影响,现在clx和vcl都在向前发展。
问题6:最好不要深究,delphi是每两个版本变一次。最近的一次改动是delphi5,导致没有
      delphi4稳定,并且有内存泄漏(大陆好多人因此转向vc++,而vc++稳定的原因是它
      没有支持过com+,因为微软的程序员做不出来。)。delphi的各个版本比较大致是
      delphi6(功能好 ,稳定一般)>delphi4(功能一般,稳定好)>delphi5(功能好)>delphi3(一个时代,可惜太老)
      针对这个问题delphi7(delphi.net)一定又变。
问题7:看你是什么水平。
      VC++思想的人用DELPHI,每屏至少4个指针。
      VB思想的人用DELPHI,每UNIT至少1个数组。
      Java思想的人用DELPHI,每UNIT至少2个自定义class。
      日本人用DELPHI,必引用comobj,至少见到一个cells(Formula one或VSFlex Grid等).
      delphi思想的人用DELPHI,全部代码见不到指针,自定义procedure超过function.
      以下是两句玩笑话:
      台湾人用delphi,class不知道从哪里继承。
      大陆人用delphi,xml当数据库用,cells当stringgrid用,属性当变量用,方法当
      goto用,null用if转换,table看成数组,最严重的是没有时间轴的观念(程序在时间进行上
      是非常混乱的,包括程序起点、工作流的时间切片,事物的时间切片,工作周期的定义,
      最小工作时间片的定义--人事考勤/产量产能/计划实际,等等,都很混乱)
      最后说的可能得罪了不少朋友,先跟大家道个谦,其实我水平很一般。

                                      Sandy Suen

  

来自:samzw, 时间:2002-7-16 17:15:00, ID:1205521
"delphi思想的人用DELPHI,全部代码见不到指针",到处都是指针,怎么会见不到指针
:)  

来自:sandy suen, 时间:2002-7-16 20:02:00, ID:1205766
您批评的是,我看问题太表面了。
^_^  

来自:yyanghhong, 时间:2002-7-16 20:12:00, ID:1205773
我还是喜欢JAVA风格的code, 看上去很酷的样子,特别是加上几个interface,
帅呆了.  

来自:wang2855, 时间:2002-8-2 17:54:00, ID:1238892
pipi你好:
     [?]我做了一个控件,当我把属性设为default  False;时,我并不需要在Create事件
中重新设置,也没有什么错误发生,你所说的“
如果设置了default,你又没有在create设置相同的值,或者根本没有赋初值,那会出问题的
"是什么意思?
  

来自:Pipi., 时间:2002-8-3 8:29:00, ID:1239674
初始化的时候boolean如果没赋值,缺省是初始化为false,所以你的default false即使没有显式在create中赋值false
他也是false,所以不出问题。但这个不是好的习惯
你可以试试default true,如果在create中不给他赋值true,你在设计期设置这个属性为true,运行起来看是否会保存true就知道了  

来自:aizb, 时间:2002-9-24 0:42:00, ID:1342086
看到楼上回答的朋友不少,没有仔细看完,也来卖卖:

1.  VCL控件开发的几个主要基类TComponent、TControl、TWinControl、TGraphicControl、TCustomControl的主要功能及各类用途!?
TComponent:因封装了设计期的一些信息而使得可以在设计时使用,当然要在设计时使用还必须注册到Delphi的IDE控件面板,所以TComponent是所有可以放在控件面板上的类的基类。
实现了IInterface, IInterfaceComponentReference接品。
TControl:顾名思义,这才是真正的Delphi的"控件"。我们常说的Delphi控件应该就是从它来继承,它是所有可视类的基类,可以在运行时看见。它封装了几封了所有的鼠标消息和部份界面的消息、外壳消息。
另外最重要的是它填充装了所有的消息分发。
TWinControl:当然它就是窗口控件,对应着VC里的窗口类(我不太懂VC),也是在Windows中的具有唯一标识Handle的类,所有容器类和可获得焦点的类都是从它上面继承。
作为窗口控件,它当然封装了所有的窗口消息,比如键盘消息。
TGraphicControl:从TControl上继承下来,没有窗口句柄,但是增加了画布Canvas,通过Canvas封装了主要的图形绘制API函数。
TCustomControl:类似于TGraphicControl,不过它是从TWinControl继承下来的,有了窗口句柄.
它和TGraphicControl一样,只处理了WM_PAINT消息。
2.  ComponentState属性的用途
用于判断TComponent继承下来的类的状态,比如是否是设计期或者装载期等等。
3.  如果有一个属性为指向另一个类的实例(如TDataSource的Dataset属性), 要注意的事项
我想最重要应该是在写接品方法中调用另一个类实例的FreeNotification方法,经以便在另一个类实例析构的时候清空本类实例的相关属性(将相关成员字段设为nil)。
4.  property宣告的具体心得及注意事项、Keyword Default及Stored的意义
这方面的东东其实主要看个人喜好,我的感觉在宣告一个属性时应尽可能避免这个属性可以不能过写接口而改写,那样可能为这个属性改变量所作的努力将不起作用,
比如动态数组类型的属性:最好不要声时动态数组类型的属性,因为在Delphi中动态数组类型的数组其实和指针差不多,它可以直接操作这个属性而不会调用写接口,除非你用赋值符号为动态数组赋值(这在Delphi中应尽量避免使用),
如果确实有动态数组类型的属性,可以通过定义属性下标来将其转换成简单类型或复合类型的属性
而一些类属性,一般在写接口中需要使用Assign方法来赋值,比如大多数可视控件的Font属性,或部份控件的TPicture类型属性,而且这样的属性因为本身有Assign方法,可能不会使用赋值运算为其赋值(在Delphi中应尽量避免使用赋值运算对类实例赋值,
除非真的是要两个实例变量指向同一个实例),所有一般不仅需要处理写接品,还需要给这个属性所对应的成员字段定义OnChange事件。
至于Default指示,不用看楼上也具定说得很多,关键是要注意,它并不对属性对应的私有成员初始化,如果需要初始化,则需要在构造函数中进行。
它仅仅用来指示属性是否需要被流化以保存在dfm文件中,编译以资源的形式进入EXE,可以有效的减小EXE文件的容量,并提示程序加载速度。
Stored指示的作用与Default指示字相仿,不过Default只是指定一个值,如果属性值在设计期间与这个值相同,就不流化,而且Default只支持有限的几种简单定长类型数据。
而Stored而可以通过一个Boolean函数来检查设计期间的属性值是否需要流化,这个函数可以非常复杂。

5.  TControl与TWinControl的差异
TControl的和TWinControl其实在上面已经比较清楚了,主要就是一一个是父类,一个是子类,TWinControl比TControl增加了Handle和相关的方法和属性,以用相应的消息处理函数,
最主要的是,除是多了句柄之外,因为可以获得焦点,所以多了键盘相关的消息和方法。

6.  TWinControl中如何封装Windows窗体(或者说, Windows的消息通知(message call), 经过了什么过程, 成为Delphi的Method Call) ? Windows的消息处理机制?
或者另一个问法, 在一个Control中, 要处理消息(message), 除了定义消息函数 (procedure WMSetFocus(var Message: TWMSetFocus); message WM_SETFOCUS;) 外, 尚有那些方式?
这个可复杂了点,首先,TControl有于个属性WindowProc,其实它是一个事件,只不过Delphi中的所有类都没有把它放到published域,所以我们从没有在设计期间看到这个属性,
但是它的确存在,而且作用非常大,在TControl中的构造函数中,在重用了父类的构造代码后的第一行就是给这个事件赋了值,这个值是成员方法WndProc,这是一个动态方法,
可以重载,它完成了几乎所有鼠标消息和界面消息的分发.我们如果需要自己来处理这些分发,一种方法可以重载这个方法,另一种是自己定WindowProc事件句柄。
不过我便能愿意重载一些。其实到这里就可以明白,除了重载消息处理函数外,我们也可以载重WndProc方法来处理消息和重写WindowProc事件来处理消息。共至少有三种方法。

其他程序向Delphi编译的程序的窗口发的消息Delphi是如何能接收到的?请看CreateWnd方法中有一句WindowClass.lpfnWndProc := @InitWndProc;就是句告诉Windows这个窗口的消息由InitWndProc这个回调函数来处理,
而在InitWndProc这个函数中的一段汇编把它和TWinControl.FObjectInstance联系起来,再转到TWinControl.Create(AOwner: TComponent)中,第二行的FObjectInstance := Classes.MakeObjectInstance(MainWndProc);
才真正引出主角MainWndProc,它个函数很简单,就是触发WindowProc事件,把接收到的消息传给这个事件,再由个这事件来分发。好了说了一大通,但是太乱,可能不会有太多人能明白。
好在我们一般情况下不需要关心这些,只需要知道处理消息的三种方法就行了。

7.  设计覆合式控件的注意事项
说得简单点,就是注意谁是容器,谁是子对象就行了,在构告的时候把子对象的Parent属性和Owner设为容器,设计时就不会出现两个或者多个可操作纵的对象(而是只有一个唯一的对象可供用户操作)。

8.  对Windows基本窗体(Eidt, Button, ListBox....)的了解及说明?
关于这一点我倒没觉得有什么说的,人人都可说一大把。  

来自:jsxjd, 时间:2002-10-3 23:47:00, ID:1358975
关键还在于:
  Windows的消息处理机制,
  面向对象的原理。
  不同控件对资源的占用情况,
  …………………………  

来自:黎永欢, 时间:2002-10-6 0:56:00, ID:1360980
请你多些学习第三方组件的好东西,学习他们的方法和精神。  

来自:yaxich, 时间:2002-10-9 15:46:00, ID:1365920
to delnus:
小弟想看看您说的Delphi组件开发帮助,可否给小弟一份?
小弟的E-Mail: yaxich@sohu.com 或 yaxich_hot@hotmail.com  

来自:SupperDog, 时间:2003-1-23 16:01:00, ID:1595899
to delnus:
小弟想看看您说的Delphi组件开发帮助,可否给小弟一份?
小弟的E-Mail: synworld@sina.com.cn  

来自:NeutronDelphi, 时间:2003-1-25 13:01:00, ID:1599138
  从面向对象过渡到面向组件的程序设计,大家基本上开始适应。怎样作好一个安全稳定
的组件(Delphi组件),光靠学好Delphi是不行的。
  我认为Component可以说是Component,也可以说是Software.
  所以Component好不好关键靠设计,Component编写之前必须对整个Component进行
全面的规划。  

来自:wr960204, 时间:2003-7-2 16:19:00, ID:1997301
1.  VCL控件开发的几个主要基类TComponent、TControl、TWinControl、TGraphicControl、TCustomControl的主要功能及各类用途!?
  TComponent所有可在设计期间可看到的组件的祖先。
  TControl控件的祖先
  TWinControl所有有句柄的控件的祖先。
  TGraphicControl所有图形组建的祖先。没有句柄
  TCustomControl继承自TWinControl但是提供了画布属性
2.  ComponentState属性的用途
  ComponentState是组件的状态。一般在可视化设计使用的较多。可以知道当前正在读入,正在设计还是运行等等信息。
3.  如果有一个属性为指向另一个类的实例(如TDataSource的Dataset属性), 要注意的事项
   调用被指向组件的FreeNotification方法指明释放通知对象,和在组件自身的Notification方法。再释放时把该属性置空
4.  property宣告的具体心得及注意事项、Keyword Default及Stored的意义
   Default是告诉窗体流保存时把该属性保存下来,而不管其是否发生过变化(通常如果属性在设计期间为变化过,窗体文件是不保存的)。Stored则通过一个布尔值来确定是否保存。
5.  TControl与TWinControl的差异
    TWinControl从TControl继承而来。最大的差别就是多了句柄。可以处理各种消息。实际上各种TWinControl都是Windows的窗口的不同体现。
6.  TWinControl中如何封装Windows窗体(或者说, Windows的消息通知(message call), 经过了什么过程, 成为Delphi的Method Call) ? Windows的消息处理机制?
或者另一个问法, 在一个Control中, 要处理消息(message), 除了定义消息函数 (procedure WMSetFocus(var Message: TWMSetFocus); message WM_SETFOCUS;) 外, 尚有那些方式?
主要可以通过覆盖过程WndProc来处理消息
7.  设计覆合式控件的注意事项
  通过主控件的ComponentState判断是设计状态还是运行状态。以便表现出不同的表现。
8.  对Windows基本窗体(Eidt, Button, ListBox....)的了解及说明?
   这些都是通过窗体的风格来实现的。也就是覆盖GreateParams方法。
   在里面调用创建子类的方法CreateSubClass;用第二个参数通知系统窗体的风格。
   例如Edit就传一个'Edit'字符串就行了,Button就是字符串'Button'而ListBox就传递一个'LisBox'。通过这些参数系统将给我们分配不同风格的的窗口。省去了我们自己画窗体的麻烦。所以标准Windows控件都是由系统自动画出外观的。


写这么多累死了。下次问点有难度的好不好!  

来自:Afei1, 时间:2004-1-4 10:49:00, ID:2391654
这么好的帖子应该继续讨论
我来提下  

来自:wr960204, 时间:2004-1-5 11:19:00, ID:2393422
1.  VCL控件开发的几个主要基类TComponent、TControl、TWinControl、TGraphicControl、TCustomControl的主要功能及各类用途!?
TComponent是组件的祖先,一切在设计期间可见的组件(包括TControl、TWinControl、TGraphicControl、TCustomControl)全部派生于此,
TControl控件的祖先,一切可是化控件皆派生与此
TWinControl是Windows控件的祖先,从这个分支以后都是Windows窗体。都有句柄
TGraphicControl图形控件的祖先,没有据柄,但有画布(TCANVAS)
TCustomControl派生自TWinControl。所以也是窗体。同时带有画布属性

2.  ComponentState属性的用途
ComponentState顾名思义就是组件的状态,是一个集合属性。举个例子:例如包含csDesigning就说明现在是在设计期间,否则在运行期间。

3.  如果有一个属性为指向另一个类的实例(如TDataSource的Dataset属性), 要注意的事项
如果指向的是TComponent类的派生类实例,要注意覆盖Notification虚方法。在所指向的组件释放的时候把该属性设置为空(NIL)
也就是Operation=opRemove并且AComponent=属性所指向的组件的时候

4.  property宣告的具体心得及注意事项、Keyword Default及Stored的意义
Default是指不管属性是否有过改变都要保存到DFM文件中。
Stored通过一个布尔表达式的值来控制特性的存贮行为

5.  TControl与TWinControl的差异
TControl不是窗体,没有句柄
TWinControl及其派生类都使窗体,有句柄

6.  TWinControl中如何封装Windows窗体(或者说, Windows的消息通知(message call), 经过了什么过程, 成为Delphi的Method Call) ? Windows的消息处理机制?
或者另一个问法, 在一个Control中, 要处理消息(message), 除了定义消息函数 (procedure WMSetFocus(var Message: TWMSetFocus); message WM_SETFOCUS;) 外, 尚有那些方式?

在TWinControl中有一句FObjectInstance := Classes.MakeObjectInstance(MainWndProc);指定了处理方法,而MainWndProc又仅仅只是用异常包装了一下调用WindowProc。
在CreateWnd时,有一句WindowClass.lpfnWndProc := @InitWndProc;说明了InitWndProc这个回调函函数是用来处理窗口消息的。
InitWndProc有这样的代码
  asm
        PUSH    LParam                                        //
        PUSH    WParam                                        //
        PUSH    Message                                       //
        PUSH    HWindow                                       //
        MOV     EAX,CreationControl                           //
        MOV     CreationControl,0                             //上面的都是参数
        CALL    [EAX].TWinControl.FObjectInstance             //调用FObjectInstance所指向的方法也就是那个MainWndProc
        MOV     Result,EAX                                    //
  end;
 
7.  设计覆合式控件的注意事项
不要忘记了调用SetSubComponent方法,否者子控件的属性设置是保存不到DFM文件中的。
8.  对Windows基本窗体(Eidt, Button, ListBox....)的了解及说明?
不知道该怎么回答。反正我只知道通过覆盖CreateParams方法设置子参数
CreateSubClass(Params, 'EDIT');
CreateSubClass(Params, 'BUTTON');
CreateSubClass(Params, 'LISTBOX');
Windows会自动帮你变出他们的风格和一些特性  

来自:baseyueliang, 时间:2004-1-5 13:15:00, ID:2393714
不知哪位大侠知道对非发布组件属性如何读写到frm,Writer.WriteComponent(组件属性)出错,不知为何?  

来自:baseyueliang, 时间:2004-1-9 9:22:00, ID:2401687
问题:有关Delphi控件开发讨论, 自认为精通Delphi控件开发及VCL架构的高手请人内发表心得!? ( 积分:300, 回复:72, 阅读:2154 )
分类:控件 - 开发 ( 版主:cAkk, amo )

-----
怎么都不说话了呀?。。。  

来自:baseyueliang, 时间:2004-1-9 11:49:00, ID:2402134
问题:有关Delphi控件开发讨论, 自认为精通Delphi控件开发及VCL架构的高手请人内发表心得!? ( 积分:300, 回复:73, 阅读:2163 )
分类:控件 - 开发 ( 版主:cAkk, amo )  
来自:lorderic, 时间:2002-5-2 15:38:00, ID:1080798 [显示:小字体 | 大字体]  

本论总预算1000分, 想与此道高手结识, 有能者得之
请勿发表不相干言论, 分数只会分给内容最精辟正确之人; 没有具体言论者, 请勿回复; 相同意见, 只给第一个发表之人
 
------------
如果能发表精辟言论,再能解决实际高难度问题才是【真言论】,如果只是把VCL源代码拷到论坛上,并说“这代码好好哦,并列举:好好点1;好好点2。。”之类谁不会呢。
言有过之请见谅,下面是偶在开发控件时遇到的一个问题
http://www.delphibbs.com/delphibbs/dispq.asp?lid=2383056
  

来自:baseyueliang, 时间:2004-1-9 11:53:00, ID:2402148
正如目前的Delphi技术书籍中大都把VCL源代码拷过来而已,又有那些书籍中的哪些技术例子在Delphi帮助中不存在的(作者独创的)?  

来自:archonwang, 时间:2004-1-9 11:59:00, ID:2402167
俺不是高手,最近有一小本关于Component开发的英文资料正在翻译当中(大概180多页,第一次干难免疏漏),争取在3月前完成。  

来自:baseyueliang, 时间:2004-1-9 12:19:00, ID:2402231
archonwang:可否有电子版啊,可以的话发偶一份xukang2002@sohu.com谢了先  

来自:zeroyou, 时间:2004-1-9 12:45:00, ID:2402275
到此一游  

来自:ranger18, 时间:2004-1-11 1:03:00, ID:2404748
先听我说完
以后将是.NET的天下,窃以为不必再浪费时间去研究VCL的部件库了,市面上有好的只管拿来用,花时间去学学.NET的CLR吧,有精力就去钻MSIL......
...砖头来了,快溜...  

来自:lzhuan, 时间:2004-1-11 3:16:00, ID:2404776
楼上也不必就要闪人^_^
学习VCL架构重在其设计思想.
这个用在那一种语言中都适用.
做ERP也有一段时间了真实感觉到设计的重用.
  

来自:ranger18, 时间:2004-1-11 13:02:00, ID:2405019
我也是做ERP的
VCL实际上是一个WINDOWS API的包装
我认为VCL并不深奥,学习它往往只见树木不见森林
C#是一种全新的语言,吸收了C++、Pascal、Java和VB的优点,虽然现在还不够强大,但我认为该种语言的设计思想是先进的(我说的是语言的),可以说代表了以后软件设计的发展方向。Delphi7是传统编程的终结者,代表了传统编程的最高境界,但Delphi8就开始对微软的.NET投降了,它自己都不坚持,屈服于微软的强大,我们又怎么支持他呢?  

来自:dekit, 时间:2004-1-16 10:01:00, ID:2414338
本人以为CLR的问题比DELPHI的还要多.
谁知道你什么时候写的C#给人反编译了.
WIN32并不会因此而终结.WIN32还会陪者我们走更远.
软件的发展是要兼容的.因此在WINDOWS上开发我还是用
DELPHI的.^o^


我开发的多层应用控件.请大家提提意见.
 http://www.dekit.net
 谢谢  

来自:lincats, 时间:2004-2-5 12:55:00, ID:2437650
也许C#设计理念很先进,可它是后来的,当然会比java更好些,但是大家都在发展中,我只选择成熟的!另外,我痛恨Microsoft!假如Linux平台足够成熟了,我将彻底告别Microsoft  

来自:hardware007, 时间:2004-2-5 13:01:00, ID:2437672
学习  

来自:WilliamGui, 时间:2006-1-2 21:09:46, ID:3316318
To lorderic 及 各位前辈:
  好不容易找到你们。
  不知我回贴后,你们是否还可以收到e-mail。我搞数据库开发,主要是ERP方面,当然是用Delphi。Delphi这东西即叫人又爱又恨,没办法,我硬着头皮看了看VCL的DB、ADODB等单元,写得很妙,不过还有不少不懂的地方,在此希望大家联系我,请教一二。我的最终目的,是改写ADO之类的数据集控件,因为数据库方面的编程也是实用的。
  我的联系方式:
QQ:4980688 (晚上在线,请直接说明来意)
e-mail: williamgui@e-erpchina.com
我的个人网站: http://www.e-erpchina.com/
0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:775061次
    • 积分:9659
    • 等级:
    • 排名:第1933名
    • 原创:96篇
    • 转载:463篇
    • 译文:1篇
    • 评论:86条
    最新评论