前半では、ウィンドウにToolbarをセットする方法を調べてみました。今回は、Toolbar上のアイテム(アイコンやラベル)をクリックすることで、親ウィンドウの右横にDrawerウィンドウを表示させる仕組みを解説してみます。切り替えるための2つのDrawerウィンドウ(Drawer_1とDrawer_2)は、Interface BuilderでNibファイルとして用意しておきます。前回紹介したopenMyWindow()ルーチンにより、親ウィンドウをオープンするのと同時に、まずは1番目のDrawer(rawer_1)をその右側にせり出させます。それを実現しているのが、以下のopenMyDrawerWindow()ルーチンです。

最初にwid(DrawerのID番号)を文字列に変更し("1"か"2")それを文字列"Drawer_"の後ろに結合します。これで、Nibファイルから呼び出すDrawerウィンドウの名称が作成できました。copyString()とcatString()は、2つのパスカル文字列の複製と結合を実行する簡単な自作ルーチンです。CFStringCreateWithPascalString()でパスカル文字列をUnicode文字列に変換した後に、CreateNibReference()とCreateWindowFromNib()でDrawerを作成します。ここまでの過程は、普通のウィンドウを作成する時とまったく同じです。
続いて、得られたWindowRef(wptr)を外部変数のdrawer_wptrに保存し、SetWRefCon()によりDrawerのID番号をウィンドウリファレンス値として保存します。SetDrawerParent()で親ウィンドウを指定してから、SetDrawerOffsets()で相対表示サイズを指示します。SetDrawerOffsets()に代入する値は、Drawerを親ウィンドウの上下サイズから何ピクセル縮めるのかを指示しています。今回は親ウィンドウの右側にせり出すので「Drawer矩形枠の下限は親から16ピクセル上にしろ」という指示になります。
SetDrawerPreferredEdge()でディフォルトのせり出し方向を右側(kWindowEdgeRight)に設定したら、OpenDrawer()で実際に表示させます。OpenDrawer()の2番目の引き数は、Drawerを親のどちら側に表示させるかを決め(kWindowEdgeDefault...つまり右側)、3番目の引き数はゼロか1で、表示アニメーションを「同期」で行うか「非同期」で行うかを決定します。同期を選択した場合には、アニメーションが終了するまでOpenDrawer()から制御は返りません。逆に非同期だと、実際のアニメーションはOpenDrawer()を抜けた後のEvent Loop中に実行されます。
次は、Toolbarのアイテムがクリックされた時に、親ウィンドウのCarbonEvent Handler(前回紹介したmyWindowEventHandler()ルーチン)から呼ばれるswitchMyDrawerWindow()ルーチンです。

このルーチンの作業目的は、「もし現在表示しているDrawerと同じID番号のアイテムがクリックされた場合には、それを表示したり隠したりする(トグル処理)」「もし現在と異なるID番号のアイテムがクリックされた場合には、現在のDrawerを削除し、新しいDrawerを作成する」といった内容です。処理が実行されるのは、drawer_wptrにWindowRefが代入されている場合だけです。GetWRefCon()でDrawserのID番号を得て、もしそれが同じならばGetDrawerState()で表示状態を調べてトグル処理を行います。同じでなければ、古いDrawerを削除してから新しい方をオープンします。実は、Drawerのトグル処理にはToggleDrawer()というAPIが用意されており、それを使えば以下のようにもっと簡単に記述できます。
}
ところが、何故だかToggleDrawer()ではアニメーションの同期、非同期の指示を行うことができません。ToggleDrawer()は必ず非同期で実行されてしまいます。現状ではDrawerの「非同期アニメーション」が使えないのは、それを行なっている間にユーザが親ウィンドウを動かすと、Drawerと親ウィンドウが離れてしまい、非常にみっともない状態になるからです(避ける方法はあるのだが..)。この不都合を含め、筆者がDrawerとToolbarを扱っている時に発見した不都合(?)を最後にまとめておきます。
・Toolbarを表示させると、せっかくSetWindowIdealUserState()で設定しておいたウィンドウズーム用の標準矩形領域がずれてしまう。
・Toolbarにアイコンをセットしていない場合でも、コマンドキー+Toolbarボックスクリックで、その表示モードに切り換わってしまう。セットしていなければ、その表示モードは避けるべきでしょう。
・Interface Builderで登録したDrawerウィンドウは、Attributesとして「Compositing」をチェックしなければいけません。このチェックを忘れていると、Drawerは親ウィンドウから正常に表示できません(仕様?)。
・Drawerのオープン、クローズアニメーションを非同期で行なう場合、その瞬間にユーザが親ウィンドウを移動させると、Drawerと親ウィンドウが離れてしまう。
・Drawerを出したまま親ウィンドウのグローボックスをドラッグして拡大させると、一瞬Drawerウィンドウとその中身(コントロールなど)の位置関係がずれる。
・Drawerと親ウィンドウの上下関係が変わる場合があある。つまり、どちらかをクリックすることでフロントウィンドウが切り換わってしまうのですが、本当ならば、親ウィンドウが必ずフロントウィンドウとして取り扱われるべきでしょう。
Drawerは、CarbonLibから導入されたウィンドウのグループ化機能で実現されているようですが、どう考えても作りかけといった感が拭えません。前回解説したToolbarの方もそうなのですが、Interface Builderでの編集を含めて、さらなる改良(せめてCocoa並に)を希望したいと思います。
copyright 2003 Ottimo, Inc. All rights reserved
無断転載・引用禁止
Contact us: koike@ottimo.co.jp