只有在按下鼠标按钮(MouseDown事件)后才能收听MouseMove事件
我基本上在F#表单应用程序中寻找Click-> Drag-> Release功能
答案 0 :(得分:2)
在鼠标按下事件中附加事件监听器以进行移动和向上移动,在向上移除它。这意味着处理程序方法需要是一个方法(或者您需要保持使用的委托)以传递给事件的remove方法。
(如果这是针对C#的,我会指向Rx- Reactive Extensions - 因为这可能是定义的例子,但我不确定Rx与F#的结合程度如何。)
答案 1 :(得分:2)
您也可以使用以下内容:
let setupDrag(target, fn) =
let isDown = ref false
target.MouseDown |> Event.add(fun _ -> isDown := true)
target.MouseMove |> Event.filter(fun _ -> !isDown) |> Event.add(fn)
target.MouseUp |> Event.add(fun( _ -> isDown := false)
在实际实现中,您可能希望在转换开始,停止和所有这些事情时实际执行其他操作。例如,您可能希望捕获目标上的指针。
答案 2 :(得分:2)
使用F#异步工作流机制可以很好地捕获此行为。我写了一篇关于此的文章(实现完全拖放功能),您可以在其中找到详细信息 - 请参阅Programming user interfaces with F# async workflows。
示例应用程序实现绘图,按下按钮,然后移动鼠标(定义矩形),最后释放按钮:
let rec drawingLoop(clr, from) = async {
// Wait for the first MouseMove occurrence
let! move = Async.AwaitObservable(form.MouseMove)
if (move.Button &&& MouseButtons.Left) = MouseButtons.Left then
// Refresh the window & continue looping
drawRectangle(clr, from, (move.X, move.Y))
return! drawingLoop(clr, from)
else
// Return the end position of rectangle
return (move.X, move.Y) }
let waitingLoop() = async {
while true do
let! down = Async.AwaitObservable(form.MouseDown)
let downPos = (down.X, down.Y)
if (down.Button &&& MouseButtons.Left) = MouseButtons.Left then
let! upPos = drawingLoop(Color.IndianRed, downPos)
do printfn "Drawn rectangle (%A, %A)" downPos upPos }
这里的好处是你可以很好地表达逻辑 - 等待MouseDown
(在waitingLoop
内),然后调用等待drawingLoop
的{{1}}函数直到按钮被释放(然后将控件转回MouseMove
,开始等待另一个鼠标按下事件。)
类似代码的另一个版本位于Phil Trelford's fractal zoom, which uses the same gesture for zooming。
完整的源代码是the Chapter 16 source code of Real-World Functional Programming的一部分。