[系统控件重绘教程(二)]重绘NSButton

[系统控件重绘教程(二)]重绘NSButton

时间: 2010-02-05 10:26 点击:1858 次

[系统控件重绘教程(二)]重绘NSButton

作者  yoyokko


原帖地址  http://www.cocoachina.com/bbs/read.php?tid-14590.html


首先大家看Apple关于NSButton的描述,NSButton跟NSWindow一样,它的外观形式也是委托给NSButtonCell来处理的, 自身只包含逻辑代码。

所以重绘NSButton就是重绘NSButtonCell啦,然后把NSButton的cell设置位你自己的cell就 好了。


1)重绘目标

首 先观察一下系统NSButton的行为和外观表现,可以发现默认Button(快捷健设置为return)是有一个一闪一闪的效果,鼠标点击其他非默认 button的时候同window上默认button的蓝色消失,同时被点中button变成蓝色。放开鼠标,默认button恢复蓝色背景并闪烁,被点 击button变白色。

重绘一个控件最好是不要改变其默认行为,也最好不要违反Apple的关于界面设计的建议文档。所以我们的目标是重绘出来的 button是灰色渐变背景,默认button有一个黄色的圈圈围在周围,不闪烁。被点中的button显示黄色圈圈,默认button黄色圈圈消失。

效 果如下图:

鼠标未按下效果


 

鼠标按下效果


 


2)渐变 背景

NSButtonCell的重绘方法很简单,重写下面的方法即可。

逻辑就是

1)检测当前button 的类型(普通button,checkbox,radiobutton等)

2)画button的基本形状和颜色

3)如果当前button 被click了,那么显然的画一个黄色的圈圈上去

4)如果没有被click,那么检测是否为默认button,如果是,并且当前window没有 被click的其他button,那么为自己画一个黄色的圈圈,否则不画。


// buttoncell有一个私有方法来标示当前button的类型

// 这里只列出关心的三种类型

typedef enum KAButtonType{

    KACheckBox = 3,

    KARadioButton = 4,

    KARoundButton = 7

};


- (void)drawWithFrame: (NSRect)cellFrame inView: (NSView *)controlView

{

switch ([self _buttonType]) { // buttonCell的私有函数,可以确定button类型,10.4/10.5/10.6都可用

            case KACheckBox:

                [self drawCheckInFrame:cellFrame isRadio:NO]; // 画checkbox的形状,这里忽略不画

                break;

            case KARadioButton:

                [self drawCheckInFrame:cellFrame isRadio:YES]; // 画radiobutton的形状,这里忽略不画

                break;

            default:

                switch ([buttonCell bezelStyle]) { // 这就是button啦,默认的形状,这个参数可以在IB里设置,

                                                                           // 所以button的类型必须为NSRoundedBezelStyle,当然你可以改为其他的

                    case NSRoundedBezelStyle:

                        [self drawRoundedButtonInFrame: cellFrame inView: controlView];

                        break;

                        

             case NSRegularSquareBezelStyle:

                        [self drawHyperLinkButtonInFrame: cellFrame];

                        break;

                    default:

                        break;

                }

                break;

        }

        

        // 画Button的图片哦

        // Comment by yoyokko

        // if [buttonCell _normalImage] is nil, that to say there is a missing 

        // field in nib file for this check box --> 

        // NSButtonCell uses function <(int)_buttonType> to determine button type.

        // After hacking, I found that 3==Checkbox, 4==Radio, 7==RoundedButton

        if([buttonCell _buttonType] == KARoundButton)

        {    

            if([buttonCell imagePosition] != NSNoImage) {

                [self drawImage: [buttonCell image] withFrame: cellFrame inView: [buttonCell controlView]];

            }

        }

}

// 查询当前window上有没有被click的button

- (void)travelSubViews: (NSView*)view

{

    NSArray *items = [view subviews];

    NSEnumerator *enumerator = [items objectEnumerator];

    id anObject = nil;

    while (anObject = [enumerator nextObject]) 

    {

        if ([anObject isKindOfClass: [NSButton class]])

        {

            NSButtonCell *buttonCell = [anObject cell];

            NSBezelStyle buttonStyle = [buttonCell bezelStyle];

            if ([buttonCell isHighlighted] &&

                (buttonStyle == NSRoundedBezelStyle || buttonStyle == NSTexturedRoundedBezelStyle))

            {

                [self setMIsFound: YES];

                break;

            }

        }

        else

        {

            [self travelSubViews: anObject];

        }

    }    

}


// 画渐变的button和黄色圈圈

-(void)drawRoundedButtonInFrame:(NSRect)frame inView: (NSView *)controlView

{    

    NSRect textFrame;

    

    //Adjust Rect so strokes are true and

    //shadows are visible

    frame.origin.x += .5f;

    frame.origin.y += .5f;

    frame.size.height -= 1;

    frame.size.width -= 1;

    

    //Adjust Rect based on ControlSize so that

    //my controls match as closely to apples

    //as possible.

    switch ([buttonCell controlSize]) {

        default: // Silence uninitialized variable warnings for textFrame fields.

        case NSRegularControlSize:

            

            frame.origin.x += 4;

            frame.origin.y += 4;

            frame.size.width -= 8;

            frame.size.height -= 12;

            

            textFrame = frame;

            break;

            

        case NSSmallControlSize:

            

            frame.origin.x += 4;

            frame.origin.y += 4;

            frame.size.width -= 8;

            frame.size.height -= 11;

            

            textFrame = frame;

            textFrame.origin.y += 1;

            break;

            

        case NSMiniControlSize:

            

            frame.origin.y -= 1;

            

            textFrame = frame;

            textFrame.origin.y += 1;

            break;

    }

    

    //Create Path

    NSBezierPath *path = [[NSBezierPath alloc] init];

    [path appendBezierPathWithRoundedRect: frame cornerRadius:6.0f];

    if([buttonCell isEnabled]) 

    {    

        // draw inner part of button first

                // 画button的灰色渐变部分

        [self drawShadingWithStartingColor: [self colorVlaueWithRed: 239 green: 239 blue: 239]//[NSColor blackColor]

                           withEndingColor: [self colorVlaueWithRed: 93 green: 93 blue: 93]//[NSColor whiteColor]

                              inBezierPath: path];

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值