重新实现 Mac OS X Dock 的自动隐藏

发布于 2024-09-27 05:25:37 字数 242 浏览 4 评论 0原文

我正在尝试用 Objective-C 制作一个服务器监视器,其行为有点像 OS X 中的扩展坞。我希望当鼠标移动到屏幕的一侧时它可以从屏幕的一侧滑动,有点像自动隐藏打开时的坞站。我不知道从哪里开始。

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

I'm trying to make a server monitor in Objective-C, that behaves kind of like the dock in OS X. I'm hoping to have it slide from the side of the screen when the mouse is moved to a side of the screen, kind of like the dock when auto hide is on. I'm not sure where to start though..

I'm guessing I need to have a window with a NSBorderlessWindowMask mask, but after that I'm at a loss. Do I just have 1 pixel of that window showing, and wait for a mouseOver event, or is that just a hacky solution for something that can be done reasonably? How would I check for a mouse over event if that's the best way to do it?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

零度℉ 2024-10-04 05:25:37

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

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

如果您采用“个人项目”方式,您可以保留显示窗口的 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 看看大多数软件是如何做到的)。请记住,即使视图可能将自身绘制为透明,它仍然会阻止您的鼠标事件到达其下方的任何内容(可能是另一个窗口或桌面等)。

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

http://brockerhoff.net/quay/< /a>

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
);

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

希望这有帮助......

You have the right idea, I think. Keep in mind though that, depending on what you want to do, borderless windows are not the easiest thing to work with (they can be tricky, especially with the complexities that things like Spaces and Exposé may add).

If this is just a personal project, you could probably get away with a one pixel edge of the window showing. If this is a professional project, I would recommend looking into using Event Taps (more on that later).

If you go the "personal project" way, you could leave 1 px edge of the window showing, use a custom NSView subclass that would draw itself as transparent and set up an NSTrackingArea to inform you of mouseEntered: events.

To draw a transparent area, you could do something like this in drawRect:

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

To set up a tracking area, do this in the awakeFromNib in your view subclass:

- (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];
}

This assumes you're overriding the window controller's showWindow: method to do an animation or whatever). By the way, whatever you do, DO NOT look for mouse moved events. (Not a big deal in your case, since your area will likely be very small, but in general, looking for mouse moved events is the wrong way to do it, as they can quickly flood the event queue. Use the tracking area feature in Quartz Debug to see how most software does it). Keep in mind that even though the view may draw itself transparent, it will still prevent your mouse events from going through to whatever is underneath it (could be another window or the Desktop, etc.).

If you want to go the "pro" route, you should be able to set up Event Taps to basically accomplish the same thing the tracking area code does. With this route, you can have the window completely hidden so it doesn't interfere with anything. To understand how Event Taps work, you might want to download the following 2 apps:

http://brockerhoff.net/quay/

http://pfiddlesoft.com/eventtapstestbench/

The first is a cool example of how you can use event taps to accomplish some cool stuff (read the Help to see some more advanced features). Rainer uses event taps to tap the Dock to figure out when you move your mouse overtop of the items in the left side of the Dock. He can then show his custom menus instead of the Dock's built-in menus.

The second app will be indispensable in examining how and what Quay (or QuayMenu, really) is doing to its event taps.

BTW, the event taps API is in Quartz (the following is an example of what you would use to set up an event tap):

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

I don't know enough about event taps myself to give an example of how to set it up, but that should at least point you in the right direction.

Hope this helps....

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文