タイトル小池邦人のプログラミング日記》2001/4/14<ウィンドウのLive Resizing その1>カテゴリーユーザインタフェース, Carbon/CF, 小池邦人のプログラミング日記
作成日2001/4/14 18:44:9作成者新居雅行
今回は、自作Carbonアプリケーションへに「ウィンドウのLive Resizing」を実装してみることにします。Live Resizingとは何でしょうか? Mac OS 9のアプリケーションでは、ウィンドウのGrow Boxをドラッグすると、ウィンドウの外枠だけが拡大縮小されます。それと比較して、Mac OS Xでは、ウィンドウ全体をリアアルタイムで書き換えながら拡大縮小することができます。Mac OS XでのFinderやInternet Explorerでウィンドウを拡大や縮小してみると、その機能の実体がよく分かります。見た目は非常に美しい機能なのですが、現状ではその書き換えスピードがあまりにも遅いために(特にFinderのリスト表示の時など)、一部のユーザから集中攻撃を浴びている不幸な新参者です(笑)。

この機能を、以前Carbon Eventを解説した時に用いた「ViewJPEG」という自作アプリケーションに実装してみます。今回、Metrowerks CodeWarriorのプロジェクトにリンクするCabonLibは、最近ADCメンバーサイトに登録されたCarbonLib 1.3b5 を利用します。また、このSDKのUniversal Interfacesのバージョンは3.4f1となっています。CarbonLib 1.3も、そろそろβ版から昇格して欲しいのですが、GM版への道はまだ遠いのでしょうか? ちなみに、「CarbonLib 1.3b45 SDK」に添付されているRelease Notesを読んでみると、今回のリリースバージョンではAPI自体の変更はなく、テキスト入力やプリントアウト関連のバグフィックスが大部分を占めているようです。また、特定アプリとの相性問題の解決が目立ちます(私の報告したバグはいつフィックスされるのだろうか?)それから、「Nibベースのアプリケーション開発」を解説した時に参照していた「Moon Travel Tutorila」ドキュメントとCarbon Eventsに関するドキュメント(両方ともPDF)が、最近新しく改訂されました。詳細を確認したい方は、以下のアップルのドキュメントサイトを参照してみてください。

◇Carbon Documentation: What’s New
 http://developer.apple.com/techpubs/macosx/Carbon/SiteInfo/whatsnew.html

「Moon Travel Tutorila」は、Mac OS X製品版のDeveloper Tools に含まれていたProject BuilderやInterface Builderに対応するため改訂されたようです。Carbon Eventsのドキュメントは、内容が5ページから30ページへとわずかに増量されました。しかし、まだまだ技術情報が貧弱であることには変わり有りません。

ウィンドウのLive Resizing機能を実装するためには、まずウィンドウ自身がこの機能を使えるように何らかの設定をする必要があるはずです。通常のままだと、Mac OS X上でもMac OS 9上とまったく同じように、ウィンドウ枠だけのResizingになってしまいます。さてどうすれば良いのでしょうか?このようなAPIに関する疑問点に遭遇したら、まずはUniversal Interfacesの内容を調べれば、たいがい何らかのヒントを見つけることができます。さっそく、ウィンドウに関するUniversal Header FileのMacWindows.hを調べてみると、WindowAttributesの設定値に以下のようなフラグを見つけることができます。

kWindowLiveResizeAttribute = (1L < < 28),/* this window supports live resizing (X only)*/

CreateNewWindow()に引数として渡すWindowAttributesに、このフラグを追加すれば、Mac OS X上でのLive Resizing機能がONになるようです。さっそくViewJPEGで画像ファイルのオープンを担当しているopenImageWindow()を、以下のように改良し試してみました。

 

ここで注意する点は、kWindowLiveResizeAttributeが利用できるのは、Mac OS X環境だけということです、Mac OS 9環境でこのアトリビュートを追加すると、CreateNewWindow()でエラーが発生してしまいます。よって、ソースコードでは、chkSysOSX()というルーチン(Gestalt()で調査しておいた環境値を返す)により、自分自身がMac OS X環境で起動しているかどうかをチェックし、その場合にのみアトリビュートにkWindowLiveResizeAttributeフラグを追加しています。

このアトリビュートの設定によりウィンドウ自身はLive Resizingするようになるのですが、これだけではウィンドウの中身(画像や上下左右のスクロールバー)はリアルタイムで再描画されません。これを実現するのには、画像ウィンドウに対して、Event Classが「kEventClassWindow」で、Event Kindが「kEventWindowBoundsChanging」のCarbon Event Handlerをインストールする必要があります。これにより、ユーザのマウスドラッグでウィンドウ枠のサイズや位置が変更されているあいだ、一定間隔でHandlerルーチンがCarbon Eventを受けることが可能になります。その時にウィンドウの中身を再描画してやれば、すべてのLive Resizingが完成するわけです。以下はViewJPEGのCarbon Event Handlerルーチンの一部で、SizeWindow()からupdateOffScreen()までの箇所がウィンドウの中身の再描画を担当しています。

 

ソースコードを見ると、chkSysOSX()で再描画をするかどうかをチェックしていることが分かります。つまり、この処理はMac OS 9環境では実行する必要はありません。

実は、Mac OS Xパブリックβ版ではこのスペックのCarbon Eventが未実装だったようで、インストールしたHandlerルーチンへのコールバックが起こりませんでした。(不思議とInternet Explorerでは可能だった?)しかし、嬉しいことに今回は問題なく動くようです。ところで、ウィンドウの中身を再描画している箇所を見ると、ウィンドウ自身のサイズ変更はWindow Managerが行なっているわけですから、ソースコード中のSizeWindow()は必要無いように思えます。しかし、これを外して試してみると、マウスドラッグを素早く行なった時、最後にマウスカーソルが静止した位置での中身の再描画が行われません。

 

どうも、Resizingが実行された直後のウィンドウ矩形枠(PortBounds)が設定されていない状況で中身の再描画ルーチンが呼ばれているようです。そこで、SizeWindow()により強制的にウィンドウ矩形枠を設定してから描画を試すと、今度は上手く行くようになりました。今回の解説に用いたViewJPEG v1.22のソースコードは以下のサイトに登録されています。詳細を確認したい方は、ぜひダウンロードしてみてください。

◇Ottimo, Inc.: Digital Library
 http://www.ottimo.co.jp/library/index.html

とりあえず、この処理の追加によりViewJPEGでも画像ウィンドウのLive Resizingが可能になりました。ウィンドウの拡大縮小時の追随スピードも、そこそこ実用範囲内だと思います。しかし、SizeWindow()を追加しなくてはいけなかった件も含めて、いくつか納得がいかない箇所がありました。そこで、新しく改訂されたCarbon Eventsに関するドキュメントを注意深く読んでみると、疑問点を解決するいくつかのヒントが記載されていることが分かりました。次回はそのヒントを元に、ウィンドウのLive Resizingを実現しているソースコードを、より良い形へと書き直しててみることにします。
[小池邦人/オッティモ]
関連リンクオッティモ