在我的应用程序的主菜单中设置项目的标题?
Posted
技术标签:
【中文标题】在我的应用程序的主菜单中设置项目的标题?【英文标题】:set titles of items in my app's main menu? 【发布时间】:2011-06-25 07:51:24 【问题描述】:我正在尝试更改 Cocoa 应用程序主菜单中某些项目的标题。我尝试在 IB 中设置它们,也尝试通过我的应用程序的 applicationDidFinishLaunchingWithOptions: 方法以编程方式设置它们。无论哪种方式,我的 NSMenuItem 对象的 title 属性都会发生变化。但是当应用程序运行时,我所做的任何更改都不会反映在屏幕顶部的项目的实际标题中。
谁能解释发生了什么?我该如何改变呢?
编辑:数据结构是 IB 设置的默认结构:
NSApplication *app = [NSApplication sharedApplication];
NSMenu *mainMenu = [app mainMenu];
NSArray *itemArray = [mainMenu itemArray];
NSMenuItem *firstItem = [itemArray objectAtIndex: 0];
NSMenu *submenu = [firstItem submenu];
我已将 firstItem 和 subMenu 的标题属性更改为我想要的标题。然而默认的仍然显示。
【问题讨论】:
它们是独立的NSMenuItem
实例还是NSMenu
实例? NSMenu
保留自己的标题。
屏幕顶部菜单栏中显示的应用程序的主菜单是一个NSMenu;但它的每个可见条目 - 例如“应用程序名称”、“文件”、“编辑”、“视图”等 - 是一个 NSMenuItem。每个菜单项都包含一个 NSMenu,它是您看到的下拉子菜单。所以它是一个 NSMenu,但它是一个“特殊的”,它在菜单栏中水平显示而不是垂直显示。现在,我希望您能够在将 NIB 加载到 Interface Builder 时双击显示的模拟菜单栏中的项目并直接在那里设置文本。这不适合你吗?
Andrew -- 我可以更改文本,但在应用程序中仍然显示相同。
Codeweavers 的某个人说他们使用“丑陋的黑客”来做到这一点,他们在 AppKit 看到之前更改了应用程序包的名称。我没有详细信息。
【参考方案1】:
不要重命名项目,而是从 $PRODUCT_NAME 更改 your-application-Info.plist 中的“Bundle name”;随心所欲;此更改将反映在主菜单的应用程序菜单项的标题中。
【讨论】:
【参考方案2】:有时,这只是行不通,因为 Cocoa 不喜欢你的标题 :-p 这种情况会发生,例如当您选择的标题是本地化的应用程序名称,但它想显示非本地化的应用程序名称。一个小技巧可以帮助...
NSMenu *menu = [[[NSApp mainMenu] itemAtIndex:0] submenu];
NSString *title = @"My app name";
// Append some invisible character to title :)
title = [title stringByAppendingString:@"\x1b"];
[menu setTitle:title];
是的,这很疯狂,但最后那个额外的角色让一切变得不同。 (您也可以仅附加一个 SPACE,但随后菜单项会增长,这可能不是您想要的。)
在 OS X 10.9.5 上测试。
另一件事:
您必须在显示窗口后执行所有这些操作。否则它就是行不通的。此外,如果您在应用程序启动时执行此过程,然后在显示窗口时再次执行此过程,它可能也不起作用。
【讨论】:
我在 - (void)applicationDidFinishLaunching:(NSNotification *)aNotification 中做了这个,它工作得很好。 这确实有效,但标题不再是粗体了? @basdp:这是个问题吗?或者你有没有标题不再是粗体的问题?在我测试过的所有地方,标题都是粗体。 是的,我也有同样的经历。菜单栏中的第一个菜单标题(前应用程序名称)发生变化,但不再是粗体。我试过设置字体,没有结果。代码是: let items = NSApplication.shared.mainMenu?.items let firstItem = items?[0] let subMenu = firstItem?.submenu subMenu?.title = "NewApplication " subMenu?.font = NSFont.boldSystemFont(ofSize: 0) 【参考方案3】:重命名项目做到了。不过好像太极端了。我仍然会对不太极端的解决方案感兴趣。
【讨论】:
当您说“重命名”时,您的意思是您只是更改了文件名并解决了问题,还是您以新名称“从干净”重新创建项目? 在 Xcode 中,项目菜单 > 重命名。这改变了很多事情。 . .我没有调查他们中的哪一个成功了。 好的,谢谢 - 可能对遇到同样问题的其他人有用。 如果您仍然对不太极端的解决方案感兴趣,那么您应该接受@askh 的回答?【参考方案4】:迟到总比没有好:在四处挖掘之后,我找到了一个可行的解决方案,甚至两个!
您可以设置带有渲染文本的菜单图像(您可以使用粗体!)
// render a string into image
let string = NSString(string: "Application Name")
let font = NSFont.boldSystemFont(ofSize: 13)
let size = string.size(withAttributes: [.font: font])
let image = NSImage(size: size)
image.lockFocus()
let rect = NSRect(origin: NSPoint(x: 0, y: 0.5), size: size)
string.draw(with: rect, options: [.usesLineFragmentOrigin], attributes: [.font: font])
image.unlockFocus()
appMenuItem.submenu?.title = " " // clear original App Name
appMenuItem.image = image // set the image instead
或者,您可以更改整个进程名称,包括 Apple 菜单标题(感谢 this answer!)
// dynamically load ApplicationServices.GetCurrentProcess
typealias GetCurrentProcessType = @convention(c) (UnsafePointer<ProcessSerialNumber>) -> OSStatus
let getCurrentProcessSym = dlsym(UnsafeMutableRawPointer(bitPattern: -2), "GetCurrentProcess")!
let getCurrentProcess = unsafeBitCast(getCurrentProcessSym, to: GetCurrentProcessType.self)
// dynamically load ApplicationServices.CPSSetProcessName
typealias CPSSetProcessNameType = @convention(c) (UnsafePointer<ProcessSerialNumber>, UnsafePointer<Int8>) -> OSStatus
let cpsSetProcessNameSym = dlsym(UnsafeMutableRawPointer(bitPattern: -2), "CPSSetProcessName")!
let cpsSetProcessName = unsafeBitCast(cpsSetProcessNameSym, to: CPSSetProcessNameType.self)
// Get current process serial number
var psn = ProcessSerialNumber()
getCurrentProcess(&psn)
// Change Process Name
"Custom Title".withCString cpsSetProcessName(&psn, $0)
【讨论】:
以上是关于在我的应用程序的主菜单中设置项目的标题?的主要内容,如果未能解决你的问题,请参考以下文章