Delphi --技巧探索:
{ No. 1 }
创建模式窗体的句子:
class procedure TMyForm.RunForm(AObj1, AObj2: TObject);
var
vForm: TMyForm;
begin
vForm := TMyForm.Create(Application);
with vForm do
Try
InitForm(AObj1, AObj2);
ShowModal;
Finally
Free;
end;
end;
//*说明:
通过class声明的函数,类似与VC中的静态函数;使用语句:TMyForm.RunForm(vObj1, vObj2);
其他具体的,参考:Delphi 帮助中的,class 类说明。
强调这个惯用法,就是为了:
1、如果此窗体在多处被使用,那么可以保证统一都调用此段代码;
2、如果功能上有所修改,比如:根据ShowModal的返回值不同进行处理,那么只修改此函数就行了。
3、程序封装性好,易于维护和工作交接。*//
{ No. 2 }//Tag 的使用
窗体工具栏按钮事件的响应
procedure TMyForm.RunOperate(ATag: Integer);
begin
Case ATag of
1: MyButton.Color := clRed;
2: MyButton.Color := clGreen;
3: MyButton.Color := clBlack;
end;
end;
procedure TMyForm.ToolBtnClick(Sender: TObject);
begin
RunOperate(TControl(Sender).Tag);
end;
如果你在某下拉菜单中,也需要执行类似功能则
procedure TMyForm.MenuItemClick(Sender: TObject);
begin
RunOperate(TMenuItem(Sender).Tag);
end;
//*说明:
1、结构清晰
2、相关的信息集中,比较容易查错、修改和维护
3、提高程序的适应、扩展能力;比如现在要求不在工具栏按钮中实现,而要求在不同按钮中实现,则修改容易。
建议:每个分类后面只跟一行或不多的几行代码,如果代码比较多,使用过程函数替代。
比较有意思的是,我经常如下写:
Case btnMyButton.Visible of
{ 显示 } True: ...
{不显示} False: ...
end; *//
{ No. 3 }//事件指针做参数
//对于列表等的读取使用事件指针的方式
type
TDataSetEvent = procedure (DataSet: TDataSet; AIndex, ACount: Integer) of Object;
//从 TADOQuery派生而来的类
procedure TMyADOQuery.EnumRecord(AWhereStr: String; APro: TDataSetEvent);
begin
Close;
SQL.Clear;
SQL.Add('Select * From Table1');
if AWhereStr <> '' then
SQL.Add('Where ' + AWhereStr);
Open;
While Not Eof do
begin
if Assigned(APro) then APro(Self, RecNo, RecordCount);
Next;
end;
Close;
end;
对TIdentMapEntryd类型的数组定义和使用,Delphi中,有比较完善的实现。
TIdentMapEntry = record
Value: Integer;
Name: String;
end;
1、数组定义:array[0..ArrMax] of TIdentMapEntry
可参考:Controls单元中:
Cursors: array[0..21] of TIdentMapEntry = (
...
);
2、两个互相求值得函数: IntToIdent(由Value求Name)和 IdentToInt(由Name求Value);
具体应用可以参考:IdentToCursor 和 CursorToIdent。
3、应用:a、直接应用此树组定义方式和数组操纵函数;b、学习函数中,对数组访问和操纵的方式。c、学习标准的信息访问函数定义: function IntToIdent(Int: Longint; var Ident: string; const Map: array of TIdentMapEntry): Boolean; 具体返回的信息由参数方式返回回来,至于访问是否有效,则通过函数的布尔返回值加以判断。
实现: TCad 为由抽象类继承下来的第一层控件类
function TCad.CadPerform(Msg: Cardinal; WParam, LParam: Longint): Longint;
begin
Case Msg of
My_Message1: Result := MyMessage1(WParam, LParam);
My_Message2: Result := MyMessage2(WParam, LParam);
end;
end;
对于,TPoint继承自 TCad, CadPerform函数实现如下。
function TPoint.CadPerform(Msg: Cardinal; WParam, LParam: Longint): Longint;
begin
Case Msg of
My_Message1: Result := MyMessage1(WParam, LParam); //屏蔽了TCad中此操作类型的处理
My_Message3: Result := MyMessage3(WParam, LParam);
else Result := inherited CadPerform(Msg, WParam, LParam);
end;
end;
//解决方案,参考TWinControl中,属性或状态改变时,通知所有子Controls的处理机制:
procedure TWinControl.NotifyControls(Msg: Word);
var
Message: TMessage;
begin
Message.Msg := Msg;
Message.WParam := 0;
Message.LParam := 0;
Message.Result := 0;
Broadcast(Message);//广播当前的变更消息
end;
其中:
procedure TWinControl.Broadcast(var Message);
var
I: Integer;
begin
for I := 0 to ControlCount - 1 do
begin
Controls[I].WindowProc(TMessage(Message));
//改为:with TMessage(Message) do Cads[I].CadPerform(msg, WParam, LParam);
if TMessage(Message).Result <> 0 then Exit;
end;
end;
但是,我们处理图形对象时,可能会直接调用 Cads 的CanPerform公共函数即可
{ No. 14 }需要时,动态创建你的对象
比如:
http://www.delphibbs.com/keylife/iblog_show.asp?xid=824 中的
//*******方案二 当需要的时候在创建属性窗体
uses
...
fProperty;
type
TfrmMyMap = class
...
procedure OnfrmMyMapDestroy(Sender: TObject);
procedure OnMapGeoSelected(AGeo: TGeometry);
private
FfrmProperty: TfrmProperty;
procedure ShowPropertyForm(aVisible: Boolean);
public
end;
procedure TfrmMyMap.ShowPropertyForm(aVisible: Boolean);
begin
if Not Assigned(FfrmProperty) then FfrmProperty := TfrmProperty.Create(Application);
FfrmProperty.Visible := aVisible;
end;
procedure TfrmMyMap.OnfrmMyMapDestroy(Sender: TObject);
begin
if Assigned(FfrmProperty) then FfrmProperty.Free;
end;
procedure TfrmMyMap.OnMapGeoSelected(AGeo: TGeometry);
begin
if Assigned(FfrmProperty) then FfrmProperty.MyRefresh(AGeo);
end;