Программно открыть меню справки Mac

Я интегрирую приложение GTK # в Mac OS X. GTK в Mac OS X - это оболочка над некоторыми основами Cocoa и Carbon. У нас есть некоторые специфические для платформы вещи, напрямую использующие API глобального меню Carbon (он более низкоуровневый и гибкий, чем Cocoa, и нам не обязательно быть 64-битным).

Кажется, что GTK поглощает все события клавиатуры до того, как Carbon отправляет их в виде команд. Это имеет смысл, потому что нет отображения команд Carbon в мире GTK. В общем, это не проблема, потому что у нас есть глобальный обработчик ключевых событий, и мы отправляем все через нашу собственную систему команд. Однако, похоже, это мешает Cmd-? от открытия меню поиска по справке, и я не могу найти способ сделать это программно.

Функция MenuSelect в Менеджере меню является многообещающей, но я не придумал, как автоматически определять координату, и по какой-то причине она работает только тогда, когда я нажимаю комбинацию дважды ...

Как вариант, способ отправки Cmd-? нажатие клавиши для обработки команд Carbon или прямое синтезирование командного события было бы хорошо, но мне не повезло в этой области.

Carbon ProcessHICommand бесполезен без идентификатора команды, и я не могу понять, что это такое (если он есть)

Что касается Какао, я могу получить 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 (Какао), но InterpretKeyEvents также не работал с событием в этом приложении. И я не могу найти селектора, связанного с командой.


person Mikayla Hutchinson    schedule 17.11.2010    source источник
comment
Пользователи просили Cmd-Shift-? привязка клавиш, чтобы открыть меню поиска по справке. Каким-то образом цикл событий GTK препятствует работе встроенной обработки.   -  person Mikayla Hutchinson    schedule 19.11.2010
comment
С событием какао пробовали ли вы использовать / вместо?.   -  person Abhi Beckert    schedule 09.05.2011
comment
Кстати, ваше утверждение, что углерод более низкоуровневый и гибкий, чем какао, неверно. Carbon - это полностью отдельный API, который был разработан для совместимости с Mac OS 8/9. Он устарел, в плохом состоянии и никоим образом не находится под какао. Какао на самом деле намного старше углерода, хотя на первый взгляд выглядит более современным. Вам действительно стоит взаимодействовать с Cocoa вместо Carbon.   -  person Abhi Beckert    schedule 09.05.2011
comment
Так почему же я вижу вызовы HIToolbox в стеке вызовов меню Какао?   -  person Mikayla Hutchinson    schedule 09.05.2011
comment
Интересный. Я предполагаю, что они, должно быть, решили, что какой-то стек меню Carbon лучше, чем тот, что есть в Какао, поэтому они его использовали. Тем не менее, я бы не стал использовать углеродные API в приложении, над которым вы собираетесь работать долгое время. Apple начала серьезно отходить от Carbon в последнем выпуске Mac OS X, и любой, кто пишет сегодня код Carbon, должен ожидать, что в ближайшем будущем его нужно будет переписать на Cocoa.   -  person Abhi Beckert    schedule 11.05.2011
comment
Да, на самом деле это не был общедоступный Carbon API, но я думаю, что разумно сказать, что система меню Cocoa построена на основе примитивов из системы меню HIToolbox от Carbon. Кроме того, Cocoa определенно построен на основе API-интерфейсов C на уровне рычагов (Core Foundation, среда выполнения Obj-C и т. Д.). Однако я согласен с тем, что использование устаревших API-интерфейсов Carbon, таких как HIToolbox, - плохая идея.   -  person Mikayla Hutchinson    schedule 11.05.2011
comment
Углерод также построен на основе Core Foundation. Core Foundation действительно использует C, но только потому, что это необходимо для дополнительной производительности, и большая его часть совместима с кодом Obj-C. Например, вы можете преобразовать CFDictionaryRef в NSDictionary * или id, и он будет вести себя точно так же, как объект NSDictionary (есть некоторые тонкие различия, которые делают CFDictionary быстрее, чем NSDictionary. Но они незначительны).   -  person Abhi Beckert    schedule 12.05.2011


Ответы (2)


Вы можете использовать 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];
person George    schedule 24.12.2013
comment
На самом деле мы нашли другое решение, которое включало исправление инструментария GTK, чтобы он не перехватывал это нажатие клавиш, а позволял Cocoa обрабатывать его вместо этого. Однако я принимаю этот ответ, поскольку это хорошее решение для всех, кто хочет полагаться на Accessibility Framework. - person Mikayla Hutchinson; 25.12.2013
comment
Осторожно. Это не сработает на любом языке, кроме английского, из-за жестко заданного заголовка @Help. Вам нужно присвоить значение тега меню справки в главном меню вашего приложения, а затем взять фактический заголовок меню и использовать его вместо этого. - person dgatwood; 28.07.2014

Это можно сделать, вызвав из C / Objective-C сценарий AppleScript (GUI), который, по сути, будет указывать и щелкать пользователя так же, как пользователь, чтобы программно открывать меню справки.

person MrDaniel    schedule 06.02.2012