- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
长按是指按下按钮/面板并按住一段时间(例如 2 秒)而不释放或拖动。常见于手机和触摸设备中。
我尝试过使用手势,在 TabletOptions 中检查了 toPressAndHold 并在 InteractiveGestureOptions 中检查了所有内容,但长按导致没有 OnGesture Call。
我能想到的另一个实现是添加一个计时器,在 MouseDown 中启动它,并在 Timer Fired、StartDrag、MouseUp 或 MouseLeave 中结束它。但是,由于我想将此行为添加到几个不同的按钮和面板组件中,因此我必须重写每个类中的一些过程,并复制每个组件的代码。
是否有更好的方法来实现这一目标?
<小时/>编辑:
至 NGLN
哇,伟大的作品!结合您对滚动效果的回答,VCL 几乎可以实现移动操作系统的外观和感觉!
您的代码与常见控件完美配合,但我遇到了 2 个问题
我有一些自定义按钮,其中有一些禁用的 HTML标签(页眉、标题、页脚)覆盖原始标签表面上,使用您的代码,FChild 将是这些标签之一,但它没有得到MouseCapture。我添加以下行来克服它:
当不是 TControlAccess(FChild).Enabled 时执行 FChild := FChild.Parent;
最后,对于一些更复杂的控件,例如 TCategoryButtons 或 TListBox,事件的用户可能需要检查的不是整个控件,而是控件中的指定项目。所以我认为我们需要保存原始的 CursorPos 并在计时器触发时触发另一个事件,以便手动确定是否满足长按条件。如果是或未分配事件,则使用您的默认代码进行确定。
总而言之,我们可以创建一个支持 LongPress 的表单/面板来托管所有其他控件。这比逐个组件实现 LongPress 功能要容易得多!非常感谢!
<小时/>编辑2:
至 NGLN
再次感谢您的组件版本,这是一个很好的方法,不需要对现有组件进行任何修改,并且可以在任何地方检测长按!
供您引用,我做了一些修改以满足我自己的需要。
再次感谢您所做的出色工作。
最佳答案
每次单击鼠标左键,WM_PARENTNOTIFY
发送给被单击控件的所有(祖) parent 。因此,这可以用于跟踪长按的起点,并且可以使用计时器来计时按下的持续时间。剩下的就是决定何时将按下称为长按。当然,要将这一切包装在一个很好的组件中。
在下面编写的组件中,当满足以下条件时会触发 OnLongPress
事件处理程序:
Mouse.DragThreshold
。代码的一些解释:
OnMouseUp
事件处理程序,否则连续单击也可能导致长按。中间事件处理程序禁用跟踪计时器,调用原始事件处理程序并将其替换回来。FindControlAtPos
例程,可以在任意窗口上执行深度搜索。替代方案是 (1) TWinControl.ControlAtPos
,但它仅搜索一层深度,以及 (2) Controls.FindDragTarget
,但尽管有 AllowDisabled
参数,它无法找到禁用的控件。unit LongPressEvent;
interface
uses
Classes, Controls, Messages, Windows, Forms, ExtCtrls;
type
TLongPressEvent = procedure(Control: TControl) of object;
TLongPressTracker = class(TComponent)
private
FChild: TControl;
FClickPos: TPoint;
FForm: TCustomForm;
FOldChildOnMouseUp: TMouseEvent;
FOldFormWndProc: TFarProc;
FOnLongPress: TLongPressEvent;
FPrevActiveControl: TWinControl;
FTimer: TTimer;
procedure AttachForm;
procedure DetachForm;
function GetDuration: Cardinal;
procedure LongPressed(Sender: TObject);
procedure NewChildMouseUp(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
procedure NewFormWndProc(var Message: TMessage);
procedure SetDuration(Value: Cardinal);
procedure SetForm(Value: TCustomForm);
procedure StartTracking;
protected
procedure Notification(AComponent: TComponent; Operation: TOperation);
override;
public
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
property Form: TCustomForm read FForm write SetForm;
published
property Duration: Cardinal read GetDuration write SetDuration
default 1000;
property OnLongPress: TLongPressEvent read FOnLongPress
write FOnLongPress;
end;
procedure Register;
implementation
procedure Register;
begin
RegisterComponents('Samples', [TLongPressTracker]);
end;
function FindControlAtPos(Window: TWinControl;
const ScreenPos: TPoint): TControl;
var
I: Integer;
C: TControl;
begin
for I := Window.ControlCount - 1 downto 0 do
begin
C := Window.Controls[I];
if C.Visible and PtInRect(C.ClientRect, C.ScreenToClient(ScreenPos)) then
begin
if C is TWinControl then
Result := FindControlAtPos(TWinControl(C), ScreenPos)
else
Result := C;
Exit;
end;
end;
Result := Window;
end;
{ TLongPressTracker }
type
TControlAccess = class(TControl);
procedure TLongPressTracker.AttachForm;
begin
if FForm <> nil then
begin
FForm.HandleNeeded;
FOldFormWndProc := Pointer(GetWindowLong(FForm.Handle, GWL_WNDPROC));
SetWindowLong(FForm.Handle, GWL_WNDPROC,
Integer(MakeObjectInstance(NewFormWndProc)));
end;
end;
constructor TLongPressTracker.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
FTimer := TTimer.Create(Self);
FTimer.Enabled := False;
FTimer.Interval := 1000;
FTimer.OnTimer := LongPressed;
if AOwner is TCustomForm then
SetForm(TCustomForm(AOwner));
end;
destructor TLongPressTracker.Destroy;
begin
if FTimer.Enabled then
begin
FTimer.Enabled := False;
TControlAccess(FChild).OnMouseUp := FOldChildOnMouseUp;
end;
DetachForm;
inherited Destroy;
end;
procedure TLongPressTracker.DetachForm;
begin
if FForm <> nil then
begin
if FForm.HandleAllocated then
SetWindowLong(FForm.Handle, GWL_WNDPROC, Integer(FOldFormWndProc));
FForm := nil;
end;
end;
function TLongPressTracker.GetDuration: Cardinal;
begin
Result := FTimer.Interval;
end;
procedure TLongPressTracker.LongPressed(Sender: TObject);
begin
FTimer.Enabled := False;
if (Abs(FClickPos.X - Mouse.CursorPos.X) < Mouse.DragThreshold) and
(Abs(FClickPos.Y - Mouse.CursorPos.Y) < Mouse.DragThreshold) and
(((FChild is TWinControl) and TWinControl(FChild).Focused) or
(TControlAccess(FChild).MouseCapture or (not FChild.Enabled))) then
begin
FForm.ActiveControl := FPrevActiveControl;
if Assigned(FOnLongPress) then
FOnLongPress(FChild);
end;
TControlAccess(FChild).OnMouseUp := FOldChildOnMouseUp;
end;
procedure TLongPressTracker.NewChildMouseUp(Sender: TObject;
Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
begin
FTimer.Enabled := False;
if Assigned(FOldChildOnMouseUp) then
FOldChildOnMouseUp(Sender, Button, Shift, X, Y);
TControlAccess(FChild).OnMouseUp := FOldChildOnMouseUp;
end;
procedure TLongPressTracker.NewFormWndProc(var Message: TMessage);
begin
case Message.Msg of
WM_PARENTNOTIFY:
if TWMParentNotify(Message).Event = WM_LBUTTONDOWN then
StartTracking;
WM_LBUTTONDOWN:
StartTracking;
end;
with Message do
Result := CallWindowProc(FOldFormWndProc, FForm.Handle, Msg, WParam,
LParam);
end;
procedure TLongPressTracker.Notification(AComponent: TComponent;
Operation: TOperation);
begin
inherited Notification(AComponent, Operation);
if (AComponent = FForm) and (Operation = opRemove) then
DetachForm;
if (AComponent = FChild) and (Operation = opRemove) then
begin
FTimer.Enabled := False;
FChild := nil;
end;
end;
procedure TLongPressTracker.SetDuration(Value: Cardinal);
begin
FTimer.Interval := Value;
end;
procedure TLongPressTracker.SetForm(Value: TCustomForm);
begin
if FForm <> Value then
begin
DetachForm;
FForm := Value;
FForm.FreeNotification(Self);
AttachForm;
end;
end;
procedure TLongPressTracker.StartTracking;
begin
FClickPos := Mouse.CursorPos;
FChild := FindControlAtPos(FForm, FClickPos);
FChild.FreeNotification(Self);
FPrevActiveControl := FForm.ActiveControl;
FOldChildOnMouseUp := TControlAccess(FChild).OnMouseUp;
TControlAccess(FChild).OnMouseUp := NewChildMouseUp;
FTimer.Enabled := True;
end;
end.
要使该组件正常工作,请将其添加到包中,或使用以下运行时代码:
...
private
procedure LongPress(Control: TControl);
end;
...
procedure TForm1.FormCreate(Sender: TObject);
begin
with TLongPressTracker.Create(Self) do
OnLongPress := LongPress;
end;
procedure TForm1.LongPress(Control: TControl);
begin
Caption := 'Long press occurred on: ' + Sender.ClassName;
end;
关于delphi - 将长按事件添加到按钮类的最佳方法是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9629063/
所以我有这个 javascript 片段,它有两个按钮可以进入全屏,一个按钮可以退出全屏。我想做到这一点,如果我不在全屏模式下,按钮会显示转到全屏模式,而当我处于全屏模式时,按钮会显示退出全屏模式..
我在自定义控件中添加了一个新属性作为可扩展属性,例如属性网格中的字体属性。在 Windows 窗体应用程序项目中使用我的自定义控件后,我在属性网格中看到一个省略号 (…) 按钮,如字体属性的“…”按钮
我在自定义控件中添加了一个新属性作为可扩展属性,例如属性网格中的字体属性。在 Windows 窗体应用程序项目中使用我的自定义控件后,我在属性网格中看到一个省略号 (…) 按钮,如字体属性的“…”按钮
我尝试将 Twitter 上的“Tweet Me”按钮 ( http://twitter.com/goodies/tweetbutton ) 添加到我的网站。然而,每当按下按钮时,我都会收到此 Jav
我试图在我的文本区域中获取一个按钮值,如果我使用 则工作正常但如果我使用那么它就不起作用了。你能找出问题所在吗? HTML 1 2 3 4 JavaScript $(document).read
我的 C# Winform 面板中有一堆文本框。每行文本框的命名如下: tb1 tbNickName1 comboBox1 tb2 tbNickName2 comboBox2 tb3 tbNickNa
我有一个表单,其中过滤器下方有按钮(应用过滤器和清除过滤器),我试图在单击“应用”按钮时显示“清除”,并在单击“清除”按钮时隐藏“清除”按钮。 下面的代码(如果我的表有的话):
excel 按钮正在工作,但是当我添加 pdf 按钮时,它添加仅显示 pdf 按钮 excel 按钮在 pdf 按钮添加后隐藏 $(document).ready(function() { $
我想创建一个 div 作为标题并分成 3 列,并按以下顺序在其中放置 2 个按钮和一个标题:Button1(左位) Title(居中) Button2(右位) 这是我为这个 div 编写的代码:
仅当选中所有框时才应禁用“允许”按钮。我该怎么做?我已经完成了 HTML 部分,如下所示。如何执行其中的逻辑部分?即使未选中一个复选框,也应禁用“允许”按钮
很难说出这里问的是什么。这个问题是含糊的、模糊的、不完整的、过于宽泛的或修辞性的,无法以目前的形式得到合理的回答。如需帮助澄清此问题以便重新打开它,visit the help center 。 已关
如您所知,您可以使用 2 种方法在 HTML5 中呈现按钮: 使用 void 元素 或 如果您需要内容,请使用 元素(不是空元素)。 在JSF2中,有2种方式生成按钮;与UICommand或 UIOu
我尝试根据表单元素的更改禁用/启用保存按钮。但是,当通过弹出按钮选择更改隐藏输入字段值时,保存按钮不受影响。 下面是我的代码。我正在尝试序列化旧的表单值并与更改后的表单值进行比较。但我猜隐藏的字段值无
我有用于在消息(电子邮件、短信)上输入内容的 EditText。我希望在单击 ActionDone 按钮时立即发布消息。我为此使用以下代码: message.setOnEditorActionList
我的 Android 应用程序中有一堆 EditText,每个都将 InputMethod 设置为 numberSigned。我的目标设备没有硬件键盘,而是使用软件键盘输入数字。 Android 将输
我无法以编程方式隐藏弧形菜单中的 fab 按钮。我正在使用https://github.com/saurabharora90/MaterialArcMenu在我的代码中。如何在Java中以编程方式隐藏
我已经看到这在其他类型的对话框窗口中是可能的,例如“showConfirmDialog”,其中可以指定按钮的数量及其名称;但是使用“showInputDialog”时是否可以实现相同的功能?我似乎无法
相同的按钮用于激活和停用。第一次,当代码运行按钮单击并成功“停用”时。但第二次,代码无法找到该元素。第一个案例按钮位于第二个“a”标签中,然后停用第一个“a”标签中的按钮。 案例1: Edit
是否可以将按钮的 onclick 操作设置为 JavaScript 变量?这个想法是我们用 JavaScript 控制一个表。每当点击该表的一行时,我们就会更新一个 JavaScript 变量。该 v
我想创建一个按钮,它包含左侧的文本和右侧的复选框(或任何其他组件)。我怎样才能做到这一点? 我发现我可以制作自己的 View extends Button,但是如果可以的话我应该如何实现 onDraw
我是一名优秀的程序员,十分优秀!