タイトル小池邦人のプログラミング日記》2001/5/2<CarbonLibの「謎」よもやま話>カテゴリーCarbon/CF, 小池邦人のプログラミング日記
作成日2001/5/2 10:43:42作成者新居雅行
今回は、Mac OS X環境でのCarbonLibに関する「謎」についてのお話しです。発表されてから随分時間が経ったにもかかわらず、未だ実現の方法がよく分からない機能や、バグなのか仕様なのか判断に困ってしまう現象を取り上げてみました。

つい最近、Apple SDKサイトに「Universal Interfaces 3.4」と「CarbonLib 1.3.1 SDK」が登録されました。これにより、ADCメンバーでない方でも最新のCarbon開発環境が利用できるようになりました。SDKには最新の「CarbonLib」も含まれていますので、何らかの問題に遭遇されている方は、機能拡張フォルダの旧バージョンと差し替えて試してみると良いでしょう。このバージョンにより、日本語環境で表面化していた文字入力やプリントアウトに関する問題の多くが解決されていればと思います。付属ドキュメントの「CarbonLib 1.3.1 TN」を読むと、v1.2.5からの改良点がいくつか記載されています。「Mac OS 9.1以降では、FSOpenResourceFile()によりデータフォークに保存されているリソースのオープンが可能」などといった項目もあります(今まではできなかったのか!)。それ以外にも、今まで存在していた「Mac OS 9とMac OS Xでの挙動の差異」を吸収するための処置がなされているようです。バグフィックス以外の項目が多いところを見ると、CarbonLib 1.3.1を含んだMac OS 9の新バージョンの登場も近いかもしれません。

CarbonLibに含まれているほとんどのAPIは、Mac OS 9とMac OS Xで共通に利用できます。これにより、デベロッパーはどちらの環境でも起動できるアプリケーションを開発することができるわけです。しかし、中にはMac OS Xのみでしか利用できない機能や仕組みもあります。前回紹介した「ウィンドウのLive Resizing」もそのひとつです。こうした機能を利用する場合に限り、アプリケーションが起動されている環境をチェックして処理を切り分けることが必要となります。例えば、最近の「Techincal Note 2017」で「LaunchServices」という、Mac OS Xでのみで利用可能なサービスが紹介されていました。これは、アプリケーションからドキュメントを遠隔オープンしたり、アプリケーションがオープンできるドキュメントの種類を調べたりするためのAPI群です。

Mac OS 9でアプリからドキュメントを遠隔オープンする時には、Finderに対してドキュメントのオープンを指示するApple Eventを送ってやるのが一般的でした。これを実現するのには、オープンしたいドキュメントのFSSpec(ファイル保存場所情報)が必要となります。FSSpecを使わずにクリエータやファイルタイプ情報のみで起動させる方法もあるのですが、こちらにはかなり複雑な処理が必要となりました。こうした問題は、このLaunchServicesの登場により解決されそうです。ちなみに、私がMac OS Xで旧方法を試したところ、Mac OS X Finderへドキュメント遠隔オープンのApple Eventを送っても何の反応もありませんでした。不思議なことに、Classic環境(Classic Finderは起動してないのに...)から送ったApple Eventは有効となります。「バグかな?」と思っていましたが、代用品としてLaunchServicesが紹介さているのを見ると、Mac OS Xの場合に限り、遠隔オープンの処理をLaunchServicesを使って書き直した方が賢明なのかもしれません。

バグなのか仕様なのか判断できない現象は、自作アプリをCarbon Event Modelへと移行する時にも遭遇しました。例えば、Mac OS 9でCarbon Event Modelを使うと、「kEventClassControl」(コントロールクラス)に属するCarbon Eventがほとんど送られて来ないのです。唯一送られてくるのは「kEventControlHitTest」だけです。この問題は、Carbon Eventの対象オブジェクトをコントロール自身にしても、それを配置したているウィンドウにしても解決しませんでした。コントロールのアクティブやインアクティブといった単純なCarbon Eventさえも送られて来ないのです。ところが、Mac OS X環境では、こうしたCarbon Eventも問題なく送られて来ます。結局のところ、このようなMac OS 9での問題点を考慮すると、旧Event ModelとCarbon Event Modelが混在しているような中途半端な移行になってしまいます。Appleは、Carbon Event ModelはMac OS Xだけで使えと言っているような気がしてなりません...。

さて、Mac OS XにはApplicationメニューが用意されており、作業終了(Quit)アイテムはそこに配置されるようになりました。Applicationメニューには「環境設定...」もあり、アプリケーションの環境設定ダイアログは、これを選択することで表示させるように推奨されています。例えばMac OS X版のInternet Explorer(Carbonアプリ)では、この「環境設定...」がちゃんとサポートされています。こうしたメニューアイテムはシステム側で自動的に追加されるのですが、これの使い方が「CarbonPortingGuide」や「AquaGuidelines」などのドキュメントに載っていないのです。とりあえず、Carbn Eventのハイコマンド用(kHICommandPreferences)のHandlerルーチンで処理するのだろうと推測して試してみましたが、今度は「環境設定...」アイテムのハイライト(使用不可)を解除する方法が見つからずに困ってしまいました。

「アバウト表示」があるため、Applicationメニュー自身はアプリ側で定義していますので、GetMenuRef()でMenuHandleを得て指定アイテムをEnableMenuItem()すれば、問題なくハイライトを解除できると考えていました。ところが、この処理ではメニューアイテムの状態を変えることはでません。どうもMac OS Xが追加しているアイテムは、アプリケーション側から操作ができないようにプロテクトされているようなのです。そこで色々と調べて行くと、AppleEvents.hのkCoreEventClassに、kAEShowPreferencesという「Moc OS X Only」のApple Event IDが定義されているのを発見しました。つまり、CoreEventClassのkAEShowPreferencesに対応するApple Event Handlerを用意すれば、そこで「環境設定...」アイテムが処理できるわけです。ならば、そのHandlerルーチンをAEInstallEventHandler()でインストールした時点で、このアイテムのハイライトが解除されるのだろうと推測したのですが、こちらも大ハズレでした(笑)。

アプリ用の初期設定ファイルを作成したり、そこにデータを書き込んだりするのには「Core Foundation」のAPIを利用することができます。そこでCFPreferences.hについても詳しく調べてみましたが、Applicationメニューに関係するAPIは無さそうです。ならば、リソース側にメニューアイテムのハイライトをコントロールするための情報があるのではないかと思い、Internet Explorerのリソースを色々と調べてみましが、それらしい物は見つけられませんでした。ひょっとしてPlistテキスト(アプリケーション情報がXMLで記述してある)の方かもしれないと、こちらの内容もPropatyListEditorで表示してみましたが、やはりそれらしき記述は見あたりません。とは言っても、とにかくInternet Explorerでは「環境設定...」の処理が実現されているわけですから、何らかの秘密があるのは間違いないはずです。

CoCoaアプリでは可能なのに、Carbonアプリは実現方法が分からない機能もあります。例えば、ファイル保存用ダイアログをSheet Window(親ウィンドウのタイトルバーから降りてくるウィンドウ)として表示する方法です。Apple Carbon Documentサイトで「Navigation Service」の最新リファレンスを調べると、CarbonLib v1.1よりNavigation Service 3.0が導入されたと記されています。Universal Interfaces 3.4のNavigation.hを見ると、確かに今まで利用してきたNavGetFile()やNavPutFile()に加えて、NavCreateGetFileDialog()やNavCreatePutFileDialog()といった新しいAPIが定義されています。新たに用意されたNavDialogCreationOptions構造体には、parentWindowというメンバーも定義されており、これにSheet Widowの親ウィンドウを設定しろとの注意書があります。「これだ!」と思い、さっそく新しいAPIに書き換えてMac OS Xで試してみましたが、やはりファイル保存用ダイアログはSheet Windowとしてオープンされませんでした。それどころか正常なFSSpecも得られなくなり、ファイルが正しく保存できなくなってしまいました。こちらに関しては未だに原因不明で解決できていません。

Sheet Window自体は、Window MangerのShowSheetWindow()を用いればオープンすることが可能です。まあ、ファイル保存用ダイアログのSheet Window化は、Mac OS X版のInternet Explorerでも実現されていませんので、残念ながら現状のCarbonLibでは未実装なのかもしれません。しかし、ユーザにとってCarbonアプリとCocoaアプリで用いられるユーザインターフェースに違いがあるのは混乱の元となります(ユーザがどちらのアプリなのか頓着する必要は無いので)。例えば、CocoaアプリのApplicationメニューに利用されている「サービス」アイテムなども、Carbonアプリからどのように実現したらよいのか不明な機能のひとつです。CarbonとCocoaどちらのフレームワークでも、ユーザインターフェースに関係するAPIだけは共通な物を用意するように、Appleに強く要望したいところです。

ひょっとすると、今回取り上げた「謎」には既に解決策があり、私がそれを知らないだけかもしれません。もしそうした解決策をご存じの方がいらっしゃいましたら、ぜひご連絡ください。同じように苦労している多くの仲間に速やかに紹介したいと思います。
[小池邦人/オッティモ]
関連リンクオッティモ