以编程方式打开Mac帮助菜单

时间:2010-11-17 02:24:00

标签: cocoa macos mono gtk macos-carbon

我正在将GTK#应用程序集成到Mac OS X.Mac OS X上的GTK是一些Cocoa和Carbon基础的包装。我们有一些特定于平台的东西,直接使用Carbon全局菜单API(它比Cocoa更低级和更灵活,我们不需要64位)。

在Carbon将它们作为命令发送之前,似乎GTK吞噬了所有键盘事件。这是有道理的,因为没有Carbon命令到GTK世界的映射。一般来说,这不是问题,因为我们有一个全局键事件处理程序,并通过我们自己的命令系统调度所有内容。但是,这似乎阻止了Cmd-?从打开帮助搜索菜单,我找不到以编程方式执行此操作的方法。

菜单管理器的MenuSelect功能很有前景,但我还没有找到一种自动确定坐标的方法,出于某种原因,它只有在我按两次组合时才有效...

或者,一种派遣Cmd-的方法?对Carbon的命令处理进行击键或直接合成命令事件会很好,但我在这方面没有运气。

Carbon的ProcessHICommand在没有命令ID的情况下没有任何用处,我无法弄清楚它是什么(如果有的话)

关于Cocoa,我可以抓住NSWindow并调用InterpretKeyEvents,但是我没有任何运气成功合成NSEvent - 它只是发出哔哔声。我正在使用的事件是

var evt = NSEvent.KeyEvent (NSEventType.KeyDown, System.Drawing.PointF.Empty,
    NSEventModifierMask.CommandKeyMask | NSEventModifierMask.ShiftKeyMask,
    0, win.WindowNumber, NSGraphicsContext.CurrentContext, "?", "?",
    false, (ushort) keycode);

密钥代码是从GTK密钥映射确定为44.我使用普通的MonoMac(Cocoa)应用程序确认密钥代码是正确的,但是InterpretKeyEvents也不适用于该应用程序中的事件。而且我找不到与该命令相关的任何选择器。

2 个答案:

答案 0 :(得分:1)

你可以通过从C / Objective-C调用AppleScript (GUI) script 来实现这一点,这实际上就像用户一样指向和点击用户,以打开帮助菜单程序。 / p>

答案 1 :(得分:0)

您可以使用辅助功能API伪造菜单项上的按键。

NSString *helpMenuTitle = [[[[NSApplication sharedApplication] mainMenu] itemWithTag:HELP_MENU_TAG] title];
AXUIElementRef appElement = AXUIElementCreateApplication(getpid());
AXUIElementRef menuBar;
AXError error = AXUIElementCopyAttributeValue(appElement,
                                              kAXMenuBarAttribute,
                                              (CFTypeRef *)&menuBar);
if (error) {
    return;
}

CFIndex count = -1;
error = AXUIElementGetAttributeValueCount(menuBar, kAXChildrenAttribute, &count);
if (error) {
    CFRelease(menuBar);
    return;
}

NSArray *children = nil;
error = AXUIElementCopyAttributeValues(menuBar, kAXChildrenAttribute, 0, count, (CFArrayRef *)&children);
if (error) {
    CFRelease(menuBar);
    return;
}

for (id child in children) {
    AXUIElementRef element = (AXUIElementRef)child;
    id title;
    AXError error = AXUIElementCopyAttributeValue(element,
                                                  kAXTitleAttribute,
                                                  (CFTypeRef *)&title);
    if ([title isEqualToString:helpMenuTitle]) {
        AXUIElementPerformAction(element, kAXPressAction);
        CFRelease(title);
        break;
    }
    CFRelease(title);
}
CFRelease(menuBar);
[children release];