共用方式為


基本概念

注意

針對 Windows 10 上的應用程式,我們建議使用 Windows.UI.Composition API,而不是 DirectComposition。 如需詳細資訊,請參閱 使用視覺層將傳統型應用程式現代化。

本主題提供 Microsoft 的 DirectComposition 基本概念的總覽。 其中包含下列各節:

組成

DirectComposition 會將 組合 定義為一組位陣圖集合,這些位圖會套用各種轉換、效果和動畫,以在應用程式 UI 中產生視覺結果。 DirectComposition 僅適用於點陣圖內容;它不支援向量或文字。 DirectComposition 不提供位圖內容。 相反地,它提供介面,讓使用者可以使用 D2D、DXGI 繪製,或上傳自己的紋理內容。

DirectComposition 應用程式會建立兩組對象來撰寫場景:組合在一起的位陣圖,以及定義點陣圖之間空間關聯性的視覺效果。 如需 DirectComposition 所支援之點陣圖物件的詳細資訊,請參閱 Bitmap 物件。

圖像

Visuals(或 視覺物件)是 DirectComposition 的基本元素。 它們是您在應用程式 UI 中用來建立組合和動畫的基本建置組塊。

在程式設計術語中,視覺效果是具有一組屬性的物件,並公開您用來設定屬性值的介面。 視覺物件的 Content 屬性會將特定位圖關聯到視覺物件上,而其他屬性則控制 DirectComposition 在畫面上呈現時如何放置及操作視覺物件。

如需詳細資訊,請參閱 Visual的屬性。

視覺樹

DirectComposition 會從稱為 可視化樹狀結構的視覺物件階層式集合建立組合。 樹狀結構的根視覺稱為 根視覺,並且它可以有一個或多個 子視覺 與其相關聯。 子視覺效果可以有自己的一或多個子視覺效果。 任何具相關子視覺效果的視覺效果稱為 父視覺效果,而共用相同父視覺效果的所有子視覺效果稱為 同層級視覺效果。 特定視圖及其所有子項視圖稱為 視圖子樹

視覺元素在樹中的位置有助於判斷其相對於組成中其他視覺元素的屏幕位置和迭置順序。 根視覺效果的位置相對於呈現組合的目標視窗客戶區域的左上角。 所有子視覺效果皆以其父視覺效果的左上角為基準(或由 TransformParent 屬性指定的視覺效果),並總是在 z 軸順序中出現在父系之前。

下圖顯示視覺效果的組成,以及用來產生組合的可視化樹狀結構。 Visual 1 是根視覺效果,也是子Visuals 2和3的父系,也就是同層級視覺效果。 Visual 3 有自己的兩個子視覺效果,Visuals 4 和 5。 Visuals 3 到 5 一起組成視覺子樹。

視覺元素及其對應的視覺樹組合

父視覺效果會維護其子視覺效果的已排序列表。 當同層級視覺效果定位成彼此重疊時,DirectComposition 會根據父視覺效果的子系列表中出現的順序,設定同層級的迭置順序。 在清單中出現較後的同層級會排在所有較早出現的同層級之前。 下圖顯示重疊子視覺元素的迭置順序。

重疊子視覺效果的迭置順序

視覺效果對象的屬性

視覺物件公開一組屬性,讓您能夠設定用於視覺對象的點陣圖內容,並控制 DirectComposition 如何定位和操控該視覺內容。 下列各節將詳細說明每個屬性。

內容屬性

視覺效果的 Content 屬性會指定與視覺效果相關聯的點陣圖內容。 這是 DirectComposition 在組合中包含視覺效果時所使用的點陣圖。

您可以呼叫 IDCompositionVisual::SetContent 方法來設定視覺效果的 Content 屬性。

如需 DirectComposition 所支援之點陣圖內容類型的詳細資訊,請參閱 位圖物件

Clip 屬性

視覺效果的 Clip 屬性會指定一個稱為 剪輯區域 的矩形區域(或 剪輯矩形)。 呈現視覺效果時,只會顯示落在裁剪區域內的視覺效果部分,而任何延伸在裁剪區域外的內容都會裁剪(也就是不會顯示)。 DirectComposition 支援具有圓角或平方角的裁剪區域。

您可以呼叫 IDCompositionVisual::SetClip 方法來設定視覺效果的 Clip 屬性。

如需詳細資訊,請參閱 裁剪

BorderMode 屬性

BorderMode 屬性會指定如何撰寫與這個視覺效果相關聯的點陣圖和剪輯邊緣,或在這個視覺效果根目錄的子樹中的視覺效果。

框線模式會影響當點陣圖轉換時,位圖邊緣的組成方式,使邊緣與整數座標不對齊。 它也會影響內容在具有圓角之剪輯的角落裁剪的方式,以及轉換的剪輯邊緣,讓邊緣與整數座標不對齊。

如需詳細資訊,請參閱 IDCompositionVisual::SetBorderMode

BitmapInterpolationMode 屬性

BitmapInterpolationMode 屬性會告訴 DirectComposition 如何在轉換點陣圖時撰寫位圖,如此一來,螢幕上的圖元與像素之間就沒有一對一的對應。

您可以呼叫 IDCompositionVisual::SetBitmapInterpolationMode 方法來設定視覺效果的 BitmapInterpolationMode 屬性。

CompositeMode 屬性

CompositeMode 屬性會告知 DirectComposition 如何將視覺效果的點陣圖內容與轉譯目標混合。 如需所支援複合模式的描述,請參閱 DCOMPOSITION_COMPOSITE_MODE

您可以呼叫 IDCompositionVisual::SetCompositeMode 方法來設定視覺效果的 CompositeMode 屬性。

OffsetX 和 OffsetY 屬性

OffsetX 和 OffsetY 屬性會告訴 DirectComposition 水平和垂直放置視覺效果的位置。 他們會定義計算視覺效果之所有轉換和效果的二維固定位置。

對於根視覺效果,OffsetX 和 OffsetY 屬性會定義相對於裝載視覺效果之視窗左上角之點的 x 座標和 Y 座標。 針對子視覺效果,座標會相對於父系的左上角,或者,如果指定 TransformParent 屬性,則為指定視覺效果的左上角。 呈現視覺效果時,其位置會讓視覺效果的左上角與指定的座標重合。

您可以呼叫 IDCompositionVisual::SetOffsetXSetOffsetY 方法來設定視覺效果的 OffsetX 和 OffsetY 屬性。

效果屬性

Effect 屬性可讓您指定效果或效果群組,以修改視覺效果及其子樹的組成方式。 例如,您可以指定控制視覺效果不透明度的效果,以各種方式將視覺效果與其他點陣圖混合,並對視覺效果應用透視變換。

您可以呼叫 IDCompositionVisual::SetEffect 方法來設定視覺效果的 Effect 屬性。

如需詳細資訊,請參閱 效果

轉換屬性

Transform 屬性會指定 DirectComposition 要在視覺效果上執行的二維(2D)轉換,或是一組 2D 轉換。 轉換(或轉換)是一項作業,可修改視覺效果相對於其父系的座標系統,或相對於 TransformParent 屬性所指定的視覺效果。 您可以使用轉換來改變視覺效果的位置、大小或本質,方法是將視覺效果移至另一個位置(翻譯),使其變大或更小(縮放)、旋轉(旋轉)、扭曲其形狀(扭曲)等等。

您可以呼叫 IDCompositionVisual::SetTransform 方法來設定視覺效果的 Transform 屬性。

如需詳細資訊,請參閱 轉換

TransformParent 屬性

視覺效果的座標系統是由 OffsetX、OffsetY 和 Transform 屬性修改。 一般而言,這些屬性會定義視覺效果相對於其直接父系的座標系統。 若要使用父系以外的某些視覺效果做為子視覺效果座標系統的基礎,請使用 TransformParent 屬性將不同的視覺效果指定為轉換用途的「父系」。

您可以呼叫 IDCompositionVisual::SetTransformParent 方法來設定視覺效果的 TransformParent 屬性。

裝置物件

若要使用 DirectComposition,您必須建立及操作各種元件物件模型(COM)物件。 您需要建立的第一個物件是 DirectComposition 裝置物件,因為它可作為建立組合中使用的所有其他對象的處理站。

您可以呼叫 DCompositionCreateDevice 函式來建立裝置物件,此函式會傳回 IDCompositionDevice 介面指標。 這個介面會公開一組方法,讓您用來建立視覺物件、剪輯對象、動畫物件、轉換物件、效果物件等等。

裝置物件除了做為建立其他對象的處理站之外,還有一個其他用途。 它會公開一個方法,稱為 Commit,該方法將視覺樹傳遞至 DirectComposition 進行處理。 如需詳細資訊,請參閱 交易式組合

請記住,雖然您可以在應用程式中建立多個裝置對象的實例,但您在特定組合中使用的所有物件都必須由相同的裝置物件建立,但有一個例外:您可以在相同的可視化樹狀結構中結合來自不同裝置對象的視覺物件。 當您這樣做時,DirectComposition 會以通常的方式處理視覺層次結構,但樹狀結構中特定視覺對象的變更只有在對建立該視覺對象的裝置物件呼叫 Commit 方法時才會生效。

在相同的可視化樹狀結構中使用來自不同裝置的視覺效果,允許多個執行緒建立及操作單一可視化樹,同時維持兩個可供非同步提交變更的獨立裝置。 如需詳細資訊,請參閱 跨裝置視覺樹狀結構

組合目標視窗

可視化樹狀結構必須系結至視窗,才能在螢幕上顯示任何樹狀結構的視覺效果。 稱為 組合目標視窗視窗的視窗可以是最上層視窗或子視窗。 此外,組合目標視窗可以是分層視窗;也就是說,它可以有 WS_EX_LAYERED 視窗樣式。

DirectComposition 可讓應用程式將最多兩個視覺樹狀結構系結至每個視窗。 視覺樹狀圖包含一個是覆蓋在視窗本身之上,但位於所有子視窗後面的,另一個則覆蓋在視窗及其子視窗之上。 換句話說,每個視窗都有四個概念層,而且所有圖層都會裁剪到目標視窗的可見區域。 下圖顯示視窗的四個概念層。

視窗的概念層

交易式組合

DirectComposition 使用交易式模型,您可以建立一組批次的視覺效果變更,然後將變更提交至 DirectComposition 一次性處理。 您可以修改相同的 DirectComposition 視覺效果物件,並在需要時多次提交變更。 當桌面視窗管理員 (DWM) 挑選批次時,它會挑選所有擱置中的批次,並依認可的順序將它們套用至下一個框架。

單一提交中的所有變更都保證會套用至單一幀。 由於 DWM 會針對每個畫面收集批次一次,因此您只能在每個畫面修改任何特定物件一次。 後續修改不同物件的提交也可能套用至目前的畫面,但 DirectComposition 不保證變更會發生在同一個畫面中。

IDCompositionSurface::BeginDrawIDCompositionSurface::EndDraw 方法可讓您同步處理轉譯更新與視覺更新。 例如,您可以呼叫 IDCompositionSurface::BeginDraw、更新視覺效果的 OffsetX 和 Clip 屬性、呼叫 IDCompositionDevice::Commit、使用 Microsoft DirectX 繪製內容,然後呼叫 IDCompositionSurface::EndDraw。 在此情況下,Microsoft DirectComposition 可確保位圖內容和視覺效果屬性同時更新。

批處理

您可以將多個變更提交至相同的視覺效果,或在同一個階段內對不同視覺效果進行多個變更。 在相同畫面內對相同視覺效果進行多個變更時,請記住下列幾點:

  • 如果您對視覺效果的相同屬性進行多個變更,則只會套用最後一個變更。 例如,如果您將不透明度設定為 0,然後將 不透明度設定為 0.5,最後設定為 1.0,則只會將不透明度 1.0 套用至視覺效果。

  • 如果您變更相同視覺效果的多個屬性,DirectComposition 會先將變更套用至視覺效果,然後再套用至任何子視覺效果。 不論您指定屬性的順序為何,屬性都會依下列順序套用:

    1. 抵消
    2. 變換
    3. 剪輯
    4. 影響

    下圖顯示將四個屬性全部套用至視覺效果的結果。

    套用所有四個屬性至視覺

    請記住,所有變更都會同時套用至相同框架中的視覺。 這表示,從用戶的觀點來看,視覺效果的變更會立即發生。

  • 針對 Transform 屬性,您可以使用 IDCompositionDevice::CreateTransformGroup 建立一組轉換,以一次套用至視覺效果。 DirectComposition 會依您指定的順序套用轉換。

  • 針對 Effect 屬性,您可以使用 IDCompositionEffectGroup 套用一組效果。 DirectComposition 會依您指定的順序套用效果。 此外,在套用目前視覺效果中的所有 3D 轉換之後,3D 透視變換會導致視覺樹扁平化。 這有助於確保產生的視覺效果盡可能接近 3D。

同步

您的應用程式可以同時從多個線程呼叫 DirectComposition。 順序呼叫的執行順序可以保證,但並行呼叫的執行順序無法保證。 例如,如果線程 A 會同時修改視覺效果,而線程 B 會同時認可批次,則不會定義該視覺變更是否包含在認可的批次中,或是否啟動新的批次。 另一方面,如果您的應用程式使用其他同步處理機制來確保在另一個方法之前呼叫一個方法,DirectComposition 會接受呼叫順序,並處理它們,就像這兩個呼叫都是以單一線程的順序發出一樣。

跨裝置的視覺樹狀結構

DirectComposition 物件不是線程系結;您可以使用多個線程來修改同一組物件。 不過,在共用相同的裝置物件時,請注意下列問題。

  • 這兩個線程都必須能夠呼叫 IDCompositionDevice::Commit。 如果只有其中一個執行緒呼叫 IDCompositionDevice::Commit,另一個執行緒就無法將其任何變更提交至 DirectComposition。
  • 如果一個線程呼叫 idCompositionDevice::Commit,而另一個線程仍在進行屬於相同交易的變更,則交易行為可能會遺失。

如果您需要將多個同時的事務提交至 DirectComposition,則必須使用多個裝置物件,這些物件可能來自多個執行緒。 在此案例中,裝置物件會共用相同的可視化樹狀結構,而每個裝置物件都會提交自己的交易。

下圖顯示兩個裝置對象共用的可視化樹狀結構。 視覺效果 1、2、4 和 5 是由一個裝置或另一個裝置所擁有,但視覺 3 是由兩個裝置共用,因此可用來將兩個子樹連接到單一較大的可視化樹狀結構。 共用可視化樹狀結構讓兩個裝置能從兩個不同的執行緒異步操作。

兩個裝置共用的可視化樹狀結構

為了說明在兩個裝置之間共用可視化樹狀結構的實用性,請考慮啟用低延遲觸控輸入的架構。 此架構可以使用兩個線程,一個處理大部分 UI 工作,另一個線程專用於處理觸控輸入事件。 觸控線程會根據使用者輸入手勢更新特定視覺效果的轉換。 藉由更新轉換矩陣,觸控執行緒可以讓該視覺效果下的整個子樹跟隨使用者的手指,隨著使用者執行多點觸控手勢而放大或縮小等。 UI 執行緒會保留大部分組合樹的擁有權,而觸控執行緒只擁有被標記為異步觸控回應的少數視覺效果。 下圖顯示這類組合樹狀結構的簡化版本:

ui 線程與觸控線程之間共用的可視化樹狀結構

一般而言,UI 線程只會修改它獨佔擁有的視覺效果,而觸控線程只會修改共用視覺效果。 唯一的例外狀況會在建立或終結啟用觸控功能的子樹時發生。

IDCompositionSurface::BeginDraw

IDCompositionSurface::EndDraw

IDCompositonDevice::Commit

DirectComposition 概念