タイトル小池邦人のプログラミング日記》2001/6/25<Navigation Service 3.0を使う その3>カテゴリーユーザインタフェース, 小池邦人のプログラミング日記
作成日2001/6/26 15:45:25作成者新居雅行
今回から、WWDC関連の話題により中断していたNavigation Service 3.0の話しを再開します。まずは、Navigation Service 3.0を利用したファイルオープンダイアログの解説から始めます。

前回では、Metrowerks CodeWarrior 7.0 Early Access(開発リリース)を使い、Mach-OベースのCarbonアプリケーションを作成しました。読者の方より、それについていくつかの質問をいただきましたので、まずはそれにお答えしておきます。最初は、アプリの容量ですが、CFMベースのCarbonアプリと比較してみると、コード自体が30Kバイトぐらい増量していました。昔々のProjectBuilderでの実験のように、QuickTime Frameworkをリンクすると、それが全部コードに追加され数Mバイトも容量が増えてしまうといった現象は起こりませんでした(笑)。次に、利用するリソースですが、これはリソースフォークに保存されていても問題ありません。最後に、アプリの起動スピードですが、CFMベースのCarbonアプリが起動するまでにDockの中で5回ジャンプするのと比べて、Mach-OベースのCarbonアプリは2回のジャンプで起動します。

この結果は、Mac OS Xのランタイム環境の仕組みからして納得できるのですが、どちらのアプリも、もう少し高速に起動するように最適化してもらいたいものです。Mac OS XのClassic環境からのCarbonアプリの起動がやたら高速なだけに、Naitive環境でのアプリの起動の遅さが目立ちます。CarbonアプリをMach-Oベースとしてコンパイル&リンクしてしまうと、当然Mac OS 8/9環境では起動できなくなります。しかし、Core Graphicsや今回説明するNavigation Service 3.0を含め、Mac OS Xでしか利用できないCarbon APIも沢山出てきて、今後はMac OS 8/9環境を対象としないMach-OベースのCarbonアプリが増えてくるでしょう。特に、Metrowerks CodeWarrior 7.0の製品版が出荷されれば、その傾向は加速されると思います。以前にも書いたかもしれませんが、CarbonはMac OS 8/9/Xで共通に起動できるアプリを作成するためのFramewrokではなく、Cocoaと並ぶMac OS X Native Frameworkのひとつだと考え直した方が良さそうです。

では、さっそくファイルオープンのための各ルーチンを見ていきます。まずは、アプリケーション起動時に一度だけ呼び出すsetUpNavi()ルーチンです。

 

これによりNavigation Serviceで利用するすべてのFilterやEventコールバックルーチンのエントリーポイントを一度にインストールしています。chkSysOSX()がtrue(1)の場合がMac OS X用、false(ゼロ)の場合にはMac OS 8/9用がインストールされます。このうち、navLoadEventProc()が今回説明するファイルオープンダイアログ用となります。navSaveEventProc()とnavExpoEventProcX()は、次回に説明するファイル保存ダイアログで使い、navAlertEventProc()は、以前説明した保存確認や復帰確認のアラートのためのものです。

ファイルメニューから「開く...」が選択されると、最初にloadImageWindow()ルーチンが呼ばれます。

 

やはりchkSysOSX()でチェックして、アプリケーションの起動環境がMac OS Xならば、navMyGetFile()の代わりにnavMyGetFileX()ルーチンが実行されます。

 

navMyGetFileX()の先頭のにあるnavMakeInfo()やcollectMyWindow()は、以前にnavMyGetFile()のために用意したルーチンとまったく同じ働きをしますので、そちらの解説を参照してください。続いてNavGetDefaultDialogCreationOptions()でディフォルトNavDialogCreationOptions構造体を得て、必要なパラメータを各メンバーに代入します。クライアント名(opt.clientName)はパスカル文字列ではなくCFStringCreateWithPascalString()でUnicode文字列を指すCFStringRefに変換してから代入します。構造体のmodalityメンバーには「kWindowModalityNone」を代入します。これにより、このダイアログはModeless Dialogとして表示されることになります。NavCreateGetFileDialog()でダイアログを作成し、返されたNavDialogRef(dpr)をNavDialogRun()に渡すと、ファイルオープンダイアログが表示されます。Mac OS 9でNavigation Serviceを利用した場合と異なるのは、NavDialogRun()を実行後、この処理から抜け出てしまうことです。後は、Carbon Event Managerの制御下にあるコールバックルーチンに、ダイアログのボタンが押された時の処理を実装します。

ファイルオープンダイアログのFilterコールバックルーチンであるnavFilterProc()は、旧Navigation Serviceで利用した物とまったく同じですが、EventコールバックルーチンのnavLoadEventProc()は新規に作成されています。

 

ファイルオープンダイアログのNavDialogRefはparm->contextに入っており簡単に参照することができます。引数で得たNavEventCallbackMessage(sel)が「kNavCBUserAction」と一致すれば、ユーザがダイアログ上のコントロール(ボタンなど)をクリックしたことになります。この時にparm->userActionも調べ、それが「kNavUserActionOpen」と一致していれば、ファイルオープンダイアログの「開く」ボタンが押された事になりますので、NavDialogGetReply()でNavReplyRecord構造体(ファイル保存場所情報)を得て、それをreadImageWindowX()ルーチンに渡し画像ファイルをオープンします。

 

また、ダイアログが閉じられた場合には、NavEventCallbackMessageにkNavCBTerminateが入りますので、NavDialogDispose()を呼び出して、ダイアログのワークエリアを開放することを忘れないでください。

Mac OS XでNavigation Service 3.0を利用したファイルオープンダイアログの挙動について、いくつか注意項目をまとめておきます。Modeless Dialogの場合には、Modal Dialogの場合と異なり、ダイアログが必要としないメニューアイテムをハイライトにする処理はされません。開発者側で何もしなければ、Open(開く)やQuit(作業終了)についてもユーザが利用可能なままになっています。そのため、自分自身で必要のないメニューアイテムをハイライトにする必要があります。加えて、ダイアログのタイトルバーにはClose、Zoom、Collapseの各ボックスが表示されており(表示される必要はあるのだろうか?)、これらをユーザがクリックした時の挙動はシステム側に任されています。

 

Closeボックスを押せば「キャンセル」ボタンを押したのと同じだろうと予想していたのですが、何故だか現状のMac OS Xでは、アプリケーションが落ちてしまう場合が多々あります。これはきっとバグなんでしょうね(涙)。

次回は、Navigation Service 3.0を利用したファイル保存ダイアログの話しに移ります。ファイルオープンダイアログとは異なり、ファイル保存ダイアログは対象となるウィンドウのタイトルバーから降りてくるSheet Windowとして表示されます。
[小池邦人/オッティモ]
関連リンクオッティモ