我的应用程序有一个TQuery组件,我需要在它的AfterScroll()事件中做一些事情:

void __fastcall TFormMain::Query1AfterScroll(TDataSet *DataSet)
{
    // do stuff here...
}


问题是,当我执行以下操作时,AfterScroll事件显然被触发了两次:

Query1->Active = true; // first call to AfterScroll
Query1->Locate( /* some arguments here */ ); // second call


注意:修改SQL查询而不是Locate()是NO选项

我不想处理AfterScroll的第一个调用,因此我正在寻找一种仅处理第二个的优雅方法。

我的第一个想法是使用AfterOpen()事件动态连接AfterScroll Event处理程序:

__fastcall TFormMain::TFormMain(TComponent* Owner)
: TForm(Owner)
{
    Query1->AfterScroll = 0;
}

void __fastcall TFormMain::Query1AfterOpen(TDataSet *DataSet)
{
     Query1->AfterScroll = Query1AfterScroll;
}


该解决方案看起来不错,但不起作用,因为在AfterAfter离开时将立即调用AfterScroll。

编辑:

我知道我可以设置一些标志来禁止AfterScroll从Executing中执行代码(这是我现在所做的(以及:下面第一个答案的描述方式)),但是我认为应该有一个更优雅的方法,少出错的方法。

但是经过一番研究,我担心周围没有更好的解决方案。

我的问题是:

捕获正确的AfterScroll调用的正确方法是什么? (在Locate(...)之后调用的那个)

最佳答案

下面的Delphi代码覆盖了TAdoQuery的标准行为(但应该可以使用
与其他任何支持Locate()的TDataSet后代),以便仅立即调用AfterScroll事件
呼叫TAdoQuery.Locate之后。

基本上,它将覆盖TAdoQuery DoAfterScroll,以便仅在设置了布尔标志FHandleScrollAfterLocate时才调用继承的方法。 DoAfterScroll是TDataSet方法,用于调用任何已设置的AfterScroll处理程序。该标志在覆盖的Locate函数中设置为True,并在每次调用DoAfterScroll时清除。

我敢肯定,如果您想更改AfterScroll的调用条件,您会明白的。

  type
    TAdoQuery = class(ADODB.TAdoQuery)
    private
      FHandleScrollAfterLocate: Boolean;
    protected
      property HandleScrollAfterLocate : Boolean read FHandleScrollAfterLocate;
      function Locate(const KeyFields: string; const KeyValues: Variant;
        Options: TLocateOptions): Boolean; override;
      procedure DoAfterScroll; override;
    public
    end;

    TForm1 = class(TForm)
      DataSource1: TDataSource;
      DBGrid1: TDBGrid;
      DBNavigator1: TDBNavigator;
      ADOConnection1: TADOConnection;
      AdoQuery1: TADOQuery;
      AdoQuery1ID: TIntegerField;
      AdoQuery1name: TStringField;
      btnLocate: TButton;
    [etc]
    [...]

    { TAdoQuery }

    procedure TAdoQuery.DoAfterScroll;
    begin
      try
        if FHandleScrollAfterLocate then
          inherited;
      finally
        FHandleScrollAfterLocate := False;
      end;
    end;

    function TAdoQuery.Locate(const KeyFields: string;
      const KeyValues: Variant; Options: TLocateOptions): Boolean;
    begin
      FHandleScrollAfterLocate := True;
      Result := inherited Locate(KeyFields, KeyValues, Options);
    end;

    procedure TForm1.AdoQuery1AfterScroll(DataSet: TDataSet);
    begin
      Caption := 'Scrolled';
    end;

    procedure TForm1.btnLocateClick(Sender: TObject);
    begin
      AdoQuery1.Locate('ID', 5, []);
    end;

09-29 21:12