Delphi 赢得';t刹住咔嗒声

Delphi 赢得';t刹住咔嗒声,delphi,events,Delphi,Events,好的,我有一个函数,它向我返回TMouseEvent类型 我需要执行返回的tmouse事件,但我不知道如何执行 返回事件的简单函数: function OMDold(obj: TObject): TMouseEvent begin ... //some operations on obj result := obj.OnMouseDown; //there is casting necessary, I skip it for simplify end; 当前事件设置为OMDn

好的,我有一个函数,它向我返回TMouseEvent类型

我需要执行返回的tmouse事件,但我不知道如何执行

返回事件的简单函数:

function OMDold(obj: TObject): TMouseEvent
  begin
  ... //some operations on obj 
  result := obj.OnMouseDown; //there is casting necessary, I skip it for simplify
end; 
当前事件设置为OMDnew,如下所示:

procedure TfmAPRBasedForm.TSDragEvent(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
begin
  if something then dosomething
  else
    begin
      Sender.OnMouseDOwn := OMDold // OMDold in most cases returns null but its ok I just want to clear custom event from the object 
      //line below is a point of my question - the one I used doesnt work
      TButton(Sender).OnMouseDown(Sender,Button,Shift,X,Y) //this line throws Access viloation at me
    end;
end;

我正在努力实现的目标:

  • 获取mousedown事件的默认按钮并将其存储在一些记录数据中

  • 将ONMouseDown事件更改为自定义

  • 在自定义事件过程中,有一个条件-如果鼠标按下是拖动,我执行拖动代码,如果不是,我将继续普通单击

  • 要继续使用公共单击,我希望恢复默认事件并重新执行它,以便可以执行单击


  • 就是这样

    只需通过参数直接调用它:

    procedure TfmAPRBasedForm.TSDragEvent(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
    begin
      if something then dosomething
      else
        begin
          TButton(Sender.OnMouseDOwn) := OMDold // OMDold in most cases returns nil (not null) but its ok I just want to clear custom event from the object 
          //line below is a point of my question - the one I used doesnt work
          If Assigned(TButton(Sender).OnMouseDown) then // Check if there is really an TMouseEvent
            TButton(Sender).OnMouseDown(Sender,Button,Shift,X,Y) //Call only when Event exist
        end;
    end;
    
    如果您在OMDOld中使用按钮、Shift、X、Y,并且需要dragEvent中当前值以外的值,例如删除ssShift等等,则可能需要更改按钮、Shift、X、Y

    如果您的OMDold存储为TMethod,则可以使用:

    TMouseEvent(OMDOld)(Sender,Button,Shift,X,Y);
    
    下面是一个经过调整的完整测试示例,以显示您希望以类似方式实现的目标:

    Unit Unit4;
    
    interface
    
    uses
      Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
      Dialogs, StdCtrls;
    
    type
      TForm4 = class(TForm)
        btn1: TButton;
        btn2: TButton;
        procedure FormCreate(Sender: TObject);
        procedure btn1MouseDown(Sender: TObject; Button: TMouseButton;
          Shift: TShiftState; X, Y: Integer);
        procedure btn2MouseDown(Sender: TObject; Button: TMouseButton;
          Shift: TShiftState; X, Y: Integer);
      private
        { Private declarations }
        procedure NewMouseDown(Sender: TObject; Button: TMouseButton;
          Shift: TShiftState; X, Y: Integer);
      public
        { Public declarations }
        OMDold : TMouseEvent;
        IsNew : Boolean;
      end;
    
    var
      Form4: TForm4;
    
    implementation
    
    {$R *.dfm}
    
    procedure TForm4.FormCreate(Sender: TObject);
    begin
      OMDold := btn1.OnMouseDown;
      btn1.OnMouseDown := NewMouseDown;
      IsNew := True;
    end;
    
    procedure TForm4.NewMouseDown(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
    begin
      if IsNew then
        ShowMessage('New Method!')
      else if Assigned(OMDold) then
        OMDold(Sender,Button,Shift,X,Y);
    end;
    
    procedure TForm4.btn1MouseDown(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
    begin
      ShowMessage('Original Method!');
    end;
    
    procedure TForm4.btn2MouseDown(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
    begin
      IsNew := not IsNew;
    end;
    
    end.
    

    只需通过参数直接调用它:

    procedure TfmAPRBasedForm.TSDragEvent(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
    begin
      if something then dosomething
      else
        begin
          TButton(Sender.OnMouseDOwn) := OMDold // OMDold in most cases returns nil (not null) but its ok I just want to clear custom event from the object 
          //line below is a point of my question - the one I used doesnt work
          If Assigned(TButton(Sender).OnMouseDown) then // Check if there is really an TMouseEvent
            TButton(Sender).OnMouseDown(Sender,Button,Shift,X,Y) //Call only when Event exist
        end;
    end;
    
    如果您在OMDOld中使用按钮、Shift、X、Y,并且需要dragEvent中当前值以外的值,例如删除ssShift等等,则可能需要更改按钮、Shift、X、Y

    如果您的OMDold存储为TMethod,则可以使用:

    TMouseEvent(OMDOld)(Sender,Button,Shift,X,Y);
    
    下面是一个经过调整的完整测试示例,以显示您希望以类似方式实现的目标:

    Unit Unit4;
    
    interface
    
    uses
      Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
      Dialogs, StdCtrls;
    
    type
      TForm4 = class(TForm)
        btn1: TButton;
        btn2: TButton;
        procedure FormCreate(Sender: TObject);
        procedure btn1MouseDown(Sender: TObject; Button: TMouseButton;
          Shift: TShiftState; X, Y: Integer);
        procedure btn2MouseDown(Sender: TObject; Button: TMouseButton;
          Shift: TShiftState; X, Y: Integer);
      private
        { Private declarations }
        procedure NewMouseDown(Sender: TObject; Button: TMouseButton;
          Shift: TShiftState; X, Y: Integer);
      public
        { Public declarations }
        OMDold : TMouseEvent;
        IsNew : Boolean;
      end;
    
    var
      Form4: TForm4;
    
    implementation
    
    {$R *.dfm}
    
    procedure TForm4.FormCreate(Sender: TObject);
    begin
      OMDold := btn1.OnMouseDown;
      btn1.OnMouseDown := NewMouseDown;
      IsNew := True;
    end;
    
    procedure TForm4.NewMouseDown(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
    begin
      if IsNew then
        ShowMessage('New Method!')
      else if Assigned(OMDold) then
        OMDold(Sender,Button,Shift,X,Y);
    end;
    
    procedure TForm4.btn1MouseDown(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
    begin
      ShowMessage('Original Method!');
    end;
    
    procedure TForm4.btn2MouseDown(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
    begin
      IsNew := not IsNew;
    end;
    
    end.
    

    停止OnMouseDown运行CLick事件的示例过程:

    procedure TForm1.CustomowyEvent(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
    begin
    if (DragDetectPlus(TWinControl(Sender))) then ShowMessage('detected drag!')
    
    else
      begin
        TButton(Sender).OnMouseDown := DME;
        TButton(Sender).OnClick(Sender);
      end;
    end;
    

    TButton(Sender)。OnClick(Sender)
    运行单击,因此如果我们不想拖动它,基本上可以单击

    停止OnMouseDown运行CLick事件的示例过程:

    procedure TForm1.CustomowyEvent(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
    begin
    if (DragDetectPlus(TWinControl(Sender))) then ShowMessage('detected drag!')
    
    else
      begin
        TButton(Sender).OnMouseDown := DME;
        TButton(Sender).OnClick(Sender);
      end;
    end;
    

    TButton(Sender)。OnClick(Sender)
    运行单击,因此如果我们不想拖动它,基本上可以单击

    分别解决所有问题部分:

  • 获取按钮默认值
    OnMouseDown
    事件并将其存储在一些记录数据中

    将专用字段添加到表单声明中,并将旧事件分配给它:

      private
        FOldButtonOnMouseDown: TMouseEvent;
      end;
    
    ...
    
      FOldButtonOnMouseDown := Button.OnMouseDown;
    
  • OnMouseDown
    事件更改为自定义

    将自定义事件处理程序分配给
    OnMouseDown
    属性:

      private
        procedure NewButtonMouseDown(Sender: TObject; Button: TMouseButton;
          Shift: TShiftState; X, Y: Integer);
      end;
    
    ...
    
      Button.OnMouseDown := NewButtonMouseDown;
    
  • 在自定义事件过程中,有一个条件-如果鼠标按下是一个拖动,我将执行拖动代码,如果不是,我将继续普通单击

    测试是否分配了原始事件,如果是,则调用它:

    procedure TForm1.NewButtonMouseDown(Sender: TObject; 
      Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
    begin
      if DragCondition then
        ExecuteDragCode
      else
        if Assigned(FOldButtonOnMouseDown) then
          FOldButtonOnMouseDown(Sender, Button, Shift, X, Y);
    end;
    
  • 要继续使用公共单击,我想恢复默认事件并重新运行它,以便可以执行单击

    还原事件:

    Button.OnMouseDown := FOldButtonOnMouseDown;
    

  • 将这一切结合在一起是您的下一个挑战。这尤其取决于drag stuf的实现方式,但您可以看看我在其中临时交换了
    OnMouseUp
    事件以撤消所有更改。

    分别解决所有问题部分:

  • 获取按钮默认值
    OnMouseDown
    事件并将其存储在一些记录数据中

    将专用字段添加到表单声明中,并将旧事件分配给它:

      private
        FOldButtonOnMouseDown: TMouseEvent;
      end;
    
    ...
    
      FOldButtonOnMouseDown := Button.OnMouseDown;
    
  • OnMouseDown
    事件更改为自定义

    将自定义事件处理程序分配给
    OnMouseDown
    属性:

      private
        procedure NewButtonMouseDown(Sender: TObject; Button: TMouseButton;
          Shift: TShiftState; X, Y: Integer);
      end;
    
    ...
    
      Button.OnMouseDown := NewButtonMouseDown;
    
  • 在自定义事件过程中,有一个条件-如果鼠标按下是一个拖动,我将执行拖动代码,如果不是,我将继续普通单击

    测试是否分配了原始事件,如果是,则调用它:

    procedure TForm1.NewButtonMouseDown(Sender: TObject; 
      Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
    begin
      if DragCondition then
        ExecuteDragCode
      else
        if Assigned(FOldButtonOnMouseDown) then
          FOldButtonOnMouseDown(Sender, Button, Shift, X, Y);
    end;
    
  • 要继续使用公共单击,我想恢复默认事件并重新运行它,以便可以执行单击

    还原事件:

    Button.OnMouseDown := FOldButtonOnMouseDown;
    

  • 将这一切结合在一起是您的下一个挑战。这尤其取决于drag stuf是如何实现的,但您可以看看我在其中还临时交换了
    OnMouseUp
    事件以撤消所有更改。

    为什么不直接调用
    OMDnew
    。你可以这样做,你知道。直接调用
    OMDnew(发送者、按钮、shift、x、y)
    有什么问题吗?我的描述不够清楚。Justmake可能给了我正确的答案。不过,为了进一步使用,我编辑了我的帖子:)正如您所说,Sender.OnMouseDOwn:=OMDold通常返回nil(非null)。这意味着Sender.OnMouseDOwn也是零。这就是为什么调用它会得到AV。在调用TButton(Sender.OnMouseDOwn)之前,您需要添加If Assigned(Sender.OnMouseDOwn),以便在Sender.OnMouseDOwn为空时跳过它。我已经回答了您最初的问题,但它可能实际上并没有解决您的问题,因为您没有清楚地指出您的问题。不断改变问题并不是获得更多帮助的好方法。如果你的新问题确实与原来的问题大不相同,你最好问一个新问题。为什么不直接打电话给
    OMDnew
    。你可以这样做,你知道。直接调用
    OMDnew(发送者、按钮、shift、x、y)
    有什么问题吗?我的描述不够清楚。Justmake可能给了我正确的答案。不过,为了进一步使用,我编辑了我的帖子:)正如您所说,Sender.OnMouseDOwn:=OMDold通常返回nil(非null)。这意味着Sender.OnMouseDOwn也是零。这就是为什么调用它会得到AV。在调用TButton(Sender.OnMouseDOwn)之前,您需要添加If Assigned(Sender.OnMouseDOwn),以便在Sender.OnMouseDOwn为空时跳过它。我已经回答了您最初的问题,但它可能实际上并没有解决您的问题,因为您没有清楚地指出您的问题。不断改变问题并不是获得更多帮助的好方法。如果你的新问题确实与原来的问题大不相同,那你就更好了