3

好奇心から、Cocoa がウィンドウを作成する方法を理解しようと試み始めました。私が見つけたすべてのライブラリは、コアで Cocoa を使用しており、オンラインで何かを見つけることができないようです。

Carbon を使用してみましたが、何もしませんが、関数が宣言されていないという警告が表示されます。

私が本当に探しているのは、Quartz Compositor とやり取りする方法だと思います。

実際のウィンドウ作成コードを見る方法はありますか?

4

2 に答える 2

11

詳しいことは言えませんが、ご案内できるかもしれません。

1 つ下のレベルは、Quartz Window Services です。これは、NSWindow と Carbon の Window Manager の両方が基づいているものです。

パブリック API であっても、ときどき覗き見します。任意のウィンドウにそのウィンドウ番号(および同様に Carbon ) を尋ねることができます。これにより、公開されている Quartz Window Services APIで何でも使用できます。ただし、これではあまり効果がありません。スクリーンショットを撮る以外にできることはあまりありません。

ただし、Quartz でウィンドウを作成する場合、(おそらく — 私はこれを試したことはありません) 空白になります。タイトル バーと背景は別々に描画されます。

これを行うために、NSWindow には、おそらく HITheme を使用するフレーム ビューと呼ばれるビュー用の 2 番目のビュー ivar があります。(驚くべきことに、公開されているものもたくさんあります。たとえば、HIThemeDrawWindowFrame!があり、公開されています! ) Window Manager は、おそらく同様のことを行います。

[追加] 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 に答える