【问题标题】:MouseDown and Click conflictMouseDown 和 Click 冲突
【发布时间】:2019-02-02 15:16:14
【问题描述】:

我在 form_MouseDown 事件上有一个 Drag() 方法。我在表单上也有一个点击事件。问题是,如果我点击表单,MouseDown 事件会被触发,它永远不会有机会触发点击事件。

解决此问题的最佳方法是什么?如果表单实际上被拖动,我正在考虑计算像素,但必须有更好的方法。有什么建议么?

【问题讨论】:

  • “计数像素”很常见,因为在大多数情况下,您实际上不希望在“移动距离”短于以下时触发 DRAG,例如例如,7..15 像素。连windows的桌面都有这么少的像素阈值。
  • 不要使用Click,而是使用MouseUp
  • 我创建了一个演示,但没有出现这种行为。达到 MouseDown Click 后。可以发一些代码吗?
  • 也许他还用 Handled=true 'acks' 事件或忘记调用基本实现等?
  • @Neolisk 这将如何解决问题?当用户在拖动后释放鼠标按钮时,MouseUp 事件仍会引发。 Click 事件实际上只是在MouseDownMouseUp 事件循环之后引发的事件。

标签: c# winforms mousedown


【解决方案1】:

我找到了这个解决方案,虽然它是针对双击和鼠标按下事件:

void pictureBox_MouseDown(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left && e.Clicks ==1)
{
PictureBox pb = (PictureBox)sender;
DoDragDrop((ImageData)pb.Tag, DragDropEffects.Copy);
}
}

来源:http://code.rawlinson.us/2007/04/c-dragdrop-and-doubleclick.html

【讨论】:

  • 这很好用,看不出这不是公认的遮阳篷。
【解决方案2】:

我在考虑如果表单实际被拖动,则计算像素,但必须有更好的方法。

不,这正是你必须这样做的方式。

这不仅仅是软件限制;它也非常实用。如果您从用户的角度考虑问题,您将立即看到问题以及解决方案。问问自己,点击和拖动有什么区别?

它们都以鼠标按钮在对象上向下移动开始,但其中一个以鼠标按钮在相同位置的对象上向上返回结束,另一个以鼠标按钮以完全不同的立场。

由于时间机器还没有完善,你无法提前知道这一点。

所以是的,您需要保持某种距离阈值,如果指针在对象上向下移动时超出该距离阈值,那么您认为它是一种拖拽。否则,您认为这是一次点击。

该距离阈值不应为 0。不应要求用户完全静止以启动点击。很多用户都是低于标准的鼠标。尝试点击时,它们很可能会轻微抽搐。如果阈值为 0,则他们在尝试点击时最终会无意中拖动。

当然,您实际上不必担心这些或自己计算阻力阈值。相反,使用 Windows 默认值,可通过调用GetSystemMetrics 函数并指定SM_CXDRAGSM_CYDRAG 来获得。 (这些可能会在 WinForms 框架的某个地方公开,但我不这么认为。自己 P/Invoke 它们同样容易。)

const int SM_CXDRAG = 68;
const int SM_CYDRAG = 69;
[DllImport("user32.dll")]
static extern int GetSystemMetrics(int index);

Point GetDragThreshold()
{
    return new Point(GetSystemMetrics(SM_CXDRAG), GetSystemMetrics(SM_CYDRAG));
}

在 UX/UI 领域,此类事情被称为 hysteresisdebouncing,类似于物理学和电子学中这些术语的使用。 p>

【讨论】:

  • 虽然您在这里总体上有好处,但程序的设计方式应该是,将任何 5px 的东西拖放到一边不会导致任何事情发生。否则你永远不会知道,也许 5px 的抖动不足以让某些人执行点击,他们需要 10px。通过适当的实施,鼠标移动是无关紧要的。例如,如果您在 Windows 中将文件拖放到自身,则不会发生任何事情。
  • 想象一下您正在创建 WinForms 设计器。即使正确实施,鼠标移动仍然相关。它的设计与 Windows Explorer 完全不同,在 Windows Explorer 中放置图标没有任何意义。但是你当然可以在任何方向拖动一个控件几个像素。或照片编辑器中的选择。或者“正确实施”规则不起作用的任何其他情况。
  • 在这些情况下,您将使用键盘定位(箭头键)。它正是这样做的——在指定方向上移动 1 个像素。否则,例如在 VS 中,您可能希望该控件粘在表格网格或其他控件上。在这两种情况下,VS 都会帮助您进行定位。在 Photoshop 或 Paint 中,您可以 1) 使用箭头键或 2) 当在任一方向移动几个像素变得无关紧要时,将其缩小到该点。
  • 我最好怎么做?有一个 MouseUp 否定检查?如果鼠标在其他地方或其他地方注册了事件怎么办?我总是对这种情况感到偏执
  • 对于将来检查这一点的任何人,这些属性实际上是通过 .NET 接口公开的。尝试使用SystemParameters.MinimumHorizontalDragDistanceSystemParameters.MinimumVerticalDragDistance,尽管它们只是使用上面显示的相同GetSystemMetrics() 调用。只是一些语法糖。
【解决方案3】:

不幸的是,在“按下按钮”时,您还不知道所需的操作是单击还是拖放。你会发现它稍后

对于点击,决定因素是“没有移动”和“按钮向上”。

对于拖动,决定因素是“移动”和“按钮向上”。

因此,要消除这些交互的歧义,您不仅要跟踪按钮,还要跟踪移动。您不需要跟踪整体运动,只有按钮向下和按钮向上之间的运动是有趣的。

因此,这些事件是启动/停止 Mouse.Capture 机制(动态呈现拖动装饰器放置位置提示)的好地方,或者以更简单的形式- 存储运动矢量的原点和目标,并检查距离是否 > D(即使发生了运动,也应该有一个安全的最小距离,在该距离内取消 DRAG。鼠标有时是“锯齿状的”,人们真的会不希望您的应用在鼠标指针快速移动结束时双击时开始拖动 :) )

【讨论】:

    猜你喜欢
    • 2015-02-05
    • 1970-01-01
    • 1970-01-01
    • 2018-08-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多