在没有Cocoa的情况下创建OS X窗口

时间:2013-08-28 23:19:19

标签: macos cocoa nswindow

出于好奇,我开始试图弄清楚Cocoa如何创造窗户。我发现的所有库都以Cocoa为核心,我似乎无法在网上找到任何东西。

我尝试使用Carbon,但它没有做任何事情,只是给我一个关于未被声明的函数的警告。

我想我真正想要的是一种与Quartz Compositor接口的方式。

有没有办法让我看一下真正的窗口创建代码?

2 个答案:

答案 0 :(得分:11)

我没有太多细节可以给你,但我可以指出你的方向。

有一个级别,这是Quartz Window Services。这就是NSWindow和Carbon的Window Manager所基于的。

即使在公共API中,偶尔也会偷看。您可以ask any window for its window number(以及likewise in Carbon),并且可以使用the public Quartz Window Services API中的任何内容。但这并没有让你走得太远:除了截图之外,你无法做到这一点。

如果你要用Quartz创建一个窗口,那么它(可能 - 我从未尝试过这个)会是空白的。标题栏和背景分别绘制。

要做到这一点,NSWindow有第二个视图ivar,用于称为框架视图的视图,可能使用HITheme。 (令人惊讶的数量甚至是公开的 - 例如,HIThemeDrawWindowFrame它是公开的!)窗口管理器可能会做类似的事情。

[已添加] Here's a test app that draws a window using HITheme(在常规NSView中)。

Screenshot of the real window containing the fake window.

正如您所看到的,它并不完美:除了其他方面,阴影半径和标题栏高度都是硬编码的。但这是一个开始,并且是一个体面的示范。

快速摘要:

  • HIThemeDrawWindowFrame目前只是绘制标题栏和红绿灯。没有标题文本(它不带字符串,因此无法绘制它),也没有窗口背景,框架轮廓或阴影。
  • 要绘制窗口背景,请使用HIThemeSetFill将窗口背景画笔设置为上下文的填充颜色。然后,使用HIThemeGetWindowShape获取窗口结构区域的HIS形状(注意:尽管名称,您需要CFRelease从中得到的形状),然后使用此形状作为上下文的当前路径HIShapeReplacePathInCGContext。然后,CGContextFillPath,正常。
  • 如果您想在窗口后面留下阴影,则需要将所有上述内容包含在transparency layer中。特别是,如果你不这样做,那么红绿灯会在每个按钮后面留下自己的影子,看起来非常奇怪。
  • 要绘制标题文字,请使用HIThemeDrawTextBox。您应该能够使用HIThemeGetWindowShape获取标题文字形状,但是,从Lion开始,它会返回一个空的形状。

答案 1 :(得分:1)

Quartz Window Services API还有一个私有部分,它定义了以下功能:

// Creating Windows
extern CGError CGSNewWindowWithOpaqueShape(CGSConnection cid, int always2, float x, float y, CGSRegionRef shape, CGSRegionRef opaqueShape, int unknown1, void *unknownPtr, int always32, CGSWindowID *outWID);
extern CGError CGSReleaseWindow(CGSConnection cid, CGSWindowID wid);
extern CGContextRef CGWindowContextCreate(CGSConnection cid, CGSWindowID wid, void *unknown);

您可以在undocumented goodness project记录这些和更多功能(不确定这里是否记录了整个私有API)。