Grabbing the NSCursor Image for custom cursors

I’m creating a sort of “listbox on steroids” for a project and find myself wanting the equivalent of the DragItem.DragPicture feature when the user clicks and drags selected items around. The problem is that I can’t use DragItem because I also need the MouseEvent to continue firing. This has been discussed elsewhere on the forum with no solid solution.

Here’s my workaround: create a custom cursor.

I’ve pieced together some code that grabs the image of the system cursor and then allows me to add to it. I then take the resulting image and set it as my mouse cursor:

[code]intNSRect | origin as nspoint, resize as nsize
NSPoint | x as single, y as single
NSSize | width as single, height as single

Soft Declare Function NSClassFromString Lib “Cocoa” (aClassName as CFStringRef) as Ptr
Soft Declare Function imageNamed Lib “Cocoa” selector “imageNamed:” (class_id as Ptr, name as CFStringRef) as Ptr
Soft Declare Function arrowCursor Lib “Cocoa” Selector “arrowCursor” (id as Ptr) as Ptr
Soft Declare Function image lib “Cocoa” selector “image” (id As Ptr) As Ptr
Soft Declare Function size lib “Cocoa” selector “size” (obj_id as Ptr) as NSSize
Soft declare function CGImageForProposedRect lib “Cocoa” selector “CGImageForProposedRect:context:hints:” (obj_id as Ptr, byref proposedDestRect as intNSRect, referenceContext as Ptr, hints as Ptr) as Ptr
soft declare sub CGContextDrawImage lib “Cocoa” (context as Ptr, rect as intNSRect, image as Ptr)

Dim iPtr as Ptr = image(arrowCursor(NSClassFromString(“NSCursor”)))
Dim cursSize as NSSize = size(iPtr)
Dim p as New Picture (cursSize.width, cursSize.height)
Dim cntx as Ptr=ptr(p.Graphics.Handle(Graphics.HandleTypeCGContextRef))

Dim rect As intNSRect
rect.rsize = cursSize

dim cgPtr As ptr=CGImageForProposedRect(iPtr,rect,nil,nil)

CGContextDrawImage cntx, rect, cgPtr

Dim NewPic as New Picture(100, 40)
NewPic.Graphics.DrawPicture(p,0,0)

NewPic.Graphics.DrawString(“Hello, world.”, p.width, p.height)

dim c as mousecursor
c = new mousecursor(NewPic, 5, 5) '<-- How do I get (5,5) programmatically?
self.mousecursor = c[/code]

My questions:

  1. Does the code look “kosher”? I’m relatively new to using declares and OS functions.
  2. This returns the image of the default arrow cursor, but I can’t figure out how to get other cursors (closedhand, I-beam, etc).
  3. How can I get the hotspot from the cursor? From trial and error, I found the hotspot of the default arrow cursor to be (5,5), but I assume it’s different if the cursor is different.
  4. How hard is it to adapt this code to Windows? Obviously, I can’t use Cocoa functions. Are there equivalent Windows functions to grab the image of the cursor?

Thank you so much!!

FWIW there is a declare for implementing a new cursor during drag in this thread :
https://forum.xojo.com/14202-drag-border-vs-focusring-visual-cues-and-drop-file-selected/0

[quote=309700:@Matthew Pool]How can I get the hotspot from the cursor? From trial and error, I found the hotspot of the default arrow cursor to be (5,5), but I assume it’s different if the cursor is different.
How hard is it to adapt this code to Windows? Obviously, I can’t use Cocoa functions. Are there equivalent Windows functions to grab the image of the cursor?[/quote]

If you design your own cursors, you should make sure they keep the hotspot at the same place. That is the easiest.

Windows : https://msdn.microsoft.com/en-us/library/system.windows.forms.cursor.aspx

First, thanks for your response, Michel!

[quote=309701:@Michel Bujardet]FWIW there is a declare for implementing a new cursor during drag in this thread :
https://forum.xojo.com/14202-drag-border-vs-focusring-visual-cues-and-drop-file-selected/0
[/quote]

I actually came across this thread earlier. It’s similar, but it doesn’t exactly address what I’m trying to do. However, one of my questions was answered after re-reading the posts on that thread. In order to get a different cursor:

Soft Declare Function arrowCursor Lib “Cocoa” Selector “arrowCursor” (id as Ptr) as Ptr

should be changed to:

Soft Declare Function arrowCursor Lib “Cocoa” Selector "[b]closedHandCursor[/b]" (id as Ptr) as Ptr

I kept trying to replace “arrowCursor” with variants of “closedHand”, but didn’t realize that I needed to include “Cursor”.

Agreed. But how do I get the hotspot coordinates from a specified system cursor?

Definitely promising!

Update…

Here’s an image that shows the code above (with some minor modifications) in use. I hope it better explains what I’m trying to do!

By the way, I figured out the code to get the hotspot. (My third question above)

Soft Declare Function hotSpot Lib "Cocoa" Selector "hotSpot" (id as Ptr) as NSPoint

I’m still not entirely confident this is the best way to grab the cursor image, but it seems to work. I’m also not sure how to accomplish this in Windows, but that may be more appropriate to ask in the Windows channel…