タイトル【小池邦人のプログラミング日記】2001/1/10<Carbon Event Managerを使う その3>カテゴリーCarbon/CF, 小池邦人のプログラミング日記
作成日2001/1/11 11:43:3作成者新居雅行
今回も「BasicCarbEvents」サンプルを取り上げ、ウィンドウに対応させたEvent Handlerルーチンの挙動や、Fileメニューで「Quit」が選択された時のCarbon Event Managerの働きを調べてみます。

ところで、ついにMac OS Xの発売開始日が3月24日に決定しました。実際のマシンにプリインストールされて販売されるのは7月になるそうです。ユーザの立場としては、3月24日のバージョンが最終βバージョン、7月にプリインストールされるのがf1バージョンぐらいに考えていれば心も安らぐのですが(笑)、デベロッパー側か見ると、そんな悠長な事は言ってられません。現在のパブリックβ版では、Carbon Event Managerなどで実装されていない機能が多数存在しています。よってデベロッパーへは、Carbon APIをちゃんとフル実装したβ2版を提供してもらわないと困るわけです。まあ、「3月24日発売のバージョンがそれだ!」と言われてしまうとそれまでなのですが...(涙)。

Mac OS Xに関係する追加情報として、以下のApple Carbon Documentサイトに「MoonTravel.pdf」という90ページ程度のPDFドキュメントが登録されました。

◇Moon Travel Tutorial: Creating a Carbon Application
  ―――「Developer Guides」のカテゴリを参照
 http://developer.apple.com/techpubs/carbon/carbon.html

これは、Project BuilderとInterface Builderを利用して、Carbonアプリケーションを開発するためのチュートリアルです。Mach-O&NibベースのCarbonアプリケーションを、Interface Builderを用いて開発する過程が詳しく解説されています。Mac OS XのNative開発環境を堪能してみたい方は、是非一読されることをお薦めします。ただし、この環境で開発したCarbonアプリケーションはMac OS 9環境では起動できませんので、注意してください。

話しをBasicCarbEventsサンプルに戻します。最初に、ウィンドウ操作で発生したCarbon Eventを処理するためのMyWindowEventHandler()(Event Handler)を見てみます。

 

このルーチンは、InstallWindowEventHandler()でインストールしておいた3種類のCarbon Eventのうちのどれかが発生した時に呼ばれます。処理の準備として、GetEventParameter()でCarbon Eventの対象となるウィンドウのWindowRefを得ておきます。続いて、GetEventKind()が返したCarbon Eventの種類に応じて処理を3つに分岐させています。

Carbon Eventの種類が「kEventWindowDrawContent」であれば、ウィンドウの再描画が必要であることを意味します。何かに隠されていたウィンドウ領域が再表示された場合に起こり、昔の「Update Event」と同じだと考えれば良いでしょう。処理内容は簡単で、HandleWindowUpdate()が呼ばれてウィンドウ上に「Hello World!」が描画されます。次の「kEventWindowBoundsChanged」は、ユーザがウィンドウのGrowボックスをドラッグするなどして、ウィンドウの矩形枠(Bounds Rect)が変更された場合に起こります。この場合の処理はInvalWindowRect()にウィンドウの矩形枠をセットし、その矩形領域の再描画が必要であることをシステムに指示します。この処理を実行すると、引き続きkEventWindowDrawContent Eventが発生し、結果としてウィンドウ上に「Hello World!」が描画されることになります。

この時の注意点は、kEventWindowBoundsChanged Eventはウィンドウを移動した場合でも発生するということです。つまり、矩形枠の変更とはその縦横サイズだけではなく、表示位置の変更にも当てはまるわけです。実際、このソースコードのままだと、ウィンドウをマウスドラッグで移動する度に再描画が起こり、処理的には美しくありません。さらにマズイことに、現在のCarbonLib v1.2では、ウィンドウを移動させなくても(ウィンドウ矩形枠は変化しない)タイトルバーをクリックしただけで、このEventが発生してしまいます。多分、こちらはバグではないかと思います。

最後の「kEventWindowClose」は、ユーザがウィンドウのCloseボックスをクリックした場合に発生します。通常はそのウィンドウを閉じる処理が実行されるはずですが、このサンプルでは DisposeWindow()とQuitApplicationEventLoop()が呼ばれて、アプリケーションを終了させています。Event Handlerルーチンにおいて、ウィンドウにどんな操作をしたら、どのようなCarbon Eventが発生するのかをチェックしたい場合には、処理の中にSysBeep()を記述して警告音を鳴らしてみるのが、一番簡単で手っ取り早い方法です。

さて、続いてはFileメニューで「Quit」が選択された時にどう処理されるのかを調べてみます。不思議なことに、このサンプルのソースコードにはメニュー用のCarbon Event Handlerルーチンは存在していません。その代わり、前回お話したウィンドウの場合と同様に、Fileメニューで「Quit」が選択されると「Standard Handler」(ディフォルト処理)が呼ばれているようです。Carbon Event Managerは、選択されたQuitメニュー用のHandlerルーチンがない場合には、AEInstallEventHandler()で登録しておいたApple Event用のQuit処理を「Standard Handler」として呼び出す仕組みになっているようです。

これでHandlerルーチンが存在しない点については納得できたのですが、ここでもうひとつの疑問が浮かんできます。実は、メニュー選択をCarebon Eventに対応させるためには、以下のように、メニューアイテムに対してSetMenuItemCommandID()でメニューコマンド(この場合には’quit’)を設定しておく必要があります。

SetMenuItemCommandID( GetMenuRef( 129 ),1,’quit’ );

メニューに対してこうした処理がなされて、初めてメニュー選択に対応した「Standard Handler」が呼ばれることになるのです。

ところが、このサンプルではSetMenuItemCommandID()が呼ばれていません?実は、この謎を解く鍵はBasicCarbEvents.rの中にありました。このファイルには、サンプルで使うすべてのリソースが定義されています。BasicCarbEvents.rをよく見てみると、Fileメニュー用の’MENU’リソースのすぐ下に定義されている’xmnu’リソースが、SetMenuItemCommandID()を実行したのと同じ効果を発揮しているようです。

 

’xmnu’リソースはメニューアイテムに色々な付加情報をつけるために導入されました。このリソースは、アイテムにコマンドIDを追加したい’MENU’リソースと同じリソースID番号で保存しておきます。その内部フォーマットは以下のように定義されています。

 

現在のResorcerer(v2.2J)には、’xmnu’リソースを編集するためのテンプレートが標準で付いています。しかし、どうもそれにはバグがあるようで、以下のようなシンタックスエラーが発生して編集することできません。

 

そこで、あちらこちらへ手配書をばらまいて情報を集めたところ、ResorcererやResEditで’xmnu’リソースをちゃんと編集することができるテンプレートが、以下のRing Server サイトのライブラリ内の「resedit-appearance-tmpl.hqx」に含まれていることが判明いたしました。

http://ring.etl.go.jp/pub/mac/info-mac/dev/

興味があるかたはダウンロードして、’xmnu’リソースの構造を確認してみてください。次回は、Carbon Eventを自作Carbonアプリケーションに実装する作業にチャレンジしてみたいと思います。
[小池邦人/オッティモ]
関連リンクオッティモ