9

私は通常、バックグラウンドで目に見えない形で実行される小さなMacアプリケーションに取り組んでいます。ただし、アプリの主な機能は、ユーザーがデスクトップまたはFinderの他の場所でファイルの名前を変更したときに機能します。これが発生した場合、ユーザーがFinderを使用してファイル拡張子を変更したときに表示されるのと同様のダイアログを表示したいと思います。これには、アプリケーションが(Finderではなく)最前面のフォーカスを取得する必要があるため、ユーザーがダイアログで[OK]を押したときに、最前面のアプリケーションとしてFinderを返したいと思います。

現在、AppleのProcess Manager機能を使用SetFrontProcessWithOptions()していますが、次のシナリオで問題が発生します。

  • ユーザーがワークスペースのどこかでFinderウィンドウを開く
  • 次に、ユーザーはデスクトップをクリックして、ウィンドウのフォーカスを解除します。
  • ユーザーがデスクトップ上のファイルの名前を変更します
  • 私のアプリケーションは、それ自体を使用して集中させますSetFrontProcessWithOptions()
  • ユーザーOKがダイアログを押すと、私のアプリはFinderを使用してフォーカスしますSetFrontProcessWithOptions()
  • Finderが再フォーカスすると、以前はFinderが最前面にあったときにフォーカスされていなかったにもかかわらず、ユーザーが以前に開いたウィンドウにフォーカスが移ります。

デスクトップ上のファイルの名前を変更する前に別のスペースでFinderウィンドウを開いている場合、これは非常に煩わしいものになります。このシナリオでは、ダイアログで[OK]を押すと、Finderが自動的にスペースを切り替えてウィンドウに戻ります。

これは、特定のアプリケーションのウィンドウSetFrontProcessWithOptions()にのみフォーカスできる関数の性質によるものです。デスクトップは明らかにウィンドウとしてカウントされないためユーザーが以前にそのウィンドウにフォーカスを設定していなかったにもかかわらず、関数は代わりにフォーカスする別のウィンドウを検索します。

ファインダーに焦点を合わせたり、焦点を外したりする必要がまったくなくても、このようなダイアログベースのことを行う方法について誰かがもっと良いアイデアを持っていれば素晴らしいでしょう。

編集:私はほとんどの部分でこの動作を修正するためのやや醜い方法を見つけましたが、それはスクリプトブリッジを含み、それからのアイテムが名前を変更された場合にデスクトップに再び焦点を合わせません。これを行うための私のコードは次のとおりです。

FinderApplication * app = [SBApplication applicationWithBundleIdentifier:@"com.apple.finder"];
if (!app || ![app isRunning]) {
    SetFrontProcessWithOptions(&processSerial, kSetFrontProcessFrontWindowOnly);
    return;
}
SBElementArray * selArray = app.selection.get;
if ([selArray count] == 0) {
    SetFrontProcessWithOptions(&processSerial, kSetFrontProcessFrontWindowOnly);
    return;
} else {
    FinderWindow * window = [[[selArray objectAtIndex:0] container].get containerWindow].get;
    if ([window isKindOfClass:NSClassFromString(@"FinderFinderWindow")]) {
        SetFrontProcessWithOptions(&processSerial, kSetFrontProcessFrontWindowOnly);
    } else {
        // TODO: this is where I'd insert code to select the item
        // on the desktop...
    }
}
4

3 に答える 3

2

単に呼び出すことを検討しました-[NSApp hide:nil]か?つまり、以前にアクティブだったアプリを再アクティブ化する方法についてシステムに心配させ、アプリがアクティブでなくなったことを確認します。

ちなみに、Finderがアクティブなステータスを受け取ったときにデスクトップではなくウィンドウをアクティブにするというあなたが観察した動作は、Command-Tabを押してから戻ったときに起こる動作と同じです。または、Commandキーを押しながらTabキーを押して、切り替えたアプリケーションを非表示にします。したがって、それは正しい動作と見なされる可能性があります。一方、私のテストでは、Finderがデスクトップにフォーカスされていたが、別のスペースにウィンドウがあるときにフォアグラウンドアプリを非表示にしても、別のスペースに切り替わりません。それはあなたが望むことをします:デスクトップに焦点を合わせた状態でFinderをアクティブにします。

最後に、-[NSRunningApplication activateWithOptions:]の最新の代替品ですSetFrontProcessWithOptions()


本当に必要なのは、同等の機能を実行する方法だけです。

tell application "Finder"
    activate
    select the desktop's window
end tell

Objective-Cから、2つのオプションがあります。まず、Scripting BridgeAPIを使用します。

[self.finder activate];
[(FinderWindow*)self.finder.desktop.containerWindow select];

(FinderでScripting Bridgeを使用するための基本をすでに理解していると思います。そうでない場合は、AppleにScriptingBridgeFinderサンプルがあります。何らかの理由で、従来のドキュメントセクションにあります。)

第二に、あなたは使用することができますNSAppleScript

NSAppleScript* s = [[NSAppleScript alloc] initWithSource:@"tell application \"Finder\"\nactivate\nselect the desktop's window\nend tell"];
NSDictionary* err = nil;
if (![s executeAndReturnError:&err])
    /* handle error */;

ただし、Snow Leopardでの私のテストでは、どちらのアプローチもデスクトップに焦点を合わせたFinderに切り替えるには機能しませんでした。しかし、その後、AppleScriptコードはAppleScriptエディタから実行されませんでした。

于 2013-02-24T19:03:54.527 に答える
1

デスクトップに選択がない場合、Alexのソリューションは機能しません。恐れ入ります。代わりに、このAppleScriptは、ウィンドウまたはデスクトップに焦点が合っているかどうかを判断するための信頼性が高いはずです。

tell application "Finder"
    get insertion location
end tell

フォーカスがある場合は、デスクトップフォルダへのパスが返されます。

それにはまだ2つの問題がありますが:

  1. ユーザーがデスクトップのウィンドウを開いている場合、上記のスクリプトは同じ情報を返します。つまり、デスクトップとフォーカスのあるデスクトップのウィンドウを区別することはできません。それに対する解決策もあればいいのにと思います。
  2. 10.7以降のFinderにはバグがあり(10.8.2にはまだ存在し、Appleには知られています(http://openradar.appspot.com/9406282を参照)、最近開いたウィンドウに関する誤った情報をFinderが報告します。上記のスクリプトは信頼できません。

デスクトップを再選択するために、私は今自分で解決策を見つけました:

tell application "Finder"
    activate
    select the desktop's window
end tell

MacScripter.netにもこれに関するスレッドがあり、オプションについてもう少し説明しています。http://macscripter.net/viewtopic.php?pid= 160529

于 2013-02-24T09:47:58.640 に答える
0

実際のAppleScriptを呼び出してみませんか。

NSDictionary *errorInfoDictionary = nil;
NSAppleScript *script = [[NSAppleScript alloc] initWithContentsOfURL:[NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:@"FocusOnFinder" ofType:@"scpt"]] error:&errorInfoDictionary];

// OR

// NSAppleScript *script = [[NSAppleScript alloc] initWithSource:@"tell application \"Finder\"\n activate\n select the desktop's window\n end tell"];

if (!errorInfoDictionary)
{
    if (![script executeAndReturnError:&errorInfoDictionary])
    {
        NSLog(@"%@", [errorInfoDictionary description]);
    }
}
else
    NSLog(@"%@", [errorInfoDictionary description]);

FocusOnFinder.scptのコンテンツ

tell application "Finder"
   activate
   select the desktop's window
end tell

Finderが実行されていないか、最小化されている場合、効果はありません。

于 2013-02-25T01:11:55.420 に答える