在我的应用程序的主菜单中设置项目的标题?

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) 

【讨论】:

以上是关于在我的应用程序的主菜单中设置项目的标题?的主要内容,如果未能解决你的问题,请参考以下文章

GraphQL:我需要在我的项目中设置啥?

在 Intellij 中设置 grails 项目

在Intellij中设置grails项目

如何在另一个模块中设置全局变量?

如何在 AngularJS 中设置嵌套视图?

从库 C++ 中设置环境变量