При вызове TransformProcessType() меню приложения не отображается

#macos #cocoa #macos-carbon

#macos #cocoa #macos-carbon

Вопрос:

Если вы вызываете TransformProcessType() следующим образом :

 ProcessSerialNumber psn = { 0, kCurrentProcess }; 
(void) TransformProcessType(amp;psn, kProcessTransformToForegroundApplication);
  

Тогда меню приложения cocoa не отображается, если вы не вызовете это достаточно рано в своем приложении (например, в applicationWillFinishLaunching ).

Комментарии:

1. Я получил ответ, но поскольку моя репутация слишком низкая, я могу ответить на него только в течение 8 часов. Я попробую добавить комментарий уже.

2. Я попросил Apple о помощи, и они мне очень хорошо помогли. Цитата : > Причина, по которой строка меню не отображается при вызове TransformProcessType, заключается в том, что ваше приложение уже является активным приложением (то есть [[NSRunningApplication currentApplication] isActive] возвращает ДА), а строка меню для приложения отображается при активации приложения

3. Это их обходной путь: — (void)transformStep1 { for (NSRunningApplication * app in [NSRunningApplication Запуск приложений с привязкой идентификатора:@»com.apple.finder»]) { [app activateWithOptions:NSApplication activateignoringotherapps]; break; } [self performSelector:@selector (transformStep2) withObject:nil После задержки:0.1]; }

4. — (void)transformStep2 { ProcessSerialNumber psn = { 0, kCurrentProcess }; (void) TransformProcessType(amp;psn, kProcessTransformToForegroundApplication); [self performSelector:@selector (transformStep3) С объектом:nil После задержки:0.1]; } — (void)transformStep3 { [[NSRunningApplication currentApplication] activateWithOptions:NSApplicationActivateIgnoringOtherApps]; }

Ответ №1:

Я попросил Apple о помощи, и они мне очень хорошо помогли. Цитата :

Причина, по которой строка меню не отображается при вызове TransformProcessType, заключается в том, что ваше приложение уже является активным приложением (то есть [[NSRunningApplication currentApplication] isActive] возвращает ДА), а строка меню для приложения отображается при активации приложения

Это их обходной путь :

 - (void)transformStep1 {
    for (NSRunningApplication * app in [NSRunningApplication runningApplicationsWithBundleIdentifier:@"com.apple.finder"]) {
        [app activateWithOptions:NSApplicationActivateIgnoringOtherApps];
        break;
    }
    [self performSelector:@selector(transformStep2) withObject:nil afterDelay:0.1];
}

- (void)transformStep2
{
    ProcessSerialNumber psn = { 0, kCurrentProcess }; 
    (void) TransformProcessType(amp;psn, kProcessTransformToForegroundApplication);

    [self performSelector:@selector(transformStep3) withObject:nil afterDelay:0.1];
}

- (void)transformStep3
{
    [[NSRunningApplication currentApplication] activateWithOptions:NSApplicationActivateIgnoringOtherApps];
}
  

Комментарии:

1. Я использовал @»com.apple.dock». Это кажется лучше, чем активировать Finder, заставляя его переходить на передний план.

Ответ №2:

Вот как я заставил его работать.

 BOOL MakeAppForeground()
{
    BOOL bSuccess = TranformAppToState(kProcessTransformToForegroundApplication);

    if(bSuccess)
    {
         bSuccess = (SetSystemUIMode(kUIModeNormal, 0) == 0);
        [NSApp activateIgnoringOtherApps:YES];
    }

    return bSuccess;
}

BOOL MakeAppBackground()
{
    return TranformAppToState(kProcessTransformToBackgroundApplication);
}

BOOL TranformAppToState(ProcessApplicationTransformState newState)
{
    ProcessSerialNumber psn = { 0, kCurrentProcess };
    OSStatus transformStatus = TransformProcessType(amp;psn, newState);

    if((transformStatus != 0))
    {
        NSError *error = [NSError errorWithDomain:NSOSStatusErrorDomain code:transformStatus userInfo:nil];
        NSLog(@"TranformAppToState: Unable to transform App state. Error - %@",error);
    }

    return (transformStatus == 0);
}
  

Ответ №3:

Вот мое решение, которое запускается при щелчке флажка в окне настроек. Единственным побочным эффектом является короткое мигание окон приложения:

 - (void) hideDockIcon:(bool) hide
{
    ProcessSerialNumber psn = { 0, kCurrentProcess };
    ProcessApplicationTransformState state = hide ? kProcessTransformToUIElementApplication : kProcessTransformToForegroundApplication;
    OSStatus err = TransformProcessType(amp;psn, state);
    
    if (err) {
        NSError *error = [NSError errorWithDomain:NSOSStatusErrorDomain code:err userInfo:nil];
        NSLog(@"TransformProcessType failed: %@", error);
    }
}

- (void) toggleDockIcon
{
    [NSApp hide:self];
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        [self hideDockIcon:self.preferences.hideDockIcon];
        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
            [NSApp activateIgnoringOtherApps:YES];
        });
    });
}