在创建主窗口后添加 NSTouchBar 支持

Posted

技术标签:

【中文标题】在创建主窗口后添加 NSTouchBar 支持【英文标题】:Adding NSTouchBar support after main window has been created 【发布时间】:2016-12-29 16:04:02 【问题描述】:

我正在尝试添加支持,以通过插件将NSTouchBar 按钮暴露给我无法以其他方式修改的应用程序。该插件是一个共享库,在创建主窗口后在运行时加载。我创建了一个AppDelegate,如下所示:

@interface AppDelegate : NSResponder <NSTouchBarDelegate>
@end

使用实现makeTouchBartouchBar 函数的@implmentation

- (NSTouchBar *) makeTouchBar
- (nullable NSTouchBarItem *) touchBar:(NSTouchBar *)touchBar
                       makeItemForIdentifier: (NSTouchBarItemIdentifier)identifier

我终于尝试将它注入到应用程序中,我在onload 函数中有以下内容,该函数在加载到应用程序时在动态库中调用。

NSWindow *w = [NSApp mainWindow];

AppDelegate *a = [[AppDelegate alloc] init];
a.nextResponder = w.nextResponder;
w.nextResponder = a;

// Re-setting FirstResponder will trigger AppDelegate::makeTouchBar
// that was attached above.
NSResponder *n = w.firstResponder;
[w makeFirstResponder: nil];
[w makeFirstResponder: n];

但是...AppDelegate::touchBar 永远不会被调用,因此我的测试按钮永远不会填充触摸栏。

如果我在 Xcode 中创建一个新项目,并使用完全相同的 AppDelegate 实现(复制粘贴相同的 @interface@implementation),我会得到既显示又响应按下事件的功能按钮,所以似乎是注射部分坏了。 (我猜在 Xcode 中,一切都是通过 MainMenu.xib 连接起来的)

更新: 主要问题是应用程序的编译方式阻止了 TouchBar 工作。可能是基于旧版 Mac OS 构建的。

【问题讨论】:

【参考方案1】:

如果这个对象真的应该充当应用程序委托(顾名思义)——而不是将它插入到主窗口的响应程序链中,最好将它实际设置为 NSApp 的delegate。设置的委托的 touchBar 也用于构建触摸栏(请参阅NSTouchBar Discovery and the Responder Chain)。

如果这对您的插件不起作用(可能应用程序已经有它需要的特定应用程序委托),您可以将其插入 NSApp 的响应者链而不是 mainWindow 的。

这两者还具有使触摸栏在应用程序级别而不是窗口关联的好处。因此,如果主/关键窗口发生变化,将始终使用提供的触摸栏。

【讨论】:

设置 NSApp.delegate 时没有任何问题,应用程序和以前一样工作。我的 AppDelegate 的 touchBar 仍然没有被调用。我尝试设置 NSApp.delegate=myappdelegate, myappdelegate.touchBar=nil, NSApp.touchBar=nil, myappdelegate.nextResponder=NSApp.nextResponder, NSApp.nextResponder=myappdelegate。有问题的应用程序是 Emacs,我正在尝试通过在评估时加载的本机 elisp 模块添加触摸栏(模块加载“/path/to/module”)。 myappdelegate.touchBar 仍然由 makeTouchBar 创建。我尝试将 myappdelegate.touchBar 分配给 NSApp.touchBar,但仍然没有 touchbar。 可能是我试图将触摸条注入的应用程序(在这种情况下为 Emacs)编译时使用了一些禁用触摸条支持的选项?我正在使用来自emacsformacosx.com 的最新版本 啊,是的。看起来该应用程序由于某种原因无法显示触摸栏内容...您可以通过在其中显示标准打开面板来看到这一点:面板在其他触摸栏中具有“取消”和“打开”按钮应用程序,但在 emacs 中缺少它们 原来 emacs 的编译方式无法启用 TouchBar。在我的笔记本电脑上构建它时,它起作用了。我正在设置 mainWindow.delegate = mydelegate 和 mainWindow.touchBar=nil 来触发触摸栏的更新。

以上是关于在创建主窗口后添加 NSTouchBar 支持的主要内容,如果未能解决你的问题,请参考以下文章

如何从 NSWindow 对象创建 NSTouchBar?

MFC 主窗口如何在创建的子窗口前

如何为主窗口创建的窗口小部件创建QCloseEvent

如何为主窗口创建的小部件创建 QCloseEvent

MFC非模态添加进程控件方法一(线程方法)

QMainWindow和QWidget