有关Delphi控件开发讨论, 自认为精通Delphi控件开发及VCL架构的高手请人内发表心得!?(300分)

  • 主题发起人 主题发起人 lorderic
  • 开始时间 开始时间
3.如果有一个属性为指向另一个类的实例(如TDataSource的Dataset属性), 要注意的事项
我最为困惑的就是此问题,不是要注意什么,而是怎么实现这样的属性?
《Delphi 5开发人员指南》上没有该内容,还请大家指教!
 
创建一个Canvas,然后
Canvas.Handle:=GetDc(Self.Handle)
 
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来访问property,stored不用说了是要不要将property value放入.dfm中的意思;
5.说起来可以讲一篇文章,一句话TWinControl继承自TControl加一个最重要的东东就是handle;
6.delphi的将message call 通过将全局的windows窗口过程,很巧妙的化为了自身类的方法,最核心的函数是makeobjectinstance这个东东,还用到了链表,要处理消息除了定义函数还可以处理procedure WndProc(var Message: TMessage);这个类的窗口方法来得到;
7.注意对象的释放问题;
8.太多了不想说了。
 
这么多!Delphi开发人员指南上全都有,好书呀好书。[:D]
另外多看看VCL的源码,比什么都强。
只要你能好好研究一下TListBox,TDataset之类的源代码,你就是高手了![8D]
 
[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来达到目的,
甚至可以使用操作系统的钩子函数。

 
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中根据消息号码调用相应的过程句柄(事件).
 
看vcl源代码比较好
 
========================================
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属性。
它们最常被用作控件数组的。
 
[red]To::LordEric[/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也正是凭此信息而工作的,[red]我们的LordEric[/red][black]可否对此做一个详细的解释[/black][/black],也希望各位前辈对此做一个补充!
 
偶写了个很烂的东西,很希望能让高手看一下偶的源代码,并给偶
提出点意见.
http://www.delphibbs.com/delphibbs/dispq.asp?lid=1132511
 
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(具有句柄)。
 
原是我們四樓的考題,我去應憑不知會不會要我呢
 
什么叫“自认为”高手高手...你会来么?
 
对于从TGraphicControl继存来的TSpeedButton类控件,怎样才能得到其父类的Canvas属性。
 
真TNND涨见识!!!!!
 
to subsky: 真TNND涨见识!!!!!

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

to all 多些上面的众多老师, 受教, 受教啊
 
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

 
"delphi思想的人用DELPHI,全部代码见不到指针",到处都是指针,怎么会见不到指针
:)
 
您批评的是,我看问题太表面了。
^_^
 

Similar threads

D
回复
0
查看
2K
DelphiTeacher的专栏
D
D
回复
0
查看
1K
DelphiTeacher的专栏
D
D
回复
0
查看
2K
DelphiTeacher的专栏
D
D
回复
0
查看
1K
DelphiTeacher的专栏
D
D
回复
0
查看
1K
DelphiTeacher的专栏
D
后退
顶部