タイトル鶴薗賢吾のCocoaはやっぱり!出張版》#3-ウィンドウの形状変更と透明化(2)カテゴリーCocoa, 鶴薗賢吾のCocoaはやっぱり!出張版
作成日2001/9/12 14:21:15作成者新居雅行
■ 形状変更の手順
仕組みは分かりましたが、それを実際にコード上でどう書くのかを見ていきます。ウィンドウを変形するには、以下の2段階の処理を行うことになります。

 1. ウィンドウ全体を完全に透明にする
 2. 不透明にしたい個所を描画する

まず、ウィンドウ上の全てのピクセルを完全に透明にしておいて、その後から描画をすることで、描画したところのみがウィンドウとして見えてくることになります。

■ ウィンドウ全体の透明化手順
ウィンドウ全体を透明化する方法を、さらに詳しくみていきましょう。以下の3段階の処理を行います。

 1. ウィンドウの背景色を透明色にすること
 2. ウィンドウの不透明フラグをNOにすること
 3. ウィンドウのスタイルマスクをNSBorderlessWindowMaskにすること

1.の「 ウィンドウの背景色を透明色にする 」は、以下の1行で行えます。NSWindowのインスタンスに対して、setBackgroundColor : を送って透明色である clearColor を指定します。下のコードの
「 window 」は存在しているNSWindowのインスタンスです。

[ window setBackgroundColor : [ NSColor clearColor ] ];

 ★ NSWindow : 背景色を指定する
  [書式] - (void) setBackgroundColor : (NSColor *) color
  [入力] color : 背景色

2.の「 ウィンドウの不透明フラグをNOにする 」は、以下の1行で行えます。setOpaque : にNOをセットします。

[ window setOpaque : NO ];

3.のウィンドウのスタイルマスクというのは、ウィンドウの大まかな形状を決めるもので、以下の値を足し合わせて指定します。完全に透明にするときには、NSBorderlessWindowMaskを使用します。

ウィンドウの形状指定
enum {
NSBorderlessWindowMask = 0, // 枠が無い
NSTitledWindowMask = 1, // タイトル部分を持つ
NSClosableWindowMask = 2, // クローズボックスを持つ
NSMiniaturizableWindowMask = 4, // 最小化ボタンを持つ
NSResizableWindowMask = 8 // リサイズボックスを持つ
};

このスタイルマスクは、ウィンドウを表示した後から変更することはできません。ウィンドウの初期化段階で指定したものに固定されるためです。初期化の段階でスタイルマスクを指定するためには、NSWindowのサブクラスを作成して、初期化メソッドをオーバーライドすることになります。NSWindowのサブクラスを作っているのはこのためです。

CustomWindowクラスのソースを書き出したら、Project Builderで初期化メソッドを以下のように書き換えます。初期化メソッドの名前は、長いですが、「 initWithContentRect : styleMask : backing : defer : 」といいます。

- (id) initWithContentRect : (NSRect ) contentRect
styleMask : (unsigned int ) aStyle
backing : (NSBackingStoreType) bufferingType
defer : (BOOL ) flag
{

NSWindow* win = [ super initWithContentRect : contentRect
styleMask : NSBorderlessWindowMask
backing : NSBackingStoreBuffered
defer : NO ];

return win;
}

ウィンドウ初期化時には、このメソッドが呼ばれます。MainMenu.nibの中のウィンドウをCustomWindowクラスにしたので、このメソッドが呼ばれるようになります。この中で、スーパークラス、つまりNSWindowの同じ初期化メソッドを呼んでいますが、ここでstyleMaskの箇所のパラメーターをNSBorderlessWindowMaskにすりかえているわけです。これで、スタイルマスクを変えることが出来ます。

このコードに、最初の2段階の処理もこの中に入れてしまいましょう。これで透明ウィンドウを作る初期化メソッドの出来上がりです。

- (id) initWithContentRect : (NSRect ) contentRect
styleMask : (unsigned int ) aStyle
backing : (NSBackingStoreType) bufferingType
defer : (BOOL ) flag
{

NSWindow* win = [ super initWithContentRect : contentRect
styleMask : NSBorderlessWindowMask
backing : NSBackingStoreBuffered
defer : NO ];

[ win setBackgroundColor : [ NSColor clearColor ] ];
[ win setOpaque : NO ];

return win;
}

これと、サンプルコードのCustomWindow.mのソースを比較してみてください。いくつか追加の処理は書かれていますが、ほぼ同様のことが書かれているはずです。個人的には、これだけのためにサブクラスを作るのはちょっと面倒な気もしますので、Interface Builder上でスタイルマスクの指定が出来るようになったらいいのになぁと思います。

[鶴薗賢吾]
関連リンクCocoaはやっぱり!