自定义OnMouseDown,不会制动点击

时间:2012-03-15 09:09:13

标签: delphi events

好的我有一个函数可以返回 TMouseEvent 类型

我需要执行返回的TMouseEvent,但我不知道如何。

返回事件的简单函数:

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;

我想要实现的目标:

  1. 获取按钮默认OnMouseDown事件并将其存储在某些记录数据中

  2. 将ONMouseDown事件更改为自定义

  3. 在自定义事件过程中有一个条件 - 如果鼠标按下是拖动,我执行拖动代码,如果不是我继续进行常见的点击

  4. 要通过常规点击进行操作,我想恢复默认事件并重新执行,以便点击可以执行

  5. 多数民众赞成

3 个答案:

答案 0 :(得分:3)

直接通过param调用它:

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;

您可能需要更改Button,Shift,X,Y,但如果您在OMDOld中使用它们,则需要除dragEvent中的当前值以外的值,例如删除ssShift左右。

如果您的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.

答案 1 :(得分:0)

阻止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)会运行点击。

答案 2 :(得分:0)

分别处理所有问题部分:

  1. 获取按钮默认OnMouseDown事件并将其存储在某些记录数据中

    在表单声明中添加一个私有字段,并将旧事件分配给它:

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

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

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

    测试是否已分配原始事件,如果已分配,请将其命名为:

    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;
    
  4. 要通过常规点击进行操作,我想恢复默认事件并重新运行,以便点击可以执行

    恢复活动:

    Button.OnMouseDown := FOldButtonOnMouseDown;
    
  5. 将这一切结合在一起是您的下一个挑战。这尤其取决于如何实现拖动stuf,但您可以查看this answer,其中我还暂时交换OnMouseUp事件以撤消所有更改。