【问题标题】:How to disable all NSCursor updates in my application?如何禁用我的应用程序中的所有 NSCursor 更新?
【发布时间】:2017-05-08 13:00:27
【问题描述】:

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

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

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

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

【问题讨论】:

  • 我觉得 window.disableCursorRects() 应该适用于此。如果没有,这似乎是一个 Apple 错误。

标签: macos cocoa webview nscursor


【解决方案1】:

您可以在 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;

【讨论】:

  • 谢谢,但我尝试通过编辑 HTML 样式(通过 JS,使用 stringByEvaluatingJavaScriptFromString:)来实现这一点。我发现这种方法有很多缺点,比如在加载 WebView 时它不起作用,似乎在 iframes 上不起作用等等。有没有更好的方法,而不依赖于 web 内容?
  • 用户样式表不同于尝试通过 JS 更改它。它适用于在 web 视图中访问的所有页面,因此也适用于所有 iframe。对于加载部分我不确定......
  • 好的,但我觉得这个解决方案仍然很老套。如果 HTML 页面的自定义样式表覆盖 CSS cursor 属性,我将无法获得所需的行为。我也想要 webView 加载时的行为。仍在寻找更好的解决方案。感谢您尝试提供帮助。 :)
  • 是的,我读过不止一次。试过了,失败了。但我最终用同样的方法找到了更好的解决方案。见我上面的回答。 :)
【解决方案2】:

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

子类NSView 并覆盖resetCursorRects 方法,其中发送addCursorRect:cursor: 及其边界作为光标rect 和所需的光标(描述here)。然后创建这个自定义NSView 的实例WebView 具有相同的框架,并将其作为子视图添加到后者。这将作为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 的默认跟踪区域/光标矩形总是干扰。就像上面的代码一样,在它上面添加一个子视图会阻止这种行为。
  • 最后,覆盖视图应该是WebView 的子视图。如果两者都是同一个 superview 的兄弟视图,Cocoa 不保证哪一个会在另一个之上。

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

希望这对某人有所帮助!

【讨论】:

    猜你喜欢
    • 2011-10-21
    • 1970-01-01
    • 2021-08-04
    • 1970-01-01
    • 2013-09-20
    • 2012-02-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多