HMDT - Logic and Intuition -

about HMDT

Cocoa Programming Tips 1001

Application Kit

NSView

Application Kit - NSView

View にカーソルを対応付ける

Keywords: resetCursorRects, addCursorRect

ある View とカーソルを対応付けられたら、便利だと思わないかい?View にマウスが入ったら、カーソルが変わる、出たら戻る、って感じの動作。

そのための機構が用意されている。Tracking Rect ってやつだ。Tracking Rect として、ある rect をセットしてやると、そこへマウスが入る時と、出る時が監視されるんだ。Tracking Rect の詳しい話は他に譲るとして、NSView にはカーソルと Tracking Rect を結び付けるための便利なメソッドが用意されているんだ。

まず、resetCurosorRects というメソッドだ。

Application Kit/NSView.h

- (void)resetCursorRects;

このメソッドは NSView がカーソル用の Tracking Rect を設定する時に使われるんだ。ユーザがオーバーライドする。カーソル用 Tracking Rect は、View の大きさが変わったり、ウィンドウの大きさが変わったりした時に、リセットされる。その度にこのメソッドが呼び出されるわけ。

resetCursorRects の中では、addCursorRect:cursor: を使おう。

Application Kit/NSView.h

- (void)addCursorRect:(NSRect)aRect 
        cursor:(NSCursor*)aCursor;

addCurosrRect:: で、カーソル用 Tracking Rect を追加できる。aRect の領域に入ったら、aCursor のカーソルに変わるんだ。

CursorView.m (sample)

- (void)resetCursorRects
{
    NSRect rect = [self bounds];
    NSCursor* cursor = [NSCursor IBeamCursor];
    [self addCursorRect:rect cursor:cursor];
}

これで、この View の領域に入った時、カーソルが I ビームカーソルに変わるぞ。

Application Kit - NSView

drawRect 以外で描画する

Keywords: displayIfNeeded

View になにかを描くときは、drawRect: メソッドをオーバーライドして、その中でいろいろやるのが普通だ。でも、それ以外のタイミングでやりたくなるときもあるよね。そんなときは、displayIfNeeded を使う。

Application Kit/NSView.h

- (void)displayIfNeeded;

View に対してなんらかの描画をしたあと、displayIfNeeded を呼べば、システムがよきにはからってくれるわけ。

DisplayView.m (sample)

- (void)initWithFrame:(NSRect)rect
{
    self = [super initWithFrameRect:rect];
    if(self) {
        NSArray* array = 
            [NSArray arrayWithObject:NSFilenamesPboardType];
        [self registerForDraggedTypes:array];
    }
    return self;
}

- (unsigned int)draggingEntered:(id <NSDraggingInfo>)sender
{
    NSFrameRect([self visibleRect]);
    [self dispalyIfNeeded];
    
    return NSDragOperationNone;
}

- (void)draggingExited:(id <NSDraggingInfo>)sender
{
    NSEraseRect([self visibleRect]);
    [self dispalyIfNeeded];
}

上のサンプルは、Finder からファイルをドラッグしてきたときに、View をハイライト表示させる例だ。draggingEntered: の中で、NSFrameRect を使って枠を描いてる。その後に displayIfNeeded を呼んで、システムにアップデートをお願いしているんだ。draggingExited: の方も同様だね。

Application Kit - NSView

コンテキストメニューを動的に変化させる

Keywords: menuForEvent

NSResponder で解説した通り、コンテキストメニューを設定できるんだ。そのメニューを、状況に応じて動的に変化させたい場合には?その場合には NSView のメソッドである menuForEvent: を使うんだ。

Application Kit/NSView.h

- (NSMenu *)menuForEvent:(NSEvent *)event;

ctrl + クリックなど、コンテキストメニューを表示させようとすると、このメソッドが呼び出される。で、好きなメニューを作って、返してやればいいんだ。そうすれば、それが表示される。引数として NSEvent が渡されるので、マウスの位置とか、好きな情報を取り出して使えばいいんだ。

■関連リンク:
コンテキストメニューを設定する (NSResponder)

Application Kit - NSView

フォーカスリングのスタイルを変える

Keywords: NSFocusRingType

Mac OS X 10.3 からは、NSView と NSCell に、フォーカスリングのタイプを設定できるようになった。フォーカスリングっていうのは、テキストビューとかにフォーカスがあたったときに、周りに描かれるあれね。

フォーカスリングのタイプは、NSFocusRingType 定数として定義されている。次の 3 つがあるんだ。

Application Kit/NSGraphics.h

typedef enum _NSFocusRingType {
    NSFocusRingTypeDefault = 0,
    NSFocusRingTypeNone = 1,
    NSFocusRingTypeExterior = 2
} NSFocusRingType;

NSFocusRingTypeDefault は、NSView か NSCell で定義されているデフォルトのタイプを使う。NSFocusRingTypeNone は、フォーカスリング無し。NSFocusRingTypeExterior は、標準のフォーカスリングで、外側に描くやつだ。ま、実質 NSFocusRingTypeExterior しかないようなもんだ。

このフォーカスリングを取得、設定するには、NSView か NSCell の focusRingType、setFocusRingType を使う。

Application Kit/NSView.h

- (NSFocusRingType)focusRingType;
- (void)setFocusRingType:(NSFocusRingType)focusRingType;

ここでフォーカスリングとしてデフォルト(NSFocusRingTypeDefault)が設定されると、NSView か NSCell の defaultFocusRingType が呼ばれる。ここで得られる値がデフォルトとして使われるんだ。

Application Kit/NSView.h

+ (NSFocusRingType)defaultFocusRingType;

だから、これを上書きすれば、デフォルトのフォーカスリングを変更できる。たとえば、こんな感じで。

(sample)

@interface NSView (DefaultFocusRingType)
+ (NSFocusRingType)defaultFocusRingType;
@end

@implementation NSView (DefaultFocusRingType)
+ (NSFocusRingType)defaultFocusRingType
{
    return NSFocusRingTypeNone;
}
@end

これはカテゴリを使って、NSView の defaultFocusRingType を書き換えてみた例だ。NSFocusRingTypeNone を返すようにしてみた。これで、デフォルトの挙動を変更できるぜ。

back to top content

Copyright © 2002-2006 HMDT. All rights reserved.