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中?