3

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

我尝试使用 Carbon,但它什么也没做,只是给我一个关于未声明函数的警告。

我想我真正想要的是一种与 Quartz Compositor 交互的方式。

有什么办法让我看看真正的窗口创建代码?

4

2 回答 2

11

我没有太多细节可以告诉你,但我或许能给你指明一个方向。

向下一层,即 Quartz Window Services。这就是 NSWindow 和 Carbon 的 Window Manager 的基础。

它偶尔会偷看,即使在公共 API 中也是如此。您可以向任何窗口询问其窗口编号同样在 Carbon 中),然后您可以使用公共 Quartz Window Services API 中的任何内容。但是,这并不能让您走得太远:除了截屏之外,您无能为力。

但是,如果您要使用 Quartz 创建一个窗口,它(可能——我从未尝试过)会是空白的。标题栏和背景是分开绘制的。

为此,NSWindow 为称为框架视图的视图提供了第二个视图 ivar,它可能使用了 HITheme。(令人惊讶的数量甚至是公开的——例如,有一个HIThemeDrawWindowFrame而且它是公开的!)窗口管理器可能会做类似的事情。

[已添加]这是一个使用 HITheme (在常规 NSView 内部)绘制窗口的测试应用程序。

包含假窗口的真实窗口的屏幕截图。

如您所见,它并不完美:阴影半径和标题栏高度是硬编码的。但这是一个开始,也是一个体面的示范。

快速总结:

  • HIThemeDrawWindowFrame目前只绘制标题栏和红绿灯。没有标题文本(它不需要字符串,因此无法绘制),也没有窗口背景、框架轮廓或阴影。
  • 要绘制窗口背景,请使用 将窗口背景画笔设置为上下文的填充颜色HIThemeSetFill。然后,使用获取窗口结构区域的 HIShape HIThemeGetWindowShape(注意:尽管有名称,但您需要从中CFRelease获得的形状),然后使用HIShapeReplacePathInCGContext. 然后,CGContextFillPath,像往常一样。
  • 如果你想在你的窗口后面有一个阴影,你会想把上面的所有东西都包裹在一个透明层中。特别是,如果你不这样做,红绿灯会在每个按钮后面都有自己的阴影,这看起来很奇怪。
  • 要绘制标题文本,请使用HIThemeDrawTextBox. 您应该能够使用 获取标题文本形状HIThemeGetWindowShape,但是,对于 Lion,它返回一个空形状。
于 2013-08-29T06:44:15.457 回答
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)。

于 2015-01-13T19:44:33.980 回答