如何在 Cocoa/Obj-C 中激活自定义屏幕保护程序预览?

发布于 2024-10-10 17:13:06 字数 1481 浏览 2 评论 0原文

我创建了一个相当简单的屏幕保护程序,可以在 Mac OS 10.6.5 上运行,没有任何问题。

配置屏幕已经积累了相当多的不同选项,我正在尝试在configureSheet窗口上实现我自己的预览,以便用户(当前只有我)可以立即看到更改的效果,而无需确定并测试每个更改。

我已将 NSView 添加到 configureSheet 中,并将 Interface Builder 中的自定义类设置为我的 ScreenSaverView 子类。我知道 drawRect: 正在触发,因为我可以删除将视图清除为黑色的条件,并且我的自定义预览不再显示黑色背景。 下面是这个函数(基于互联网上的几个优秀教程):

- (void)drawRect:(NSRect)rect
{
   if ( shouldDrawBackground ) 
   {
      [super drawRect:rect];
      shouldDrawBackground = NO;
   }
   if (pausing == NO)
      [spiroForm drawForm];
}

spiroForm 类只是使用 NSBezierPath 将自身绘制到 ScreenSaverView 框架中,并且如上所述,对于实际的屏幕保护程序或内置屏幕保护程序来说不是问题。在系统偏好设置预览中。自定义预览 (configureView) 框架被传递到其本身的 init 方法中(因为它的自定义类是我的 ScreenSaverView 子类。)在将 configureSheet 对象返回到之前,在 configureSheet 中调用 -initWithFrame 方法操作系统:

[configureView initWithFrame:[configureView bounds] isPreview:YES];

也许我不必这样做?这只是我想看看绘画是否需要它。

我最终向 configureSheet 添加了一个委托,以尝试通过 windowWillBeginSheetwindowWillEndSheet 触发预览的 startAnimationstopAnimation 函数> 通知,但由于某种原因这些似乎没有被调用。该委托被声明为 NSObject,并且我在返回 configureSheet 对象之前在 configureSheet 方法中设置委托。

我已经为此工作好几天了,但一直无法找到有关操作系统如何管理 ScreenSaverView 对象的任何信息(我认为这就是我试图通过运行自己的副本来模拟的内容。

)关于如何管理这个问题的建议,或者苹果是否在我找不到的地方记录了它?这并不是屏幕保护程序工作所必需的,我只是认为这会很有趣(我也寻找了一种使用操作系统预览的方法,但在激活configureSheet时它被阻止了。)

I have created a fairly simple screensaver that runs on Mac OS 10.6.5 without issue.

The configuration screen has accumulated quite a few different options and I'm trying to implement my own preview on the configureSheet window so the user (just me, currently) can immediately see the effect of a change without having to OK and Test each change.

I've added an NSView to the configureSheet and set the custom class in Interface Builder to my ScreenSaverView subclass. I know that drawRect: is firing, because I can remove the condition for clearing the view to black, and my custom preview no longer appears with the black background.
Here is that function (based on several fine tutorials on the Internet):

- (void)drawRect:(NSRect)rect
{
   if ( shouldDrawBackground ) 
   {
      [super drawRect:rect];
      shouldDrawBackground = NO;
   }
   if (pausing == NO)
      [spiroForm drawForm];
}

The spiroForm class simply draws itself into the ScreenSaverView frame using NSBezierPath and, as mentioned, is not problematical for the actual screensaver or the built-in System Preferences preview. The custom preview (configureView) frame is passed into the init method for, um, itself (since its custom class is my ScreenSaverView subclass.) The -initWithFrame method is called in configureSheet before returning the configureSheet object to the OS:

[configureView initWithFrame:[configureView bounds] isPreview:YES];

Maybe I don't have to do that? It was just something I tried to see if it was required for drawing.

I eventually added a delegate to the configureSheet to try triggering the startAnimation and stopAnimation functions of my preview via windowWillBeginSheet and windowWillEndSheet notifications, but those don't appear to be getting called for some reason. The delegate is declared as NSObject <NSWindowDelegate> and I set the delegate in the configureSheet method before returning the configureSheet object.

I've been working on this for days, but haven't been able to find anything about how the OS manages the ScreenSaverView objects (which I think is what I'm trying to emulate by running my own copy.)

Does anybody have any suggestions on how to manage this or if Apple documents it somewhere that I haven't found? This isn't really required for the screensaver to work, I just think it would be fun (I also looked for a way to use the OS preview, but it's blocked while the configureSheet is activated.)

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

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

发布评论

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

评论(1

无人问我粥可暖 2024-10-17 17:13:06

好的,该解决方案涉及到一些“呃”时刻:

首先,我将工作表通知的委托设置为工作表本身。工作表所属的窗口会收到通知。

其次,工作表所属的那个窗口由系统偏好设置拥有,我没有看到任何方法将我的委托类设置为该窗口的委托,因此整个委托似乎不是一个可行的解决方案。

我最终为 configureSheet 子类化了 NSWindow,以便我可以通过覆盖 makeKeyWindow 和 close 方法来在预览上启动和停止动画。

- (void) makeKeyWindow
{
   if (myPreview != nil)
      if ( ! [myPreview isAnimating])
      {
         [myPreview startAnimation];
      }
   [super makeKeyWindow];
}

我还必须为预览对象本身添加 IBOutlet 并在 Interface Builder 中连接它。

仍在解决一些问题,但现在当我单击屏幕保护程序“选项”按钮时,我的configureSheet会下拉并在您设置选项时显示其自己的预览。谢什。我为了这些小细节而跳过圈子。无论如何,我喜欢它。向前和向上。

OK, there are a couple of 'duh' moments involved with the solution:

First of all, I was setting the delegate for the sheet notifications to the sheet itself. The window that the sheet belongs to gets the notifications.

Secondly, that very window that the sheet belongs to is owned by System Preferences, I don't see any way to set my delegate class as a delegate to that window, so the whole delegate thing doesn't appear to be a viable solution.

I ended up subclassing NSWindow for the configureSheet so that I could start and stop animation on my preview by over-riding the makeKeyWindow and close methods.

- (void) makeKeyWindow
{
   if (myPreview != nil)
      if ( ! [myPreview isAnimating])
      {
         [myPreview startAnimation];
      }
   [super makeKeyWindow];
}

I also had to add an IBOutlet for my preview object itself and connect it in Interface Builder.

Still working out a couple of issues, but now when I click on my screensaver Options button, my configureSheet drops down and displays its own preview while you set options. Sheesh. The hoops I jump through for these little niceties. Anyway, I like it. Onward and upward.

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