如何在我的应用程序中禁用所有 NSCursor 更新?

How to disable all NSCursor updates in my application?

在我的 macOS 应用程序中,我有一个自定义 WebView。当用户将鼠标光标移动到 WebView 网页中的不同元素(如文本、链接等(我认为是作为子视图实现的))时,光标会根据元素的类型自动更新。

我的要求是我想为 WebView 设置一个自定义光标(如果可能的话甚至为我的整个应用程序),并且不要让它发生任何变化,至少在我以编程方式在代码的其他部分更改它之前.我试图在 AppDelegate 的 applicationDidFinishLaunching: 方法中设置 NSCursor,但它立即被重置。

我尝试了很多解决方案,例如设置 NSTrackingArea、向我的 NSApplicationNSWindow 发送 disableCursorRects,甚至监控光标更新事件,但都没有成功.

那么有没有办法在我的应用程序中禁用所有 NSCursor 更新?我会在 applicationDidFinishLaunching: 中将它设置为我的自定义光标,并希望它在应用程序运行时保持不变,或者我在代码中更改它。

您可以在 WebView 中使用用户样式表来设置 html 元素的默认光标。

WebPreferences *preferences = [[[WebPreferences alloc] initWithIdentifier:@"TestIdentifier"] autorelease];

NSURL *stylesheetURL = [[NSBundle bundleForClass:[self class]] URLForResource:@"yosemite-stylesheet" withExtension:@"css" subdirectory:@"Welcome"];

preferences.userStyleSheetEnabled = YES;
preferences.userStyleSheetLocation = stylesheetURL;


self.webView.preferences = preferences;

找到适合我的解决方案!这是我的做法:

子类 NSView 并重写 resetCursorRects 方法,其中发送 addCursorRect:cursor: 及其边界作为游标矩形和所需的游标(描述为 here)。然后使用与WebView相同的frame创建这个自定义NSView的实例,并将其作为子视图添加到后面。这将充当 WebView 上的透明覆盖层。它只影响光标,不影响鼠标点击或按键。

这是 PyObjC 中的代码(该概念也适用于 Objective C):

# Overlay View (NSView subclass)
class OverLayView(AppKit.NSView):
   def resetCursorRects(self):
       self.addCursorRect_cursor_(self.bounds(), my_custom_cursor)

# In my main class
    ...
    self.overlay = OverLayView.alloc().initWithFrame_(self.webview.bounds())
    self.webview.addSubview_(self.overlay)
    ...

如果我想将光标重置回自动,我可以删除这个叠加视图,或者更好的是,通过向它发送 setHidden: 消息将其暂时隐藏:

self.overlay.setHidden_(Foundation.YES)

一些额外的注意事项:

  • 使用 NSTrackingArea 代替光标矩形似乎效果不佳。对我来说没有。
  • 我已经在自定义 WebView 本身上尝试了上述方法,但没有用。 WebView 的默认跟踪 areas/cursor rects 总是干扰。在它上面添加一个子视图会阻止这种行为,就像上面的代码一样。
  • 最终叠加视图 应该是 WebView 的子视图。如果两者都是同一个父视图的兄弟视图,Cocoa 不能保证哪个会在另一个之上。

如果有人有更好的解决方案,或者可以改进这个,请随时post。

希望这对某人有所帮助!