OSX下原生态按钮的Hover状态

14 篇文章 0 订阅
14 篇文章 2 订阅
OSX原生态按钮的Hover状态

        在上一篇《OSX10.11分屏(SplitView)功能的新特性研究》文章中,介绍了自定义TitleBar时,用到了原生态的按钮。此时的原生态按钮的行为跟使用原生态的TitleBar上自带的按钮行为还有点不一样,你把鼠标移到最大化、最小话以及关闭按钮上的时候,会发现没有hover的状态。

        究竟是什么原因呢?我们该如何解决这个问题呢?带着疑问,查看NSButton的定义,里面提供的各种函数尝试一遍都不起多用,此时我们就应该想到了私有类的私有函数,这三个原生态按钮的cell都继承于_NSThemeWidgetCell类,查看这个类,最终锁定了coreUIState这个方法,并且进一步追踪出三种状态下返回字符串为”normal”(正常态)、”rollover”(悬停态)以及”pressed”(按下态)。有关如何锁定的问题,请参看上篇文章,留给开发者自己实践去了。

        最后使用Method Swizzling 钩住(Hook)我们想截获的消息,并对感兴趣的消息进一步的处理,代码片段如下:

//设置标示,便于从截获的消息中,找出我们感兴趣的对象
 [self.closeButton setTitle:@"OSX_CUSTOM_BUTTON"];
 [self.minimizeButton setTitle:@"OSX_CUSTOM_BUTTON"];
 [self.zoomButton setTitle:@"OSX_CUSTOM_BUTTON"];



//消息劫持代码
CFStringRef (* originalIMP)(id self, SEL _cmd);//保存原始的消息函数
Method coreUIWidgetStateMethod=class_getInstanceMethod(NSClassFromString(@"_NSThemeWidgetCell"), NSSelectorFromString(@"coreUIState"));
const char *encoding=method_getTypeEncoding(coreUIWidgetStateMethod);
originalIMP=(void*)method_getImplementation(coreUIWidgetStateMethod);
class_replaceMethod(NSClassFromString(@"_NSThemeWidgetCell"), NSSelectorFromString(@"coreUIState"), (IMP)methodState, encoding);


//处理劫持的消息
static CFStringRef methodState(id self, SEL _cmd) {
    if ([self isKindOfClass:[NSButtonCell class]]) {
        NSButtonCell *cell = (NSButtonCell*)self;
        NSString *title = [cell title];
        if ([title isEqualToString:@"OSX_CUSTOM_BUTTON"]) {
            if (cell.highlighted) {
                return (__bridge CFStringRef)@"pressed";
            } else if (cell.state) {
                return (__bridge CFStringRef)@"rollover";
            } else {
                return (__bridge CFStringRef)@"normal";
            }
        }

    }

    //不是我们感兴趣的,调用原来的消息处理函数
    return originalIMP(self,_cmd);
}




//鼠标移入与移除事件,切换正常态与悬停态
-(void)mouseEntered:(NSEvent *)theEvent {
    [self setTitleButtonDisplay:YES];
}

-(void)mouseExited:(NSEvent *)theEvent {
   [self setTitleButtonDisplay:NO];
}

- (void)setTitleButtonDisplay:(BOOL)bHover {

//设置state属性值代表按钮正常与悬停的状态
    [closeButton setState:bHover];
    [zoomButton setState:bHover];
    [minimizeButton setState:bHover];
    [closeButton setNeedsDisplay:YES];
    [zoomButton setNeedsDisplay:YES];
    [minimizeButton setNeedsDisplay:YES];
}

        将上述代码移植到自己的工程中,会发现神奇的事情发生了,按钮可以捕捉到hover状态了。

        转载请注明出处:http://blog.csdn.net/skynullcode

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值