【问题标题】:Cocoa: pasting formatted text in the current font?Cocoa:以当前字体粘贴格式化文本?
【发布时间】:2009-10-06 13:12:44
【问题描述】:

当我将格式化文本放入粘贴板 (NSRTFPboardType) 时,它会在粘贴时保留所有格式。但我真正想要的是丢弃字体和大小信息,同时保留重量、颜色等。

根据文档,没有字体信息的 NSAttributedString 将默认为 Helvetica 12,所以这似乎是一个死胡同。

我还可以按需生成文本,所以如果我可以找出当前 UI 元素中的字体,我可以在文本进入粘贴板之前对其进行修改。我希望可访问性 API 可以对此有所帮助,但我在 UIElementInspector 中找到的所有属性似乎都无法处理格式。

有什么想法吗?

这是一个测试用例。即使唯一的属性是绿色,它也会在 Helvetica 12 中粘贴:

// Create the string with no attributes, and strip the font just in case.
NSMutableAttributedString *s = [[[NSMutableAttributedString alloc] initWithString:@"Hello green world!"] autorelease];
[s removeAttribute:NSFontAttributeName range:NSMakeRange(0, [s length])];

// Add a test attribute
[s addAttribute:NSForegroundColorAttributeName value:[NSColor greenColor] range:NSMakeRange(6, 5)];

// Generate RTF data 
NSData *rtf = [s RTFFromRange:NSMakeRange(0, [s length]) documentAttributes:nil];

// Copy to pasteboard
NSPasteboard *pb = [NSPasteboard generalPasteboard];
[pb declareTypes:[NSArray arrayWithObject:NSRTFPboardType] owner:nil];
[pb setData:rtf forType:NSRTFPboardType];

这里有一些有趣的东西。如果我尝试生成最简单的原始 RTF 数据,绝对没有字体信息,它仍然会粘贴到 Helvetica 12 中!

char *rawrtf = "{\\rtf1\\ansi\\ansicpg1252\n"
               "Hello world.}";
NSData *rtf = [NSData dataWithBytes:rawrtf length:strlen(rawrtf)];

因此,如果这完全可能的话,我认为只有通过查询当前正在运行的应用程序的当前字体才有可能。

【问题讨论】:

  • 您可以尝试使用 NSPasteboardTypeHTML 将 HTML 添加到粘贴板,但我不太确定是否有可能实现您的目标。
  • 我开始怀疑如果没有一些非常讨厌的黑客攻击是不可能的。大多数应用程序可能不接受 HTML 格式,但可能值得一试。

标签: objective-c cocoa


【解决方案1】:

“当前字体”没有系统范围甚至应用程序范围的概念。您可以获得的最接近的是当前活动的NSTextView 的打字属性;如果没有激活,则没有什么像当前字体。

话虽如此,您可以向粘贴板承诺 RTF 数据,当它请求它时,向当前活动的应用程序发送一个复制 AppleEvent 命令,等待响应,从粘贴板上拉出任何富文本,并获取其字体属性。如果没有可用的富文本,请坚持使用当前的字体和大小。我不知道这种启发式方法在实践中的效果如何,但我想不出更好的方法。

如果我尝试生成最简单的原始 RTF 数据,但绝对没有字体信息,它仍然会粘贴到 Helvetica 12 中!

当没有提供字体信息时,字体默认为 Helvetica-12,因为所有正在绘制的文本都必须采用 some 字体和 some 大小。 Helvetica-12 必须看起来具有可读性和足够的无害性,才能被选为默认值。 (当然胜过 Comic Sans-72!)

【讨论】:

  • 如果没有选择,复制操作通常不会是空的吗?不过我会尝试这个想法,我喜欢它。
【解决方案2】:

NSAttributedString 是不可变的。我想也许你需要的是NSMutableAttributedStringThis guide 有一个如何改变事物的例子。您应该能够创建一个新的 NSMutableAttributedString 作为 NSAttributedString 的副本,然后在将其传递到粘贴板之前对其进行修改。

编辑:

我不太确定你要做什么。您是说要保留一些格式,并删除其他格式,并且您似乎了解如何操作 NSMutableAttributedString 属性,那么问题出在哪里?创建一个新的属性字符串,询问旧字符串,然后将您想要的任何属性应用于新字符串,如果您不喜欢默认字体,请更改它。我不明白问题出在哪里。

EDIT2:

使用initWithAttributedString: 应该复制字体属性,但如果没有,你应该能够使用enumerateAttributesInRange:options:usingBlock: 来询问你原来的 NSAttributedString

EDIT3:

NSAttributedString *attrStr;
NSRange limitRange;
NSRange effectiveRange;
id attributeValue;

limitRange = NSMakeRange(0, [attrStr length]);

while (limitRange.length > 0) {
    attributeValue = [attrStr attribute:NSFontAttributeName
        atIndex:limitRange.location longestEffectiveRange:&effectiveRange
        inRange:limitRange];

    // apply attributeValue to the other mutable attributed string range here

    limitRange = NSMakeRange(NSMaxRange(effectiveRange),
        NSMaxRange(limitRange) - NSMaxRange(effectiveRange));
}

【讨论】:

  • 我尝试生成一个没有格式化的新 NSMutableAttributedString,并去掉字体属性。它仍然粘贴为 Helvetica 12。
  • [mutableAttrStr addAttribute:NSFontAttributeName value:nameOfFont range:r] 应该可以工作
  • 问题是我不知道nameOfFont。如果我可以确定用户正在编辑的当前字体,我可以设置它。用户通常会在我的应用程序之外粘贴,我不确定是否可以在我自己的应用程序之外访问当前字体。这就是我研究无障碍 API 的原因。
  • 例如,假设用户正在 Mail.app 中撰写邮件,当前字体是 Times New Roman 14。当他粘贴富文本时,它是 Helvetica 12,字体错误。我正在寻找一种将其保留在 Times New Roman 14 中的方法,同时仍保留粗体、斜体、颜色等。
  • 是的,他的意思是:根据周围文本的字体,明确地自己设置字体。
【解决方案3】:

更改复制的文本使其与用户复制的内容不同会违背复制和粘贴的想法,不是吗?

【讨论】:

  • 在这种情况下,它不是用户复制的东西。它是由我的应用程序生成的格式化文本,用户希望将其粘贴到当前字体中。
  • 啊,好的。我明白你现在打算做什么。在这种情况下,这是一个废话拍摄。您的用户粘贴到的应用程序本身可以对粘贴的文本执行任何操作。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-09-29
  • 2023-03-29
  • 2013-06-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多