zoukankan      html  css  js  c++  java
  • 对delphi中的数据敏感控件的一点探索

      一直对delphi数据敏感控件很好奇,感觉很神奇。只要简单设置一下,就显示和编辑数据,不用写一行代码。

    如果不用数据敏感控件,编辑一个表字段数据并保存,我相信应用如下代码。

    Table1.edit,

    Table1.fieldByName (‘***’) .AsString:= ‘***’;

    //Table1.Next;//在内部如果是edit状态,则调用Post.

    Table1.Post;

    我也相信数据敏感控件从Table端看也应该逃不出以上方法和步骤。

    1、  首先,调用edit,使数据集处于编辑状态

    2、  第二,给一个字段赋值

    3、  第三,调用Post保存到数据库中;

    事实上vcl中也是如此处理。

    为了说明举一个简单的例子,在一个Edit框中显示并能编辑数据。

    在TForm1OnCreate中,Edit1设置字段1的内容。

    procedure  TForm1OnCreate(Sender: TObject);

    Begin

      Table1.Open;

      Table1.First;

      Edit1.Text := Table1.FieldByName(‘字段1’).AsString;

    End;

    那么在Edit1框中编辑数据的时候,调用edit过程。

    procedure  TForm1.Edit1KeyPress(Sender: TObject; var Key: Char);

    begin

       if  (Table1. State = dsBrowse) then Table1.Edit;//数据集在浏览状态时,调用Edit进入编辑状态

    end;

    接下来应给字段赋值,在哪里呢,还好Edit1有一个事件OnExit,在Edit1失去焦点的给字段赋值。

    TForm1.Edit1Exit(Sender: TObject);

    Begin

      Table1.FieldByName(‘字段1’).AsString := Edit1.Text;

    End;

    接下就要保存了,可以在按钮OnClick中处理了。

    procedure TForm1.Button1Click(Sender: TObject);

    begin

    if  (Table1. State = dsEdit) then Table1.Post;// 数据集在状编辑态时保存

    Table1.Close;

    end;

    这也算数据敏感控件,也太简陋了,不过说回来,这很能说明问题。

    数据敏感控件分二部分,第一部分是控件的变化要反应到数据集,第二部分是数据集的变化要反应到控件中去,要相互作用。 

    现要让我们看看VCL源码中TDBEdit中处理。

    第一部分控件到数据集。

    procedure TDBEdit.KeyDown(var Key: Word; Shift: TShiftState);

    begin

      inherited KeyDown(Key, Shift);

      if (Key = VK_DELETE) or ((Key = VK_INSERT) and (ssShift in Shift)) then

        FDataLink.Edit;//注意这里

    end;

    procedure TDBEdit.KeyPress(var Key: Char);

    begin

      inherited KeyPress(Key);

      if (Key in [#32..#255]) and (FDataLink.Field <> nil) and

        not FDataLink.Field.IsValidChar(Key) then

      begin

        MessageBeep(0);

        Key := #0;

      end;

      case Key of

        ^H, ^V, ^X, #32..#255:

          FDataLink.Edit; //注意这里

        #27:

          begin

            FDataLink.Reset;

            SelectAll;

            Key := #0;

          end;

      end;

    end;

    其中TDataLink.EditàTFieldDataLink.EditàTFieldDataLink.EditàTDataLink.EditàTDataSource.EditàTDataSet.Edit

     

    最终调用TDataSet.edit,使数据集处于编辑状态

     

    字段赋值过程先看CMExit消息过程;

     

    procedure TDBEdit.CMExit(var Message: TCMExit);

    begin

      try

        FDataLink.UpdateRecord; //注意这里

      except

        SelectAll;

        SetFocus;

        raise;

      end;

      SetFocused(False);

      CheckCursor;

      DoExit;

    end;

     

    在FDataLink.UpdateRecord中究竟做了什么,让我们看看代码。

     

    procedure TDataLink.UpdateRecord;

    begin

      FUpdating := True;

      try

        UpdateData; //注意这里

      finally

        FUpdating := False;

      end;

    end;

     

    让我们再看UpdateData是个虚函数,看它的继承类TFieldDataLink处理。

     

    procedure TFieldDataLink.UpdateData;

    begin

      if FModified then

      begin

        if (Field <> nil) and Assigned(FOnUpdateData) then FOnUpdateData(Self);

        FModified := False;

      end;

    end;

     

    再往下看

     

    constructor TDBEdit.Create(AOwner: TComponent);

    begin

      …..

      FDataLink.OnUpdateData := UpdateData; //注意这里

    …….

    End;

     

    procedure TDBEdit.UpdateData(Sender: TObject);

    begin

      ValidateEdit;

      FDataLink.Field.Text := Text; //注意这里,哈哈终于看到了

    end;

     

    从上面我们可以看出TDBEdit给一个字段赋值过程。

    TDBEdit.CMExità TDataLink.UpdateRecord à TFieldDataLink.UpdateData àTDataLink.OnUpdateDataà TDBEdit.UpdateData àTDataLink.Field.Text := Text

    层层调用终于给字段赋值了。

     

     

    第二部分从数据集到控件,为了和数据敏感控件交互,数据集TDataSet中定义了一系列数据事件。TDataSet的打开,关闭,编辑,插入,删除,取消,数据集的滚动,最终会通知数据敏感控件,让数据敏感控件有机会改变自己。

     因此TDBEdit中有一个成员变量FFieldDataLink来接收数据集TDataSet中的数据事件,而FFieldDataLink是从TDataLink继承下来的, 让我们看看最主要的一个TDataLink.DataEvent过程

    procedure TDataLink.DataEvent(Event: TDataEvent; Info: Longint);

    var

      Active, First, Last, Count: Integer;

    begin

      if Event = deUpdateState then UpdateState else

        if FActive then

          case Event of

            deFieldChange, deRecordChange:

              if not FUpdating then RecordChanged(TField(Info));

            deDataSetChange, deDataSetScroll, deLayoutChange:

              begin

               ……

                case Event of

                  deDataSetChange: DataSetChanged;

                  deDataSetScroll: DataSetScrolled(Count);

                  deLayoutChange: LayoutChanged;

                end;

              end;

            deUpdateRecord:

              UpdateRecord;

            deCheckBrowseMode:

              CheckBrowseMode;

            deFocusControl:

              FocusControl(TFieldRef(Info));

          end;

    end;

    下面是主要数据事件的说明。

    deFieldChange      一个字段数值已改变。

    deRecordChange     当前记录的内容已改变。

    deDataSetChange    例如调用. Insert,delet,edit等时发生

    deDataSetScroll      

  • 相关阅读:
    Web API 配置Help Page
    Web API Help Page Install WebApiTestClient 简单的测试客户端
    开始一个简单的ASP.NET Web API 2 (C#)
    一些有用的huginn Agent
    jsp填坑:找不到属性
    Oracle学习笔记
    阿里云服务器端配置TensorFlow & jupyter
    重启部署在阿里云上的huginn
    centos升级python2.7到3.6之后造成yum命令报错
    取消layUI中日期选择控件默认填充日期
  • 原文地址:https://www.cnblogs.com/jijm123/p/7538989.html
Copyright © 2011-2022 走看看