● 小池邦人のMac OS Xへの道 2002/06/01

〜 画像のセレクションを実現する その3 〜

今回は「ウニウニ波線」を表示する時にもOverlayウィンドウを使う「UniUni_Demo2」サンプルアプリケーションを作成してみます。ソースコードの内容は、前回、前々回に紹介した「UniUni_Demo1」サンプルとほとんど同じでが、その時に採用した方法と比較して、どんな違いがあるのかを調べてみます。

「UniUni_Demo2」のために用意するNibファイルは「UniUni_Demo1」とまったく同じですので、前々回の解説を参照してください。さっそく「UniUni_Demo2」サンプルのソースコードを「UniUni_Demo1」と比較してみます。まずは、main()ルーチンからです。



前回のソースコードでは、マウスドラッグで矩形セレクションを描画する度にOverlayウィンドウをオープンしていました。しかし、今回はmain()ルーチンで一度オープンしたら、アプリケーションが終了するまで利用し続けます。そのために、OverlayウィンドウのWindowRef(ovr_wptr)と、そこから得られるCGContextRef(ovr_ctx)を外部変数に確保するようにします。

メニューバー(MenuBar)とメインウィンドウ(MainWindow)をNibファイルから読み込み、setUpWindowEvent()でメインウィンドウにCarbon Event Handlerルーチンをインストールする所までは前回と同じです。CreateWindowGroup()で新しいウィンドウグループを作成していますが、今回はオープンしたOverlayウィンドウも同じグループに属させ、メインウィンドウの移動や縮小化に挙動を同期させます。オープンするOverlayウィンドウのフレームサイズには、メインウィンドウに配置されているPICT表示コントロールの矩形枠を使います。このコントロールのID番号は400ですので、それを用いgetMyControlRef()とGetControlBounds()で矩形枠を得ています。

openOverlayWindow()でOverlayウィンドウをオープンしたら、SetWindowGroup()でメインウィンドウと同じグループに属させます。その後、CreateCGContextForPort()でQuartz 2D(Core Graphics)描画用にCGContextRefを確保し、CGContextScaleCTM()で座標系をQuickDrawの左上原点に合わせておきます。前回の「UniUni_Demo1」サンプルでは、この処理を逐次実行していましたが、今回は最初に一度行うだけでOKです。最後にChangeWindowGroupAttributes()でグループのアトリビュート(性質)を変更しています。これは、グループ間のウィンドウ上下関係(レイアー)がマウスクリックで変わってしまわないように固定するためです。

メインウィンドウにCarbon Event HandlerルーチンをインストールしているsetUpWindowEvent()と、Current Event LoopにCarbon EventTimerルーチンをインストールしているsetUpTimer()に変更はありません。メインウィンドウのEvent HandlerルーチンであるmyWindowEventHandler()についても、ほとんど変更はありません。ただし、アバウトウィンドウを表示する時に、メインウィンドウとOverlayウィンドウの両方を閉じるので、'ok 'コマンドIDを受けた場合には、ShowWindow()を使い両ウィンドウを再表示させています。



EventTimerルーチンでのmyTimaerEvent()では、フロントウィンドウの代わりに外部変数のover_wptrをdrawSelection()に渡します。実際に「ウニウニ波線」を描画しているdrawSelection()には、いくつかの変更点があります。



今回は「ウニウニ波線」はメインウィンドウではなくOverlayウィンドウの方に描画されます。ですから、CGContextRefを得るためにCreateCGContextForPort()を呼ぶ処理や、QuickDrawに合わせて座標系を変換をする処理は省かれます。加えて、前回はPICT表示コントロールを再描画することで「ウニウニ波線」を消去していたのですが、それがclearSelection()ルーチンに取って代わられました。ウィンドウ上のセレクション領域を消去する処理は、後から説明するhandlSelection()でも使うので、独立ルーチンとして準備したわけです。

Event Handlerルーチンの'sall'と'selc'のコマンドIDは、それぞれ、メインウィンドウの「全選択」と「選択解除」ボタンがクリックされた時に対応しています。これらの処理は、どちらもhandleSelectAll()が実行します。ここでも、直前描画されていた「ウニウニ波線」を消去するために、DrawOneControl()の代わりにclearSelection()が利用されています。



それとは別に、Editメニューの「Copy」を処理しているのがhandleCopy()ルーチンです。こちらの処理では、逆に「ウニウニ波線」を消去する必要がなくなりましたので(メインウィンドウには描画されないため)消去に使っていたDrawOneControl()が取り除かれています。



最後は、実際にセレクション処理をしているhandlSelection()ルーチンの違いを見てみます。



ここでも、「Overlayウィンドウのオープン」「CGContextRefの確保」「QuickDawに合わせた座標系の変換」「DrawOneControl()での図形の消去」の4つの処理が省略されています。それ以外については、前回のルーチンとまったく同等の処理内容とです。このように両サンプルソースコードを比較してみると、先んじてOverlayウィンドウをオープンしておいた方が、描画処理のためのソースコードがスッキリすることが理解できます。ただし、Overlayウィンドウを表示している時には、それによって引き起こされる別の現象も頭に入れておく必要があります。

例えば、今回のサンプルで「ウニウニ波線」が表示されている時に、その波線の真上をマウスクリックしてみてください。

 

通常ならドラッグで矩形領域の書き換えが開始されるのですが、この場合には何も起こりません。これは、マウスクリックで発生するCarbon Eventが、メインウィンドウではなくOverlayウィンドウの方に送られているためです。つまり、Overlayウィンドの「透明」以外の個所でのマウスクリックでは、通常ウィンドウと同じくCarbon Event が発生するのです。ですから、アプリケーションによっては、Overlayウィンドウ側にも幾つかのEvent Handlerルーチンを用意しておく必要が出てくるでしょう。例えば「ウニウニ波線」上のマウスクリックを認識し、矩形領域を拡大縮小するような処理を実装したい場合には、この「Overlayウィンドの性質」をうまく使うのが得策かもしれません。

ここで解説している「UniUni_Demo2」サンプルアプリケーションは、以下のサイトに登録されていますので試してみてください。Mac OS X 10.1と最新版のDeveloper Toolsが必要です。

http://www.ottimo.co.jp/library/

次回は、久しぶりにQuickTimeの話をしてみます。本当なら、QuickTime 6.0での新機能などを紹介したいところですが、まだ正式発表前ということで、公にするのにはもう少し時間がかかるようです。そこで、Carbon Eventモデルを採用しているアプリケーションで「Movie Controller」を使う方法を解説したいと思います。


copyright 2002 Ottimo, Inc. All rights reserved
無断転載・引用禁止
Contact Us: koike@ottimo.co.jp