【问题标题】:Reimplementing the Mac OS X Dock's auto hide重新实现 Mac OS X Dock 的自动隐藏
【发布时间】:2010-10-12 05:03:52
【问题描述】:

我正在尝试在 Objective-C 中创建一个服务器监视器,其行为类似于 OS X 中的扩展坞。我希望当鼠标移到一侧时它会从屏幕一侧滑动屏幕,有点像自动隐藏打开时的停靠栏。我不知道从哪里开始..

我猜我需要一个带有 NSBorderlessWindowMask 掩码的窗口,但在那之后我不知所措。我是否只显示该窗口的 1 个像素,并等待 mouseOver 事件,或者这只是一个可以合理完成的事情的 hacky 解决方案?如果这是最好的方法,我将如何检查鼠标悬停事件?

【问题讨论】:

    标签: objective-c cocoa nsview nswindow


    【解决方案1】:

    我认为你的想法是对的。但请记住,根据您想要做什么,无边框窗口并不是最容易使用的东西(它们可能很棘手,尤其是像 Spaces 和 Exposé 这样的东西可能会增加复杂性)。

    如果这只是一个个人项目,您可能会逃脱一个像素边缘的窗口显示。如果这是一个专业项目,我建议考虑使用 Event Taps(稍后会详细介绍)。

    如果您采用“个人项目”的方式,您可以保留 1 px 的窗口边缘显示,使用自定义 NSView 子类将自身绘制为透明并设置一个 NSTrackingArea 来通知您 mouseEntered: 事件。

    要绘制透明区域,你可以在 drawRect 中做这样的事情:

    - (void)drawRect:(NSRect)frame {
       [[NSColor clearColor] set];
       NSRectFill(frame);
    }
    

    要设置跟踪区域,请在视图子类的 awakeFromNib 中执行此操作:

    - (void)awakeFromNib {
     NSTrackingArea *tracker = [[[NSTrackingArea alloc] initWithRect:[self frame]
       options:(NSTrackingMouseEnteredAndExited | NSTrackingActiveAlways)
       owner:self
       userInfo:nil] autorelease];
    
     [self addTrackingArea:tracker];
    }
    
    - (void)mouseEntered:(NSEvent *)theEvent {
     [[[self window] windowController] showWindow:self];
    }
    
    - (void)mouseExited:(NSEvent *)theEvent {
     [[[self window] windowController] myHideMethodName:self];
    }
    

    这假设您正在覆盖窗口控制器的 showWindow: 方法来执行动画或其他操作)。顺便说一句,无论你做什么,都不要寻找鼠标移动的事件。 (在您的情况下没什么大不了的,因为您的区域可能非常小,但一般来说,查找鼠标移动事件是错误的方法,因为它们会迅速淹没事件队列。使用中的跟踪区域功能Quartz Debug 看看大多数软件是如何做到的)。请记住,即使视图可能会将自身绘制为透明,它仍然会阻止您的鼠标事件通过它下面的任何内容(可能是另一个窗口或桌面等)。

    如果您想走“专业”路线,您应该能够设置 Event Taps 以基本上完​​成与跟踪区代码相同的事情。使用这条路线,您可以将窗口完全隐藏起来,这样它就不会干扰任何东西。要了解 Event Taps 的工作原理,您可能需要下载以下 2 个应用程序:

    http://brockerhoff.net/quay/

    http://pfiddlesoft.com/eventtapstestbench/

    第一个是一个很酷的示例,说明如何使用事件点击来完成一些很酷的事情(阅读帮助以查看一些更高级的功能)。 Rainer 使用事件点击来点击 Dock 以判断您何时将鼠标移到 Dock 左侧的项目上方。然后他可以显示他的自定义菜单而不是 Dock 的内置菜单。

    第二个应用程序对于检查 Quay(或 QuayMenu,实际上)对其事件点击的方式和操作是必不可少的。

    顺便说一句,事件点击 API 在 Quartz 中(以下是您将用来设置事件点击的示例):

    CFMachPortRef CGEventTapCreate (
       CGEventTapLocation tap,
       CGEventTapPlacement place,
       CGEventTapOptions options,
       CGEventMask eventsOfInterest,
       CGEventTapCallBack callback,
       void *refcon
    );
    

    我自己对事件点击的了解还不够,无法举例说明如何设置它,但这至少应该为您指明正确的方向。

    希望这会有所帮助....

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-01-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-03-05
      相关资源
      最近更新 更多