Canvas.MouseWheel Boundaries Control

Hi,

When using the mousewheel what is the best way to deploy boundary control? I try the basic if y <= blah then exit function else continue scrolling. This methodology is crude and is not smooth at all.

Any advice would be greatly appreciated! (this is for Desktop / Mac)

Here is my current mousewheel Event;

  DontRedrawReportCanvas = False
  drawStatic = True
  
  Dim CorrectX As Single = DeltaX
  Dim CorrectY As Single = DeltaY
  Dim UsesPixelDeltas As Boolean
  
  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 * -1
    CorrectY = DeltaY * -1
  End Try
  
  Me.ScrollValY = CorrectY
  Me.ScrollValX = CorrectX
  Me.Invalidate(False)

I use a different approach for that. I have subclassed Canvas and in its Open event I insert an NSScrollView into the view hierarchy:

Sub Open() Declare Function NSClassFromString Lib "Foundation" (aClassName As CFStringRef) As Ptr Declare Function alloc Lib "Foundation" Selector "alloc" (NSClass As Ptr) As Ptr Declare Function retain Lib "Foundation" Selector "retain" (NSObject As Ptr) As Ptr Declare Function release Lib "Foundation" Selector "release" (NSObject As Ptr) As Ptr Declare Function initWF Lib "AppKit" Selector "initWithFrame:" (NSView As Ptr, r As NSRect) As Ptr Declare Function superview Lib "AppKit" Selector "superview" (NSView As Ptr) As Ptr Declare Sub removeFromSuperview Lib "AppKit" Selector "removeFromSuperview" (NSView As Ptr) Declare Sub addSubview Lib "AppKit" Selector "addSubview:" (NSView As Ptr, aView As Ptr) Declare Sub setDocumentView Lib "AppKit" Selector "setDocumentView:" (NSView As Ptr, aView As Ptr) Declare Sub setHasVS Lib "AppKit" Selector "setHasVerticalScroller:" (NSScrollView As Ptr, f As Boolean) Dim scrollView As Ptr = initWF(alloc(NSClassFromString("NSScrollView")), NSMakeRect(0, 0, Width, Height)) setHasVS(scrollView, True) Dim xojoView As Ptr = Ptr(Handle) Dim superview As Ptr = superview(xojoView) Call retain(xojoView) removeFromSuperview(xojoView) addSubview(superview, scrollView) setDocumentView(scrollView, xojoView) Call release(xojoView) RaiseEvent Open() End Sub
In the canvas instance on the window I do as test:

Window1 Control Canvas1: Sub Open() Me.Height = Me.Height * 2 End Sub Sub Paint(g As Graphics, areas() As REALbasic.Rect) g.DrawOval(0, 0, g.Width, g.Height) End Sub
You then see only the upper half of the oval and the native Cocoa scroller appears when you try to scroll vertically.

Note:
The scroll views coordinate system is cartesian (meaning 0, 0 is in the left bottom corner), which is the standard in Cocoa. To change that to 0, 0 being the top left corner, the scrollView above would need to be an instance of a subclass created in the Objective C Runtime where the isFlipped method is overridden and returns True.

[quote=217071:@Eli Ott]I use a different approach for that. I have subclassed Canvas and in its Open event I insert an NSScrollView into the view hierarchy:

Sub Open() Declare Function NSClassFromString Lib "Foundation" (aClassName As CFStringRef) As Ptr Declare Function alloc Lib "Foundation" Selector "alloc" (NSClass As Ptr) As Ptr Declare Function retain Lib "Foundation" Selector "retain" (NSObject As Ptr) As Ptr Declare Function release Lib "Foundation" Selector "release" (NSObject As Ptr) As Ptr Declare Function initWF Lib "AppKit" Selector "initWithFrame:" (NSView As Ptr, r As NSRect) As Ptr Declare Function superview Lib "AppKit" Selector "superview" (NSView As Ptr) As Ptr Declare Sub removeFromSuperview Lib "AppKit" Selector "removeFromSuperview" (NSView As Ptr) Declare Sub addSubview Lib "AppKit" Selector "addSubview:" (NSView As Ptr, aView As Ptr) Declare Sub setDocumentView Lib "AppKit" Selector "setDocumentView:" (NSView As Ptr, aView As Ptr) Declare Sub setHasVS Lib "AppKit" Selector "setHasVerticalScroller:" (NSScrollView As Ptr, f As Boolean) Dim scrollView As Ptr = initWF(alloc(NSClassFromString("NSScrollView")), NSMakeRect(0, 0, Width, Height)) setHasVS(scrollView, True) Dim xojoView As Ptr = Ptr(Handle) Dim superview As Ptr = superview(xojoView) Call retain(xojoView) removeFromSuperview(xojoView) addSubview(superview, scrollView) setDocumentView(scrollView, xojoView) Call release(xojoView) RaiseEvent Open() End Sub
In the canvas instance on the window I do as test:

Window1 Control Canvas1: Sub Open() Me.Height = Me.Height * 2 End Sub Sub Paint(g As Graphics, areas() As REALbasic.Rect) g.DrawOval(0, 0, g.Width, g.Height) End Sub
You then see only the upper half of the oval and the native Cocoa scroller appears when you try to scroll vertically.

Note:
The scroll views coordinate system is cartesian (meaning 0, 0 is in the left bottom corner), which is the standard in Cocoa. To change that to 0, 0 being the top left corner, the scrollView above would need to be an instance of a subclass created in the Objective C Runtime where the isFlipped method is overridden and returns True.[/quote]

Thanks Eli and I will give this a try. I have a very OOP situation that I can easily add this into Window --> Container —> SubClass Canvas Class

I may ask a few additional questions on this, but thank you again for the push in this direction!

  • Mike

Thanks again!