Macos 在非活动窗口上更改鼠标光标

Macos 在非活动窗口上更改鼠标光标,macos,cocoa,mouse,mouseover,nswindow,Macos,Cocoa,Mouse,Mouseover,Nswindow,我有一个子类NSWindow,还有一个MYWindow类实现了以下方法: -(void)resetCursorRects { NSImage *image = [NSImage imageNamed:@"cursor.png"]; [image setSize:NSMakeSize(32, 32)]; NSCursor *cursor = [[NSCursor alloc] initWithImage:image hotSpot:NSMakePoint(1, 1)];

我有一个子类NSWindow,还有一个MYWindow类实现了以下方法:

-(void)resetCursorRects {
    NSImage *image = [NSImage imageNamed:@"cursor.png"];
    [image setSize:NSMakeSize(32, 32)];
    NSCursor *cursor = [[NSCursor alloc] initWithImage:image hotSpot:NSMakePoint(1, 1)];
    [super resetCursorRects];    
    [self addCursorRect:[self bounds] cursor:cursor];
}
这将改变整个窗口的光标,我将看到cursor.png而不是默认的鼠标指针。问题是,只有当MYWindow设置为key window时,它才起作用,而key window的设置当然非常重要

在我的项目开始时,我只有一个主窗口,但现在我需要有两个不同的MYWindow。两个窗口的问题是,无法将这两个窗口都设置为关键点窗口,因此自定义鼠标指针仅显示在活动窗口上。我需要单击另一个窗口以显示光标

这有什么办法吗?所以我在两个窗口上都有一个自定义光标

编辑:尝试跟踪区域

我将此添加到我的内容视图的init方法中:

self.trackingArea = [[NSTrackingArea alloc] initWithRect:[self frame] options: (NSTrackingCursorUpdate | NSTrackingActiveAlways | NSTrackingMouseMoved) owner:self userInfo:nil];
[self addTrackingArea:self.trackingArea];
然后我覆盖了cursorUpdate:如下所示:

-(void)cursorUpdate:(NSEvent *)event {
    NSLog(@"event : %@", event);
    [[NSCursor crosshairCursor] set];
}

当包含NSImageView派生类的NSWindow为key window时,这会使CrossHairsor显示。但如果我将应用程序中的另一个NSWindow设置为键窗口,光标将再次返回到标准光标。我做错什么了吗?

你应该能够添加一个NSTrackingArea来更改光标,只要你不希望它在应用程序处于非活动状态时也发生更改(这基本上是不可能的)


编辑:

我能够使用以下代码实现此功能:

- (vod)someSetup;
{
    NSTrackingArea *const trackingArea = [[NSTrackingArea alloc] initWithRect:NSZeroRect options: (NSTrackingMouseEnteredAndExited | NSTrackingActiveAlways | NSTrackingInVisibleRect) owner:self userInfo:nil];
    [self.view addTrackingArea:trackingArea];
}

- (void)mouseEntered:(NSEvent *)theEvent;
{
    [[NSCursor IBeamCursor] push];
}

- (void)mouseExited:(NSEvent *)theEvent;
{
    [[NSCursor IBeamCursor] pop];
}

现在我终于找到了一个有效的解决方案。我不知道这是否会在将来咬我的尾巴,但至少这似乎在测试时起作用

谢谢威尔给我的例子,它让我走了一半。但直到我最终将它与resetCursorRects结合起来,并在每个视图中使用特定的游标定义了游标rect时,我才这样做。我花了很长时间才弄明白,我不知道解决方案是否最优(欢迎提出改进建议)

下面是使它最终对我起作用的完整示例(self.cursor是游标的一个实例)


我很长一段时间都在努力解决这个问题,我认为只有一种方法可以将鼠标光标移到非活动应用程序(非前台窗口)上。这是一种老套而神奇的方式

在调用pretty standard之前:

[[NSCursor pointingHandCursor] push];
你必须打电话:

void CGSSetConnectionProperty(int, int, int, int);
int CGSCreateCString(char *);
int CGSCreateBoolean(BOOL);
int _CGSDefaultConnection();
void CGSReleaseObj(int);
int propertyString, boolVal;

propertyString = CGSCreateCString("SetsCursorInBackground");
boolVal = CGSCreateBoolean(TRUE);
CGSSetConnectionProperty(_CGSDefaultConnection(), _CGSDefaultConnection(), propertyString, boolVal);
CGSReleaseObj(propertyString);
CGSReleaseObj(boolVal);
或者,如果您正在使用Swift:

将其放入你的
应用程序桥接标题中。h

typedef int CGSConnectionID;
CGError CGSSetConnectionProperty(CGSConnectionID cid, CGSConnectionID targetCID, CFStringRef key, CFTypeRef value);
int _CGSDefaultConnection();
然后打电话:

let propertyString = CFStringCreateWithCString(kCFAllocatorDefault, "SetsCursorInBackground", 0)
CGSSetConnectionProperty(_CGSDefaultConnection(), _CGSDefaultConnection(), propertyString, kCFBooleanTrue)

我猜你指的是NSTrackingArea?我现在已经试过了,但是我不能让它工作。我只想在应用程序处于活动状态时更改光标,但我需要在应用程序内的非活动NSWindows上也更改光标。我将用我的发现更新我的问题。谢谢!现在这是非常接近工作后,编辑,只有一件事要解决。现在,它在我的两个NSWindows中正确地显示了正确的光标,但只要我单击其中一个NSWindows,光标就会恢复为标准的。如果我再从窗口进出,那就又对了。但我也需要解决这个小问题。你的窗口中有什么视图?视图上还有cursorUpdate:方法吗?它们都是NSImageView的子类,我删除了cursorUpdate:方法。在子类中,我实现了viewWillMoveToWindow(示例中包含someSetup的内容)、mouseEntered(与示例中完全相同)、mouseexitted(与示例中完全相同)。仅此而已。我不熟悉OSX,但从我读到的addCursorRect为整个rect定义了一个特定的光标-如果您想在鼠标移动到不同区域时更改光标,该怎么办?假设我不能预先定义所有的矩形。我想您可以更改self.cursor并调用resetCursorRects。。。覆盖
windowDidBecomeKey
windowDidBecomeMain
以同时调用
[self.cursor push]
似乎是另一种解决方案,尽管单击窗口时确实会短暂看到光标闪烁到正常箭头。(您是否需要使用游标矩形来推送
呢?)如果没有桥接头怎么办。如何在Swift中声明这些行?我相信您只需要有
桥接头
(为什么不?),因为没有其他方法(IMO)在Swift代码中导入这些函数。或者您可以将此代码放入动态库(用C或Objective-C编写),然后将其导入Swift代码中。我想没有理由不使用它。到目前为止,我的应用程序完全使用Swift,但我无法完成这部分操作。剩下的唯一一块拼图是让
cGassociateMouseandMouseCorPosition
也在后台工作。我的应用程序也是如此。我不认为在非主线程中使用UI方法是个好主意。。。但也许像“调度同步”这样的东西可以帮助你。这种方法仍然有效吗?应该包括哪个框架或库来实现这一点?我在OS X 10.11上得到链接器错误:_CGSCreateBoolean、_CGSCreateCString、_CGSReleaseObj相关问题→
let propertyString = CFStringCreateWithCString(kCFAllocatorDefault, "SetsCursorInBackground", 0)
CGSSetConnectionProperty(_CGSDefaultConnection(), _CGSDefaultConnection(), propertyString, kCFBooleanTrue)