Canvas.MouseWheel and native feeling Delta

Is there a way (Declare?) to make MouseWheel event return deltas that would feel more native in OS X? Like Xojo’s navigator. It scrolls faster with just a tiny swipe on the trackpad.

From the docs of Canvas.MouseWheel:

It is up to you to make the necessary calculations. Take DeltaY and multiply it with some factor.

[quote=74279:@Eli Ott]From the docs of Canvas.MouseWheel:

It is up to you to make the necessary calculations. Take DeltaY and multiply it with some factor.[/quote]
For Cocoa this is not true. The only way is with declares. You need to look into the NSEvent object to determine if hasPreciseScrollingDeltas is true, and read the pixel values. If false, then the value is number is lines which needs to be multiplied by the height of one line.

It’s… not pretty.

Try this inside a MouseWheel event. Your CorrectX and CorrectY will be pixel deltas, rather than line deltas. LineStep is a value you will need to create and set to the height of one line.

[code]Dim CorrectX As Single = DeltaX
Dim CorrectY As Single = DeltaY
Dim UsesPixelDeltas As Boolean

#if TargetCocoa
Try
Declare Function objc_getClass Lib “Cocoa.framework” (aClassName As CString) As Ptr
Declare Function sel_registerName Lib “/usr/lib/libobjc.dylib” (Name As CString) As Ptr
Declare Function GetSharedApplication Lib “Cocoa.framework” Selector “sharedApplication” (Target As Ptr) As Ptr
Declare Function GetCurrentEvent Lib “Cocoa.framework” Selector “currentEvent” (Target As Ptr) As Ptr
Declare Function RespondsToSelector Lib “Cocoa.framework” Selector “respondsToSelector:” (Target As Ptr, Sel As Ptr) As Boolean
Declare Function HasPreciseScrollingDeltas Lib “Cocoa.framework” Selector “hasPreciseScrollingDeltas” (Target As Ptr) As Boolean
Declare Function ScrollingDeltaX Lib “Cocoa.framework” Selector “scrollingDeltaX” (Target As Ptr) As Single
Declare Function ScrollingDeltaY Lib “Cocoa.framework” Selector “scrollingDeltaY” (Target As Ptr) As Single

Dim NSApplication As Ptr = objc_getClass("NSApplication")
If NSApplication <> Nil Then
Dim SharedApplication As Ptr = GetSharedApplication(NSApplication)
If SharedApplication <> Nil Then
  Dim EventObject As Ptr = GetCurrentEvent(SharedApplication)
  If EventObject <> Nil Then
	If RespondsToSelector(EventObject,sel_registerName("hasPreciseScrollingDeltas")) Then
	  UsesPixelDeltas = HasPreciseScrollingDeltas(EventObject)
	  CorrectX = ScrollingDeltaX(EventObject) * -1
	  CorrectY = ScrollingDeltaY(EventObject) * -1
	End If
  End If
End If
End If

Catch Err As RuntimeException
UsesPixelDeltas = False
CorrectX = DeltaX
CorrectY = DeltaY
End Try
#endif

If Not UsesPixelDeltas Then
CorrectX = CorrectX * LineStep
CorrectY = CorrectY * LineStep
End If[/code]

Perfect! Worked straight out of the box. Thanks, Thom! Hope someday we get these ScrollingDeltas to Xojo built-in…

What would be the best way to provide a scroll boundary Min-Max for say the CorrectY?

Starting a new thread on my question.

Are you guys having any luck with this code when compiling for 64Bit?

For me the Deltas are returning 0 when it was working fine on 32bit

For 64bit, the single values must be doubles: https://github.com/thommcgrath/ArtisanKit/blob/master/Project/ArtisanKit/ScrollEvent.xojo_code

Thanks Thom!

Is it the same to just change all Single’s to CGFloat’s?

I honestly don’t know. The code in the posted link is what I use and it works. If there’s a better way, that’d be good to know.

Thom - how do you actually use this to scroll a canvas? Sorry for noobie question…

When I’m designing my controls, I usually store the scroll position as a property and offset my drawing by that amount. So the MouseWheel event just does something simple like

Self.ScrollPositionY = Self.ScrollPositionY + PixelsY
Self.Invalidate

And in Paint

G.DrawLine(0, 20 - Self.ScrollPositionY, G.Width, 20 - Self.ScrollPositionY

Though it’s a bit of an oversimplification of course.

Hi Thom, what about the use of ScrollEvent.xojo_code - I’ve imported it in to my project as a class and would like to use that… a manual scroll bar works fine - but would love mousewheel event to work more natively…

In the MouseWheel event of the scrollbar, create a new instance of the ScrollEvent object. Then you can get its properties and adjust your ScrollBar values accordingly.

You’re a legend Thom - thanks.

OK, sorry to bother you again Thom - getting somewhere, but not got it working right, when I scroll, it sort of attempts to do it then springs back to the top when I release the mousehweel…

Without seeing code, I don’t know why.

Resolved - cheers again Thom.