青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

逛奔的蝸牛

我不聰明,但我會很努力

   ::  :: 新隨筆 ::  ::  :: 管理 ::
@import url(http://m.shnenglu.com/CuteSoft_Client/CuteEditor/Load.ashx?type=style&file=SyntaxHighlighter.css);@import url(/css/cuteeditor.css); 首先大家看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];

        
        // draw focus ring second
       // 當當前button被click時,畫那個黃色的圈圈
        // if the button is highlighted, then draw a ring around the button
        if([buttonCell isHighlighted]) // 當button被click時,isHighlighted返回YES
        {            
            [[self colorVlaueWithRed: 246 green: 186 blue: 55] set];
            [path setLineWidth: 3.0f];
            [path stroke];        
        } 
        else
        {

          // button沒有被click,那就檢查是否為默認的button
            // otherwise, check if it is a default button
            id btnControl = [buttonCell controlView];
        
            if ([btnControl respondsToSelector: @selector(keyEquivalent)] && [[btnControl keyEquivalent] isEqualToString: @"\r"])
            { 

                // 如果是默認button
                NSView *superView = controlView;
                NSView *tempView = nil;
                for (tempView = superView; tempView != nil; tempView = [tempView superview])
                    superView = tempView;

                // 找到當前window的contentview
                if (superView)
                {
                    [buttonCell setMIsFound:NO];
                    [buttonCell travelSubViews: superView];
                }
                

                // 看當前window中有沒有被click的button,沒有就把自己這個默認button畫一個黃圈
                if (![buttonCell mIsFound])
                {
                    [[self colorVlaueWithRed: 246 green: 186 blue: 55] set];
                    [path setLineWidth: 3.0f];
                    [path stroke];
                }
                
                [buttonCell setMIsFound:NO];
            }
        }
        
    } 
    else 
    {        

        // button 沒有enable
        [self drawShadingWithStartingColor: [self colorVlaueWithRed: 220 green: 220 blue: 220]//[NSColor blackColor]
                           withEndingColor: [self colorVlaueWithRed: 112 green: 112 blue: 112]//[NSColor whiteColor]
                              inBezierPath: path];
    }
    
    [path release];

    
        // 畫button的text,這里忽略不畫
    if([buttonCell imagePosition] != NSImageOnly) {        
        [self drawTitle: [buttonCell attributedTitle] withFrame: textFrame inView: [buttonCell controlView]];
    }
}



至此,所有繪制的代碼工作都已經完成了,包括黃色圈圈和點擊其他button的行為都寫好了~
但這樣做會有一個問題……


3)更改系統默認畫黃色圈圈的行為
釋下面一段代碼的行為,這個很重要,否則會出現非常巧妙的bug……很奇妙,困擾了我兩個星期的bug,恨哪~

- (void)heartBeat:(CDAnonymousStruct7 *)fp8
{
    id btnControl = [self controlView];

    if ([btnControl respondsToSelector: @selector(keyEquivalent)] && [[btnControl keyEquivalent] isEqualToString: @"\r"])// && !oneButtonClicked)
    {
        [btnControl setNeedsDisplay:YES];
    }
}


首先探索一下系統默認button的一閃一閃的行為是怎么做的,blabla一大堆,經過hack發現,每個程序在起來之后都會啟動一個叫做HeartBeat的線程。每個control都有一個heartBeat:的函數。
這個線程負責默認button的一閃一閃的刷新,spin的旋轉等,所以在你的主界面block住的時候你會發現button還在閃,spin還在轉,而你自己用timer寫的progressspin是不會轉的。對于一個window來說,它上面的button不會一直刷新,只是顯示的時候刷幾次,而默認button會被heartbeat線程調用一直刷新。

問題就出在這里,這是一個線程啊,我們重寫了buttoncell的繪制函數,但我們并沒有做處理并保證這個函數是原子的調用啊,所以這里會發生非常極品的問題(當用多線程繪制界面時一定要注意是原子操作)
首先有一個程序彈出了一個sheet,然后這個sheet上有一個button,點擊button會再次彈出一個sheet,不知道是不是apple的這里的消息循環有問題,在點擊這個button彈出sheet的同時,button所在的window或者新彈出的window上有的button會被刷成別的形狀,比如某個radiobutton的字變成了OK,或者就變成了一個拉長版的普通button,并且只會變成默認button的字或者形狀。
這就是因為多線程的原因造成的。在刷當前button的時候,heartbeat來搗亂了,不知道怎么搞得就把默認button的字或者形狀刷到了當前button的信息上面(button的text就是被改變了)。不太清楚默認的heartBeat:里面做了些什么。
所以這里只能重寫heartBeat:函數(亦或把重繪函數變成原子的,沒試過),在這個函數里面啥都不做,只是檢測當前button是否為默認button,是的畫就通知主線程來刷新。
因為這里只是加一個黃色圈圈而已,所以即使主線程block住也沒什么問題。

JB,非常JB~

PS:在10.4上程序起來時heartbeat線程不能正常起來,所以需要在程序結束launching之后談一個sheet,再把之關閉就可以了(很奇怪,估計Tiger上的消息循環還是有很大的問題的)。
@import url(http://m.shnenglu.com/CuteSoft_Client/CuteEditor/Load.ashx?type=style&file=SyntaxHighlighter.css);@import url(/css/cuteeditor.css);

From: http://www.cocoachina.com/bbs/read.php?tid=14590
posted on 2011-12-09 04:00 逛奔的蝸牛 閱讀(2961) 評論(0)  編輯 收藏 引用 所屬分類: Cocoa
青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            国产精品一区久久久久| 亚洲高清自拍| 欧美国产日本在线| 欧美在线视频不卡| 亚洲一区二区高清视频| 国产丝袜一区二区| 国产精品成人免费| 欧美婷婷六月丁香综合色| 99天天综合性| 一本一本久久| 亚洲视频香蕉人妖| 午夜精品免费| 亚洲国产日韩美| 一区二区视频欧美| 国产一区二区你懂的| 国产午夜精品久久| 亚洲欧美精品伊人久久| 亚洲女爱视频在线| 亚洲性xxxx| 亚洲人成在线免费观看| 日韩天堂在线视频| 亚洲欧美视频| 你懂的视频欧美| 亚洲国产另类 国产精品国产免费| 篠田优中文在线播放第一区| 国产日韩欧美三级| 久久久精品一区二区三区| 久久综合九色九九| 免费亚洲婷婷| 亚洲小少妇裸体bbw| 久久久7777| 欧美精品一区二区三区四区| 国产精品成人播放| 午夜激情综合网| 欧美一级片在线播放| 美国成人直播| 国产精品美腿一区在线看| 国产自产v一区二区三区c| 亚洲在线观看免费| 亚洲国产一区二区三区在线播| 欧美成人综合网站| 国产精品免费看片| 久久久久一区二区| 亚洲欧美一区二区三区极速播放 | 亚洲一区中文| 亚洲综合激情| 亚洲高清在线播放| 亚洲三级影院| 国产精品一区视频网站| 久久综合伊人77777蜜臀| 日韩一级在线| 国产亚洲欧美色| 亚洲人线精品午夜| 国产午夜亚洲精品羞羞网站| 欧美福利影院| 久久99在线观看| 国产精品久久午夜夜伦鲁鲁| 久久岛国电影| 欧美激情免费观看| 亚洲第一在线综合网站| 久久精品国产免费看久久精品| 99视频精品| 韩国精品主播一区二区在线观看| 欧美一级二级三级蜜桃| 99精品国产在热久久婷婷| 国产日韩欧美在线| 亚洲精品资源| 欧美日韩精品一区视频 | 亚洲一区区二区| 久久久久久久网站| 国产亚洲成av人在线观看导航| 亚洲综合成人婷婷小说| 久久久国产精品亚洲一区| 亚洲欧美在线一区二区| 亚洲黄色大片| 久久久久久久国产| 欧美激情第1页| 一级成人国产| 亚洲欧洲在线一区| 欧美大尺度在线| 久久女同精品一区二区| 国产精品va| 99亚洲一区二区| 99国产精品久久久久久久成人热| 欧美黄色精品| 国产一区二区三区自拍| 亚洲影视在线播放| 亚洲欧美激情四射在线日 | 国产精品久久久久影院亚瑟| 亚洲黄色成人网| 91久久午夜| 亚洲精品一区二| 亚洲欧洲一二三| 免费日韩视频| 亚洲一区视频在线| 欧美日韩一卡| 久久综合九色综合欧美狠狠| 国产午夜精品理论片a级大结局| 亚洲婷婷免费| 午夜伦理片一区| 国产情侣一区| 欧美freesex交免费视频| 国产一区二区久久久| 欧美一区二区三区的| 久久久免费观看视频| 国产综合欧美| 免费成人高清视频| 亚洲精品乱码| 亚洲午夜视频| 国产欧美日韩精品专区| 久久高清福利视频| 亚洲精品国产拍免费91在线| 亚洲一区精品视频| 欧美在线高清| 欧美日韩八区| 中国成人黄色视屏| 亚洲一品av免费观看| 国产日韩欧美一区二区三区在线观看 | 一区二区三区欧美成人| 亚洲一区欧美激情| 国产欧美韩日| 欧美亚洲免费| 欧美黄色日本| 欧美一级淫片aaaaaaa视频| 国产精品一级| 麻豆精品精华液| 一区二区免费在线播放| 久久全国免费视频| 999在线观看精品免费不卡网站| 欧美搞黄网站| 夜夜嗨av色综合久久久综合网| 老鸭窝毛片一区二区三区| 亚洲精品一区二区三区不| 欧美日韩一区二区欧美激情| 午夜亚洲性色福利视频| 亚洲福利国产精品| 国内精品久久久久国产盗摄免费观看完整版| 欧美在线视频免费播放| 欧美高清在线一区二区| 亚洲男女自偷自拍| 亚洲福利视频一区| 国产精品久久一卡二卡| 欧美成年人视频网站| 亚洲欧美日韩人成在线播放| 欧美国产免费| 久久se精品一区二区| 一本色道久久综合狠狠躁篇的优点| 国产日韩欧美另类| 欧美日韩视频在线第一区| 久久九九国产精品| 亚洲一区精品视频| 99精品久久久| 亚洲国产欧美一区二区三区丁香婷| 欧美在线观看一区二区三区| 亚洲美女在线一区| 欧美日韩国产a| 久久日韩粉嫩一区二区三区 | 制服丝袜激情欧洲亚洲| 久久综合中文字幕| 亚洲一区三区视频在线观看| 亚洲美女诱惑| 亚洲精品免费观看| 国产视频欧美视频| 欧美无乱码久久久免费午夜一区| 久久蜜桃资源一区二区老牛 | 欧美专区一区二区三区| 亚洲午夜一区二区三区| 日韩一级在线观看| 亚洲经典自拍| 欧美激情国产精品| 免费看av成人| 免费观看不卡av| 久久欧美肥婆一二区| 久久久久久久久久码影片| 欧美伊久线香蕉线新在线| 午夜精品久久久久久久99樱桃 | 欧美国产亚洲视频| 欧美成人精品| 欧美黄色日本| 亚洲国产欧美日韩精品| 亚洲人成啪啪网站| 日韩午夜电影在线观看| 亚洲免费观看高清在线观看| 91久久在线视频| 亚洲精品一区在线| 亚洲免费av网站| 亚洲一区二区三区四区中文| 亚洲专区一区二区三区| 亚洲欧美三级伦理| 午夜精品视频在线| 久久激情五月激情| 蜜臀久久99精品久久久久久9| 久久免费一区| 亚洲欧美日韩国产一区| 蜜桃伊人久久| 欧美视频在线观看视频极品| 国产精品免费一区豆花| 国产一区二区精品| 最新日韩欧美| 亚洲在线一区二区|