我在form_MouseDown事件上有一个Drag()方法。我在表单上也有一个点击事件。问题是,如果我单击表单,MouseDown事件将被触发,它永远不会有机会触发click事件。
解决此问题的最佳方法是什么?如果表单实际被拖动,我在考虑计算像素,但必须有更好的方法。有什么建议?
答案 0 :(得分:2)
不幸的是,在“按下按钮”的时候,您还不知道所需的操作是单击还是拖放。你会发现它以后。
对于单击,行列式是“无移动”和“按钮向上”。
对于拖动,行列式是“移动”和“按钮向上”。
因此,要消除这些交互的歧义,您不仅要跟踪按钮,还要跟踪移动。您无需跟踪整体移动,只需按下按钮和按钮之间的移动即可。
因此,这些事件是启动/停止Mouse.Capture机制(动态呈现拖动装饰器和放置位置提示)的好地方,或者是更简单的形式 - 存储运动矢量的原点和目标,并检查距离是否> D(即使发生了移动,也应该有一些安全的最小距离,其中DRAG被取消。鼠标有时是“锯齿状”,人们真的不喜欢你的应用程序在他们双击结束时开始拖动快速鼠标指针移动:))
答案 1 :(得分:2)
我在考虑计算像素是否实际拖动,但必须有更好的方法。
不,这正是你必须要做的。
这不仅仅是软件限制;它也非常实用。如果从用户的角度思考问题,您将立即看到问题以及解决方案。问问自己,点击和拖动之间有什么区别?
它们都是以鼠标按钮向下朝向对象开始的,但其中一个按钮以鼠标按钮向上移动到同一位置的对象上,而另一个以鼠标按钮向后返回完全不同的立场。
由于时间机器还没有完善,你无法事先知道这一点。
所以是的,你需要保持一定的距离阈值,如果指针在物体上方向下移动时移动到该距离阈值之外,那么你认为它是一个阻力。否则,您认为这是一次点击。
该距离阈值不应为0.不应要求用户完全按住鼠标 以启动点击。许多用户都是低于标准的鼠标。尝试点击时,他们很可能会轻微抽搐。如果阈值为0,当他们尝试点击时,他们最终会进行大量的无意拖动。
当然,您实际上不必担心任何此问题或自行计算阻力阈值。而是使用Windows默认值,可通过调用GetSystemMetrics
函数并指定SM_CXDRAG
或SM_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领域,这类事物被称为 hysteresis 或 debouncing ,类似于在物理和电子学中使用这些术语。
答案 2 :(得分:2)
我找到了这个解决方案,虽然它是双击和鼠标按下事件:
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