以编程方式设置Mac菜单栏标题

时间:2013-01-02 12:47:19

标签: macos nsbundle

如何以编程方式更改Mac菜单栏中的应用程序标题(启动应用程序后)?

我知道我可以在Info.plist文件中通过CFBundleName运行程序之前设置它。但是,我需要在初始化应用程序后更改它。操纵我自己的Info.plist也行不通。

没有官方API这样做,但在this discussion有人暗示有一个秘密函数调用更改了包名称/菜单栏标题:

  

“如果你看起来很难看,你可以使用SPI,但是   我不会指出任何人,除非他们可以证明他们为什么这样做   需要使用它:-)“

我认为Java也使用类似的东西。那么什么是秘密API?

1 个答案:

答案 0 :(得分:1)

好的,我找到了办法。这是Python中的代码(采用from here)。它可以使用一些清理和一些错误处理,但它的工作原理。关键是来自ApplicationServices的未记录的CPSSetProcessName。

def _osx_set_process_name(app_title):
    """ Change OSX application title """

    from ctypes import cdll, c_int, pointer, Structure
    from ctypes.util import find_library

    app_services = cdll.LoadLibrary(find_library("ApplicationServices"))

    if app_services.CGMainDisplayID() == 0:
        print "cannot run without OS X window manager"
    else:
        class ProcessSerialNumber(Structure):
            _fields_ = [("highLongOfPSN", c_int),
                        ("lowLongOfPSN", c_int)]
        psn = ProcessSerialNumber()
        psn_p = pointer(psn)
        if (  (app_services.GetCurrentProcess(psn_p) < 0) or
              (app_services.SetFrontProcess(psn_p) < 0) ):
           print "cannot run without OS X gui process"

        print "setting process name"
        app_services.CPSSetProcessName(psn_p, app_title)

    return False

如果您立即调用它,它会更改活动监视器中的进程名称。由于某种原因我不得不在一个小的超时之后调用它来改变菜单栏名称:

import gobject
gobject.timeout_add(100, _osx_set_process_name, "MyTitle")

请注意,如果将它与.app包结合使用,您可以获得一个非常好的python应用程序系统集成。虽然您可以更改图标,Finder显示名称,...,但我尝试的所有方法都将CFBundleName(菜单栏中的名称)保留为“Python”。 (This answer例如只更改长名称(显示在停靠栏图标上)。还有很多其他功能几乎可以使用。)

虽然这个答案给出了预期的结果,但它不是很优雅。我很欣赏为什么我需要超时...我认为Python或pygtk在我第一次导入gtk或运行主循环时会改变进程名称。