如何在 Firebreath NPAPI 插件中将 NSMenu 连接到 NSStatusItem,以便在单击状态栏项时出现菜单?
Posted
技术标签:
【中文标题】如何在 Firebreath NPAPI 插件中将 NSMenu 连接到 NSStatusItem,以便在单击状态栏项时出现菜单?【英文标题】:How to connect NSMenu to NSStatusItem in a Firebreath NPAPI plugin so the menu appears when clicking the StatusBar Item? 【发布时间】:2012-09-18 23:32:00 【问题描述】:作为 NPAPI Chrome 浏览器插件的一部分,我正在努力在 Mac OS 状态栏中显示一个带有菜单的状态图标。
Firebreath 使用 C++,而大多数用于 Mac OS 开发的库都使用 Objective C。感谢this question 上的回复,我克服了这个障碍。我还必须调整我的 CMake 设置才能将 XIB 文件编译为 NIB。
经过反复试验,我能够让状态栏选项出现在状态栏中,但是当我单击它时,菜单不会展开。我不确定我需要做什么才能显示菜单。它适用于 Cocoa 应用程序,但不适用于 Firebreath 应用程序。
我也导入了 Foundation 和 Cocoa 库。
我怀疑问题出在我的 MainMenu.xib 文件或 AppDelegate.m 中。
AppDelegate.m:
#import "AppDelegate.h"
@implementation AppDelegate
-(void)awakeFromNib
NSLog(@"calling awakeFromNib...");
NSStatusBar *bar = [NSStatusBar systemStatusBar];
statusItem = [[bar statusItemWithLength:NSVariableStatusItemLength ] retain];
// statusItem = [[NSStatusBar systemStatusBar] statusItemWithLength:NSVariableStatusItemLength];
//[statusItem retain];
NSMenuItem *menuItem;
menuItem = [[[NSMenuItem alloc] initWithTitle:@"Test" action:NULL keyEquivalent:@""] retain];
// [menuItem setView: myView];
statusMenu = [statusMenu initWithTitle:@"WTF"];
[statusMenu addItem:menuItem];
[menuItem retain];
[statusItem setTitle: NSLocalizedString(@"StatusMenu",@"")];
[statusItem setHighlightMode:YES];
[statusItem setMenu:statusMenu];
[statusItem setEnabled:YES];
[statusMenu retain];
// this was needed to get the icon to display
[statusItem retain];
//[window retain];
- (IBAction)settings:(id)sender
NSLog(@"Invoking the settings from the menu...");
//@synthesize window;
@end
此文件是从示例应用程序中获取的,并且正在从 Objective C++ 包装类手动调用 awakeFromNib。根据日志,以及我在状态栏中看到“StatusMenu”这一事实,我知道正在调用此函数。
我还附上了 MainMenu.xib 的屏幕截图:
MainMenu.xib:
我尝试的最后一件事是将 NSStatusItem 添加为 IBOutlet 以查看是否可以将其连接到 xib 文件中的某些内容,但我不确定这是正确的方向。
单击“状态菜单”选项时需要做什么才能显示菜单?
【问题讨论】:
当您说“awakeFromNib
正在从 Objective C++ 手动调用”时,您涉及的是NSBundle
还是NSNib
?如果没有,我怀疑你需要这样做。也许The Nib Object Life Cycle 或Loading Nib Files Programmatically 会有所帮助。
嗨@JoshCaswell,在示例应用程序中,我认为它被处理加载应用程序的其他进程调用,但 Firebreath 框架使用 C++ 和其他一些机制来启动应用程序。我正在从 Objective C++ 包装器中调用 awakeFromNib
。我会看看 NSBundle 和 NSLib 以及那个链接。谢谢你的提示;当我了解更多信息时,我会更新我的问题。
请记住,可能没有 NSApplication 并且您可能无法创建一个;这些是生活在别人的过程中的缺点。
@taxilian - Google 有一个Google Talk Chrome Extension,它使用 NPAPI 在 Windows 和 Mac OS 中安装状态栏图标。右键单击显示选项,左键单击加载 Chrome 面板。我已经有了状态栏图标,所以我的想法是尝试注册一个我可以绑定的点击事件。我想我不需要与操作系统完全集成,事实上,抛出一个扩展可以绑定的事件会更跨平台兼容。所以如果 NSApplication 不可用,我会试试这个。
好的,事实证明我没有在 NSMenu 对象上调用 alloc,并且 Objective C 不会像 Java 那样抛出 NPE 或像 javascript 在这种情况下会发生的未定义错误。添加 alloc 后,我可以以编程方式将项目添加到菜单并在单击时触发日志事件。简而言之,我完全绕过了 xib/nib,如果这意味着进入下一个挑战,这对我来说没问题。
【参考方案1】:
这里的问题是 Firebreath 项目和 NPAPI 插件架构不支持自动引用计数 (ARC),通常在 XCode 项目中默认开启。
此外,由于将 Objective C 与 C++ 混合的疯狂,XCode 并不能像纯粹用 Objective C 编写代码那样容易地报告错误。因此,错误消息被抑制了。为了避免错误,使用 NPAPI 插件架构的开发人员必须通过在 NSMenu 对象上调用 alloc 来显式管理内存。
只要对这些对象调用 alloc,它们就会被正确保留。这解决了问题。
【讨论】:
以上是关于如何在 Firebreath NPAPI 插件中将 NSMenu 连接到 NSStatusItem,以便在单击状态栏项时出现菜单?的主要内容,如果未能解决你的问题,请参考以下文章
结合FireBreath在Chrome/FireFox的多进程模式下崩溃一例
仅使用 Firefox Addon SDK 在后台嵌入 NPAPI 插件