delphi 如何实现三击鼠标事件

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了delphi 如何实现三击鼠标事件相关的知识,希望对你有一定的参考价值。

关键是如何判断是连续三次点击鼠标,类似鼠标双击,而不是间隔点了三次,有高手给出delphi的代码吗?

以下代码实现在ContentEdit(文本编辑器)中三击鼠标选中一整行的功能。

先定义4个全局变量
FIsThreeClicking: Boolean; //三击事件(是否)进行中
FCurMouseX: Integer;
FCurMouseY: Integer; //三击时的坐标校验
FStartTime: Double; //用于实现鼠标三击事件

事件FormCreate 中初始化变量
procedure TFormMDIChild.FormCreate(Sender: TObject);
begin
FIsThreeClicking := False;
FStartTime := 0;
......
end;

控件的KeyDown事件中
procedure TFormMDIChild.ContentEditKeyDown(Sender: TObject; var Key: Word;
Shift: TShiftState);
begin
if FIsThreeClicking then //正处于三击事件时,屏蔽掉按键
begin
Key := 0;
Exit;
end;
......
end;

控件的MouseUp事件中
procedure TFormMDIChild.ContentEditMouseUp(Sender: TObject;
Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
var
pointBB, pointBE: TPoint;
bSelectFromTop: Boolean;
begin
if FIsThreeClicking then
begin
FIsThreeClicking := False; //三击事件结束
FStartTime := 0;

with ContentEdit do
begin
//恢复为正常选择模式,并选中指定块
if SelectionMode = smLine then
begin
SelectionMode := smNormal;
//if SelAvail then
begin
if (BlockBegin.y > BlockEnd.y)
or ((BlockBegin.y = BlockEnd.y)
and (BlockBegin.x > BlockEnd.x)) then
begin
pointBB := BlockEnd;
pointBE := BlockBegin;
end //如果块是从下往上选择
else begin
pointBB := BlockBegin;
pointBE := BlockEnd;
end; //否则正常
if CaretY = pointBE.y then
bSelectFromTop := True
else
bSelectFromTop := False;

pointBB.x := 1;
if pointBE.y < Lines.Count then
begin
pointBE.x := 1;
pointBE.y := pointBE.y + 1;
end
else begin
pointBE.x := Length(Lines[pointBE.y-1]) + 1;
pointBE.y := pointBE.y;
end;

BlockBegin := pointBB;
BlockEnd := pointBE;
if bSelectFromTop then
CaretXY := pointBE
else
CaretXY := pointBB;
end;
end; //三击后恢复选择模式

if [eoNoCaret] * Options = [eoNoCaret] then
begin
Options := Options - [eoNoCaret];
end; //三击后恢复光标(不是鼠标)
end;
end;
end;

procedure TFormMDIChild.ContentEditMouseDown(Sender: TObject;
Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
begin
if Button = mbLeft then
begin
with ContentEdit do
begin
if (GetTickCount - FStartTime < GetDoubleClickTime)
如果当前时间 - 双击时的时间 < 系统的双击间隔时间——即当前动作为三击
and (PixelsToRowColumn(Point(FCurMouseX, FCurMouseY)).x = PixelsToRowColumn(Point(X, Y)).x)
and (PixelsToRowColumn(Point(FCurMouseX, FCurMouseY)).y = PixelsToRowColumn(Point(X, Y)).y)
当前坐标 = 双击时的坐标
then begin
Options := Options - [eoDragDropEditing]; //不允许拖动(MouseDown 事件中处理中用到)
PostMessage(Self.Handle, WM_THREECLICK, 0, 0); //发送消息到消息队列
end //因为 MouseDown 后 SynEdit 要进行一些处理,而这些处理与三击事件的处理
//代码在顺序上有冲突,故通过消息队列来安排事件处理顺序
else begin
FCurMouseX := X;
FCurMouseY := Y; //保存当前 Mouse X,Y
end;
end;
end;
end;

procedure WmContentEditThreeClick(var Message: TMessage); message WM_THREECLICK; //处理鼠标三击事件

procedure TFormMDIChild.WmContentEditThreeClick(var Message: TMessage);
三击时选中全行
var
pointCaretXY: TPoint;
begin
FIsThreeClicking := True; //三击事件进行中
with ContentEdit do
begin
Options := Options + [eoDragDropEditing]; //恢复拖动
SelectionMode := smLine; //改为双击选中行模式

pointCaretXY.x := 1;
pointCaretXY.y := CaretXY.y;
BlockBegin := pointCaretXY;
pointCaretXY.x := Length(LineText) + 1;
BlockEnd := pointCaretXY; //选中全行

if [eoNoCaret] * Options <> [eoNoCaret] then
begin
Options := Options + [eoNoCaret]; //隐藏光标
end;
end;
end;
参考技术A 全局变量i=0;
鼠标点击事件里 i=i+1;
添加一个timer控件,每过1秒将i重设为0;
判断i为3时就是鼠标在1秒内3击了。至于是1秒还是其他,这个自己决定
如果还有6连击(执行两次3连击)的情况,那就在执行一次后将i重置为0
参考技术B 你就设置一个变量,累加点击的次数的,在点击事件里写代码,判断条件是这个变量等于三,然后才执行你要的代码 参考技术C type
TMouseDownThree=class
private
Fcount:integer;
FlastDown:TTime;
FonThreeDown:TNotifyEvent;
public
procedure Down;
//当三连击时的事件,
property onThreeDown:TNotifyEvent read FonThreeDown write FonThreeDown;
end;

procedure TMouseDownThree.Down;
begin
//这里的3差不多是三分之一秒,数值越小要求点击越快
if (Time-FlastDown)*1000000>3 then
Fcount:=1
else
Fcount:=Fcount+1;
if Fcount>=3 then
begin
Fcount:=1;
if assigned(FonThreeDown) then
FonThreeDown(self);
showmessage('三击');
end;
FlastDown:=time;
end;

例:
var MouseDownThree:TMouseDownThree;

procedure TForm12.FormCreate(Sender: TObject);
begin
MouseDownThree:=TMouseDownThree.Create;
end;

procedure TForm12.FormDestroy(Sender: TObject);
begin
MouseDownThree.Free;
end;

procedure TForm12.FormMouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
begin
MouseDownThree.Down;
end;本回答被提问者和网友采纳
参考技术D 推荐四楼的,1,2,3楼的做法 并不能将单击,双击,三击区分开。
用计数的方式没错,但是一定要 把击键的频率考虑进去

Delphi中window消息截获的实现方式

  近来笔者在一个项目中需要实现一个功能:模仿弹出菜单的隐藏方式,即鼠标在窗口的非PanelA区域点击时,使得PanelA隐藏。
   经过思考,笔者想到通过处理鼠标的点击事件来实现相应功能。但是,究竟由谁来处理这个点击事件呢?如果窗口中包含多个句柄控件,则不能确定谁能获取到这个鼠标的点击事件,故而无法做出处理。
   通过热心网友的帮忙,笔者了解到了window消息截获的实现方式,更棒的是:消息截获并不影响消息的正常处理。最终实现的效果非常完美。在此分享给有需要的朋友。下面是消息截获的实现代码。
1.对于有句柄的控件,可以用一下代码
interface  
  
uses  
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,  
  Dialogs, StdCtrls, ComCtrls;  
  
type  
  TForm1 = class(TForm)  
    btn1: TButton;  
    btn2: TButton;  
    PageControl1: TPageControl;  
    ts1: TTabSheet;  
    ts2: TTabSheet;  
    procedure FormCreate(Sender: TObject);  
    procedure btn1Click(Sender: TObject);  
  private  
    { Private declarations }  
  public  
    { Public declarations }  
    procedure AppMsg(var Msg: TMsg; var Handled: Boolean);  
  end;  
  
var  
  Form1: TForm1;  
  
implementation  
  
{$R *.dfm}  
  
{ TForm1 }  
procedure TForm1.AppMsg(var Msg: TMsg; var Handled: Boolean);  
var  
  i:integer;  
begin  
  case Msg.message of  
    WM_LBUTTONDOWN,  
    WM_LBUTTONDBLCLK:  
      begin  
        //拦截PageControl控件的Tab标签切换事件  
        if Msg.hwnd=PageControl1.Handle then  
        begin  
          for i:=0 to PageControl1.PageCount-1 do  
          begin  
            if PtInRect(PageControl1.TabRect(i),PageControl1.ScreenToClient(Msg.pt)) then  
            begin  
              Handled:=true;  
              ShowMessage(IntToStr(i));  
            end;  
          end;  
        end;  
  
        //拦截Button按钮点击事件  
        if Msg.hwnd=btn1.Handle then  
        begin  
          Handled:=true;  
          ShowMessage(‘bbbb‘);  
        end;  
      end;  
  end;  
end;  
  
procedure TForm1.FormCreate(Sender: TObject);  
begin  
  Application.OnMessage:=AppMsg;  
end;  
  
procedure TForm1.btn1Click(Sender: TObject);  
begin  
  ShowMessage(‘aaaa‘);  
end;  
  
end.
2.对于没有句柄的控件,可以通过矩形区域判断
var
  Pt: TPoint;
  MyRect: TRect;
begin
  if (Msg.message = WM_LBUTTONUP) or (Msg.message = WM_RBUTTONUP) then
  begin
    GetCursorPos(Pt);
    MyRect.TopLeft.X := OwnButton5.ClientOrigin.x;
    MyRect.TopLeft.y := OwnButton5.ClientOrigin.y;
    MyRect.BottomRight.X := MyRect.TopLeft.X +OwnButton5.Width;
    MyRect.BottomRight.y := MyRect.TopLeft.y +OwnButton5.Height;
    if not PtInRect(MyRect,Pt) then Panel14.Visible := False;
  end;
end; 
 需要注意的是:窗口销毁时,如果应用程序需要继续运行,则要在窗口销毁时解除消息截获,即Application.OnMessage:=nil;

以上是关于delphi 如何实现三击鼠标事件的主要内容,如果未能解决你的问题,请参考以下文章

delphi6 两个dbgrid如何实现水平滚动条同步滚动?

delphi 如何实现grid组件在鼠标双击某一行后获得这一行的数据并将数据写到相应的edit中?

Delphi中window消息截获的实现方式

delphi 对右键菜单的操作

Delphi - 通过WinAPI GetCursorPos实现鼠标位置的实时显示

用jQuery如何实现鼠标拖选事件