Search code examples
macoscocoaresourcescursor

OSX Cocoa cursor in resources


ALL,

On Windows cursors are indicated by the cur file extension. Is there something similar for OSX Cocoa application?

Is there a way in XCode to edit such files, just like in MSVC there is some basic graphical editor?

Also, is there a special API which will allow loading such files on Cocoa? Or I can just load them as images?

TIA!!

EDIT:

In the meantime I think I found a good solution that will satisfy my needs

NSString *path;
NSBundle *bundle = [NSBundle mainBundle];
NSString *path = [bundle pathForResource:cursor_file ofType:@"cur"];
if( path )
{
    CGImageSourceRef image = CGImageSourceCreateWithURL( path, nil );
    CFDictionaryRef properties =

CGImageSourceCopyPropertiesAtIndex( image, 0, nil ); NSInteger x = properties["hotspotX"]; NSInteger y = properties["hotspotY"]; }

Except that it doesn't compile:

I need to import the file where CGImageSourceCreateWithURL() is declared, and I need to fix the last 2 lines, because the array subscript can't be strings.

Could someone help, please?


Solution

  • The following source code will create a custom NSCursor in Xcode from a .cur image, after retrieving its “hotspot” coordinates from the file located in the app bundle Resource folder. Replace the contents of the main.m file with the code below and delete the pre-supplied AppDelegate files to avoid duplicate symbols. You will need to copy/paste the .cur file into the Xcode project folder and also drag and drop it into the Project navigator. Xcode will not automatically place this file into the Resources folder of your application bundle (unlike a .png file), so copy/paste it there as well after you have compiled the app. Reference: Hotspot in Windows cursor .cur loaded by NSImage?

    #import <Cocoa/Cocoa.h>
    
    @interface AppDelegate : NSObject <NSApplicationDelegate> {
      NSWindow *window;
      CGFloat x,y;
    }
    @end
    
    @implementation AppDelegate
    
    - (void) customCursor {
        // **** Get HotSpot from .cur file **** //
        NSBundle *bundle = [NSBundle mainBundle];
        NSURL *url = [bundle URLForImageResource:@"myCursor.cur"];
        if( url ) {
        CGImageSourceRef image = CGImageSourceCreateWithURL( (__bridge CFURLRef)url, nil );
        NSDictionary *properties = (__bridge NSDictionary *)CGImageSourceCopyPropertiesAtIndex( image, 0, nil );
            x = [[properties objectForKey:@"hotspotX"]floatValue];
            y = [[properties objectForKey:@"hotspotY"]floatValue];
            CFBridgingRelease(image);
            CFBridgingRelease((__bridge CFTypeRef _Nullable)(properties));
        }
        NSCursor *customCursor = [[NSCursor alloc] initWithImage:[NSImage imageNamed:@"myCursor.cur"] hotSpot: NSMakePoint( x, y) ];
        [customCursor set];
        NSLog(@"x = %0.02f",x);
        NSLog(@"y = %0.02f",y);
        
    }
    
    - (void) arrowCursor {
     [[NSCursor arrowCursor] set];
    }
    
    - (void) buildMenu {
     NSMenu *menubar = [NSMenu new];
     [NSApp setMainMenu:menubar];
     NSMenuItem *menuBarItem = [NSMenuItem new];
     [menubar addItem:menuBarItem];
     NSMenu *appMenu = [NSMenu new];
     [menuBarItem setSubmenu:appMenu];
     [appMenu addItemWithTitle:@"Quit" action:@selector(terminate:) keyEquivalent:@"q"];
    }
    
    - (void) buildWnd {
    
     #define _wndW  500
     #define _wndH  250
    
     window = [[NSWindow alloc] initWithContentRect: NSMakeRect( 0, 0, _wndW, _wndH )  styleMask: NSWindowStyleMaskTitled | NSWindowStyleMaskMiniaturizable | NSWindowStyleMaskClosable backing: NSBackingStoreBuffered defer: NO];
     [window center];
     [window setTitle: @"Custom cursor"];
     [window makeKeyAndOrderFront: nil];
    
    // **** Button 1 **** //
     NSButton *myBtn =[[NSButton alloc]initWithFrame:NSMakeRect( 30, 30, 135, 30 )];
     [myBtn setBezelStyle:NSBezelStyleRounded ];
     [myBtn setTitle: @"Custom Cursor"];
     [myBtn setAction: @selector (customCursor)];
     [[window contentView] addSubview: myBtn];
    
    // **** Button 2 **** //
     NSButton *myBtn2 =[[NSButton alloc]initWithFrame:NSMakeRect( 190, 30, 135, 30 )];
     [myBtn2 setBezelStyle:NSBezelStyleRounded ];
     [myBtn2 setTitle: @"Arrow Cursor"];
     [myBtn2 setAction: @selector (arrowCursor)];
     [[window contentView] addSubview: myBtn2];
    
    // **** Quit btn **** //
     NSButton *quitBtn = [[NSButton alloc]initWithFrame:NSMakeRect( _wndW - 50, 10, 40, 40 )];
     [quitBtn setBezelStyle:NSBezelStyleCircular ];
     [quitBtn setTitle: @"Q" ];
     [quitBtn setAction:@selector(terminate:)];
     [[window contentView] addSubview: quitBtn];
    }
    
    - (void) applicationWillFinishLaunching: (NSNotification *)notification {
     [self buildMenu];
     [self buildWnd];
    }
    
    @end
    
    int main() {
    NSApplication *application = [NSApplication sharedApplication];
    AppDelegate *appDelegate = [[AppDelegate alloc] init];
    [application setDelegate:appDelegate];
    [application run];
    return 0;
    }