<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ??一站式輕松地調用各大LLM模型接口,支持GPT4、智譜、豆包、星火、月之暗面及文生圖、文生視頻 廣告
                WINDOWS 10 2015 年特別版 # 圖形和動畫 - Windows 組合支持 10 倍縮放 作者?[Kenny Kerr](https://msdn.microsoft.com/zh-cn/magazine/mt149362?author=Kenny+Kerr)?| Windows 2015 Windows 組合引擎,又稱桌面窗口管理器 (DWM),為 Windows 10 提供了新 API。DirectComposition 是組合的主要接口,但是作為經典 COM API,它對于一般水平的應用開發人員而言很大程度上是難以訪問的。全新 Windows 組合 API 基于 Windows 運行時 (WinRT) 構建,并且通過將 Direct2D 和 Direct3D 提供的即時模式圖形領域與如今動畫及效果有很大改進的保留可視化樹進行混合,為高性能渲染奠定了基礎。 我首次撰寫 DWM 文章要追溯到 2006 年,當時 Windows Vista 還在測試中 ([goo.gl/19jCyR](http://goo.gl/19jCyR))。它允許您控制給定窗口模糊效果的范圍,并創建與桌面完美混合的自定義鑲邊。圖 1?顯示了 Windows 7 中這一實現的高度。可以使用 Direct3D 和 Direct2D 制作硬件加速渲染,從而為您的應用打造絕妙的視覺效果 ([goo.gl/IufcN1](http://goo.gl/IufcN1))。您甚至可以將 GDI 和 USER 控件的舊領域與 DWM 混合 ([goo.gl/9ITISE](http://goo.gl/9ITISE))。然而,任何敏銳的觀察者都會說 DWM 可以提供的更多 — 更多。Windows 7 中的 Windows Flip 3D 功能就是有力的佐證。 ![](https://box.kancloud.cn/2016-01-08_568f406e112fd.png)? 圖 1 Windows Aero Windows 8 為 DWM 引入稱為 DirectComposition 的新 API,它的名稱正是向激發其設計靈感的經典 COM API 的 DirectX 系列致敬。DirectComposition 開始向開發人員提供比 DWM 能夠提供的畫面更加清晰的畫面。此外,它還提供了改進的術語。DWM 確實是 Windows 組合引擎,能夠在 Windows Vista 和 Windows 7 中制作炫麗的效果,因為它從根本上改變了桌面窗口的渲染方式。默認情況下,組合引擎為每個頂層窗口創建了重定向設計面。我在 2014 年 6 月專欄中對此進行了詳細介紹 ([goo.gl/oMlVa4](http://goo.gl/oMlVa4))。這些重定向設計面構成了可視化樹的一部分,并且 DirectComposition 允許應用利用這一相同技術為高性能圖形提供輕量保留模式 API。DirectComposition 提供了可視化樹與設計面管理,允許應用將效果與動畫的制作任務轉移給組合引擎。我在 2014 年 8 月 ([goo.gl/CNwnWR](http://goo.gl/CNwnWR)) 和 9 月專欄 ([goo.gl/y7ZMLL](http://goo.gl/y7ZMLL)) 中介紹了這些功能。我甚至制作了有關使用 DirectComposition for Pluralsight 實現高性能渲染的課程 ([goo.gl/fgg0XN](http://goo.gl/fgg0XN))。 Windows 8 首次推出 DirectComposition,以及對 API 其余 DirectX 系列的一些顯著改進,而且,它還引領了一個全新的 Windows API 時代,將永遠改變開發人員看待操作系統的方式。Windows 運行時的推出舉世矚目。Microsoft 預示了全新的構建應用和訪問操作系統服務的方式,這將最終終結所謂的 Win32 API,Win32 API 一直以來主導著構建應用和與操作系統交互的方式。Windows 8 起步艱難,但是 Windows 8.1 修復了很多問題,并且 Windows 10 如今提供了更為全面的 API,將滿足對構建適用于 Windows 的一級應用(甚至是重要的應用)感興趣的更多開發人員。 Windows 10 于 2015 年 7 月推出,預告了尚未準備制作的新組合 API。其仍會有變動,因此不能在提交至 Windows 應用商店的通用 Universal Windows 應用中使用。這也正是因為現在可進行制作的組合 API 發生了顯著的變化,并且是向好的方向轉變。此 Windows 10 更新也是有史以來第一次同一組合 API 在所有規格的產品上可用,這也進一步證明了通用 Windows 平臺的通用性。無論您面向的是多顯示器的桌面平臺,還是置于口袋中的小巧智能手機,這一組合均采用相同的工作方式。 當然,對于 Windows 運行時,每個人都喜歡的一個優點就是,它最終兌現了 Windows 通用語言運行時的承諾。如果您更喜歡用 C# 編碼,則可以通過內置于 Microsoft .NET Framework 的支持直接使用 Windows 運行時。如果與我一樣,您更喜歡使用 C++,則可以使用沒有中間媒介或者成本高昂的抽象化的 Windows 運行時。Windows 運行時構建于 COM 而非 .NET,因此非常適于使用 C++。我將使用針對 Windows 運行時、標準 C++ 語言投射的現代 C++ ([moderncpp.com](http://moderncpp.com/)),但是您可以選擇自己喜歡的語言,因為不管怎樣,API 都是相同的。我也會提供一些 C# 示例來說明 Windows 運行時如何無縫支持不同的語言。 Windows 組合 API 遠離其 DirectX 根。DirectComposition 提供了一個設備對象(效仿 Direct3D 和 Direct2D 設備),而新的 Windows 組合 API 則以排序器開始。但是,其目的相同,都是充當組合資源的工廠。除此之外,Windows 組合與 DirectComposition 非常類似。有一個代表窗口及其可視化樹之間關系的組合目標。您離視覺對象越近,差異就越明顯。DirectComposition 視覺對象具有提供某種位圖的內容屬性。位圖為以下三項之一:組合設計面、DXGI 交換鏈或另一窗口的重定向設計面。一個典型的 DirectComposition 應用程序由視覺對象和設計面構成,設計面充當不同視覺對象的內容或位圖。如圖 2所示,組合可視化樹稍微有點怪異。新的視覺對象沒有內容屬性,而是使用組合畫筆渲染。這就造就了更靈活的抽象化。雖然畫筆只能像以前那樣渲染位圖,但至少從概念上而言,可以更高效地創建純色畫筆并可定義更詳盡的畫筆,采用的方式與 Direct2D 提供可視作圖像的效果的方式一樣。合適的抽象化非常重要。 ![](https://box.kancloud.cn/2016-01-08_568f406e3d503.png)? 圖 2 Windows 組合可視化樹 讓我們看一些實際示例,來說明這一切的工作原理并讓您大致了解一下可能的情況。同樣,您可以選擇自己喜歡的 WinRT 語言投射。您可以使用現代 C++ 創建排序器,如下所示: ~~~ using namespace Windows::UI::Composition; Compositor compositor; ~~~ 同樣,您可以使用 C# 執行相同的操作: ~~~ using Windows.UI.Composition; Compositor compositor = new Compositor(); ~~~ 您甚至可以使用 C++/CX 提供的更炫麗的語法: ~~~ using namespace Windows::UI::Composition; Compositor ^ compositor = ref new Compositor(); ~~~ 從 API 的角度看,所有這些都是相同的,僅僅在語言投射方面有一些差異。如今,您基本上可以采用兩種方式編寫通用 Windows 應用。或許最常見的方法是使用操作系統的 Windows.UI.Xaml 命名空間。如果 XAML 對于您的應用沒有那么重要,您還可以直接使用基礎應用模型(不依賴于 XAML)。我在 2013 年 8 月專欄 ([goo.gl/GI3OKP](http://goo.gl/GI3OKP)) 中介紹了 WinRT 應用模型。如果使用這種方法,您只需以最小程度實現 IFrameworkView 和 IFrameworkViewSource 接口即可直接開始操作了。圖 3?在提供了一個使用 C# 的基本大綱,可方便您入手。Windows 組合還提供了與 XAML 的深入集成,但是讓我們先看看簡單的無 XAML 的應用吧,因為它可以提供一個更簡單的場所來了解組合。我將在本文稍后部分再返回到 XAML。 圖 3 C# Windows 運行時應用模型 ~~~ using Windows.ApplicationModel.Core; using Windows.UI.Core; class View : IFrameworkView, IFrameworkViewSource { ? static void Main() ? { ??? CoreApplication.Run(new View()); ? } ? public IFrameworkView CreateView() ? { ???? return this; ? } ? public void SetWindow(CoreWindow window) ? { ??? // Prepare composition resources here... ? } ? public void Run() ? { ??? CoreWindow window = CoreWindow.GetForCurrentThread(); ??? window.Activate(); ??? window.Dispatcher.ProcessEvents(CoreProcessEventsOption.ProcessUntilQuit); ? } ? public void Initialize(CoreApplicationView applicationView) { } ? public void Load(string entryPoint) { } ? public void Uninitialize() { } } ~~~ 它位于應用的 SetWindow 方法(參見圖 3)內,其中應構造排序器。事實上,這是應用生命周期中最早發生這種情況的點,因為排序器依賴窗口的調度程序,而這是窗口和調度程序最終都存在的點。然后,可通過創建組合目標在排序器與應用視圖之間建立一種關系: ~~~ CompositionTarget m_target = nullptr; // ... m_target = compositor.CreateTargetForCurrentView(); ~~~ 應用保持組合目標處于活動狀態很重要,所以請務必使其成為 IFrameworkView 實現的成員變量。正如我先前所說,組合目標代表窗口或視圖與其可視化樹之間的關系。您能對組合目標執行的操作就是,設置根視覺對象。通常,這將會是一個容器視覺對象: ~~~ ContainerVisual root = compositor.CreateContainerVisual(); m_target.Root(root); ~~~ 在此我使用的是 C++,其缺少屬性語言支持,因此根屬性被投射為訪問器方法。C# 與屬性語法的新增部分非常相似: ~~~ ContainerVisual root = compositor.CreateContainerVisual(); m_target.Root = root; ~~~ DirectComposition 只提供了一種視覺對象,它支持各種設計面來表示位圖內容。Windows 組合提供了表示各種視覺對象、畫筆和動畫的小類層次結構,然而只有一種設計面,且只能使用 C++ 創建,因為它屬于供 XAML 等框架以及更有經驗的應用開發人員使用的 Windows 組合 interop API。 視覺對象類層次結構如圖 4?所示。CompositionObject 是由排序器支持的資源。所有組合對象可能已為其屬性設置動畫。視覺對象提供了大量屬性,用于控制視覺對象相對位置、外觀、裁剪和渲染選項等許多方面。它包含轉換矩陣屬性,以及用于縮放和旋轉的快捷方式。這的確是一個非常強大的基類。相反,ContainerVisual 是一個相對簡單的類,只添加了 Children 屬性。雖然您可以直接創建容器視覺對象,但是 SpriteVisual 添加了關聯畫筆的功能,以便視覺對象可以確實地渲染其自己的像素。 ![](https://box.kancloud.cn/2016-01-08_568f406e55e13.png) 圖 4 組合視覺對象 給定一個根容器視覺對象,我可以創建任意數量的子視覺對象: ~~~ VisualCollection children = root.Children(); ~~~ 這些還可以是容器視覺對象,但是他們更可能是子畫面視覺對象。我可以使用 C++ 中的 for 循環添加三個視覺對象作為根視覺對象的子項: ~~~ using namespace Windows::Foundation::Numerics; for (unsigned i = 0; i != 3; ++i) { ? SpriteVisual visual = compositor.CreateSpriteVisual(); ? visual.Size(Vector2{ 300.0f, 200.0f }); ? visual.Offset(Vector3{ 50 + 20.0f * i, 50 + 20.0f * i }); ? children.InsertAtTop(visual); } ~~~ 您可以在圖 5?中輕松想象應用窗口,然而該代碼不會導致渲染任何內容,因為沒有畫筆與這些視覺對象關聯。畫筆類層次結構如圖 6?所示。CompositionBrush 只是畫筆的一個基類,不提供其自己的任何功能。CompositionColorBrush 是最簡單的種類,只提供一個顏色屬性用于渲染純色視覺對象。這可能聽起來沒什么讓人振奮的,但是不要忘了,您可以將動畫連接到該顏色屬性。CompositionEffectBrush 和 CompositionSurfaceBrush 類相關聯,但卻是更復雜的畫筆,因為它們由其他資源支持。對于任何附加的視覺對象,CompositionSurfaceBrush 都會渲染一個組合設計面。它具有控制位圖繪制的各種屬性,例如內插、對齊和拉伸,更不用說設計面本身了。Composition-EffectBrush 采用多種設計面畫筆制作各種效果。 ![](https://box.kancloud.cn/2016-01-08_568f406e652fa.png) 圖 5 窗口中的子視覺對象 ![](https://box.kancloud.cn/2016-01-08_568f406e81b6e.png) 圖 6 組合畫筆 創建和應用彩色畫筆簡單直接。下面是使用 C# 的一個例子: ~~~ using Windows.UI; CompositionColorBrush brush = compositor.CreateColorBrush(); brush.Color = Color.FromArgb(0xDC, 0x5B, 0x9B, 0xD5); visual.Brush = brush; ~~~ 顏色結構由 Windows.UI 命名空間提供,并顯示 alpha、紅色、綠色和藍色作為 8 位顏色值,不同于 DirectComposition 和 Direct2D 對浮點顏色值的偏好。對于視覺對象和畫筆,該方法一個比較好的功能是,可以隨時更改顏色屬性,而且引用相同畫筆的所有視覺對象都將自動進行更新。我之前的確暗示過,顏色屬性甚至可以制作動畫。那么它的工作原理是什么? 接下來我們談談動畫類。 動畫類層次結構如圖 7?所示。CompositionAnimation 基類提供了存儲命名值以用于表達式的功能。我稍后將詳細討論表達式。KeyFrameAnimation 提供了典型的基于關鍵幀的動畫屬性,如持續時間、迭代和停止行為。各種關鍵幀動畫類提供了用于插入關鍵幀的特定于類型的方法,以及特于定類型的動畫屬性。例如,ColorKeyFrameAnimation 允許您插入具有顏色值的關鍵幀以及一個用于控制顏色空間以使其在關鍵幀之間插入的屬性。 ![](https://box.kancloud.cn/2016-01-08_568f406e91937.png)? 圖 7 組合動畫 創建動畫對象,然后將該動畫應用至特定組合對象,這簡直太容易了。假設我想為某視覺對象的不透明度制作動畫。我可以直接使用 C++ 中的標量值將視覺對象的不透明度設置為 50%,如下所示: ~~~ visual.Opacity(0.5f); ~~~ 或者,我可以使用關鍵幀創建一個標量動畫對象,以制作一個從 0.0 至 1.0 的動畫變量,代表 0% 到 100%的不透明度: ~~~ ScalarKeyFrameAnimation animation = ? compositor.CreateScalarKeyFrameAnimation(); animation.InsertKeyFrame(0.0f, 0.0f); // Optional animation.InsertKeyFrame(1.0f, 1.0f); ~~~ InsertKeyFrame 的第一個參數是從動畫 (0.0) 開始到動畫 (1.0) 結束的相對偏移。第二個參數是動畫時間線中該點的動畫變量的值。因此,該動畫將在動畫期間將值從 0.0 順利轉變為 1.0。然后,我可以設置該動畫的總體持續時間,如下所示: ~~~ using namespace Windows::Foundation; animation.Duration(TimeSpan::FromSeconds(1)); ~~~ 動畫準備好后,我只需將其連接至我選擇的組合對象和屬性: ~~~ visual.StartAnimation(L"Opacity", animation); ~~~ StartAnimation 方法實際上繼承自 CompositionObject 基類,表示您可以為各種類的屬性制作動畫。這也是與 DirectComposition 相背離的一點。在 DirectComposition 中,每個可制作動畫的屬性為標量值和動畫對象提供了過多負載。Windows 組合可提供更加豐富的屬性系統,這就引入了一些非常有趣的功能。尤其是,它支持寫入文本表達式,減少了為制作更有趣的動畫和效果所需編寫的代碼量。這些表達式在運行時進行分析,由 Windows 組合引擎編譯,然后高效執行。 假設您需要沿 Y 軸旋轉某視覺對象,讓其深度表現出來。視覺對象的 RotationAngle 屬性(以弧度測量)是不夠的,因為它無法制作出包含角度的轉換。隨著視覺對象旋轉,離人眼最近的邊會顯得較大,而相反方向的邊則會顯得較小。圖 8?顯示了說明這一行為的多個旋轉對象。 ![](https://box.kancloud.cn/2016-01-08_568f406ea8151.png) 圖 8 旋轉視覺對象 您如何實現此類動畫效果? 那么,我們來看看針對旋轉角度的標量關鍵幀動畫: ~~~ ScalarKeyFrameAnimation animation = compositor.CreateScalarKeyFrameAnimation(); animation.InsertKeyFrame(1.0f, 2.0f * Math::Pi, ? compositor.CreateLinearEasingFunction()); animation.Duration(TimeSpan::FromSeconds(2)); animation.IterationBehavior(AnimationIterationBehavior::Forever); ~~~ 線性緩動函數替代了默認的加速/減速功能,以制作持續的旋轉動作。然后,我需要使用可以從表達式中引用的屬性定義自定義對象。排序器針對這一目的提供了一個屬性集: ~~~ CompositionPropertySet rotation = compositor.CreatePropertySet(); rotation.InsertScalar(L"Angle", 0.0f); ~~~ 一個屬性集也是一個組合對象,所以我可以使用 StartAnimation 方法為我的自定義屬性制作動畫,就像為任意內置屬性制作動畫那樣簡單: ~~~ rotation.StartAnimation(L"Angle", animation); ~~~ 我現在有一個 Angle 屬性在移動中的對象。現在,我需要定義一個轉換矩陣來制作想要的效果,同時委派給針對旋轉角度本身的此動畫屬性。輸入表達式: ~~~ ExpressionAnimation expression = ? compositor.CreateExpressionAnimation( ??? L"pre * Matrix4x4.CreateFromAxisAngle(axis, rotation.Angle) * post"); ~~~ 動畫表達式不是關鍵幀動畫對象,因此沒有動畫變量可能會改變的相對關鍵幀偏移(基于某些內插功能)。表達式反而僅僅是指可能在更傳統的意義上為自身制作動畫的參數。當然,由我來定義什么是“前”、“軸”、“旋轉”和“后”。我們來看看軸參數: ~~~ expression.SetVector3Parameter(L"axis", Vector3{ 0.0f, 1.0f, 0.0f }); ~~~ 表達式中的 CreateFromAxisAngle 方法預計旋轉某軸并因此圍繞 Y 軸定義該軸。它還預計旋轉角度,為此我們可以遵從旋轉屬性集及其動畫“Angle”屬性: ~~~ expression.SetReferenceParameter(L"rotation", rotation); ~~~ 要確保旋轉發生在視覺對象中央而不是左邊,我需要預先將 CreateFromAxisAngle 創建的旋轉矩陣乘以邏輯上將軸移動到旋轉點的轉換: ~~~ expression.SetMatrix4x4Parameter( ? L"pre", Matrix4x4::Translation(-width / 2.0f, -height / 2.0f, 0.0f)); ~~~ 切記,矩陣相乘不是交替的,所以前矩陣和后矩陣確實就是那樣。最后,在旋轉矩陣之后,我可以添加一些角度,然后將視覺對象還原至其原始位置: ~~~ expression.SetMatrix4x4Parameter( ? L"post", Matrix4x4::PerspectiveProjection(width * 2.0f) * ??? Matrix4x4::Translation(width / 2.0f, height / 2.0f, 0.0f)); ~~~ 這滿足表達式提及到的所有參數,我現在只需使用表達式動畫即可通過 TransformMatrix 屬性來為視覺對象制作動畫: ~~~ visual.StartAnimation(L"TransformMatrix", expression); ~~~ 我已經探討了創建、填充視覺對象并為其制作動畫的各種方式,那么我如果要直接渲染視覺對象的話,該怎么辦? DirectComposition 同時提供了預先分配的設計面和稀疏分配的位圖(叫做虛擬設計面,按需分配并可調整大小)。Windows 組合似乎沒有提供創建設計面的功能。有一個 CompositionDrawingSurface 類,但如果沒有外界協助,則無法創建。答案來自 Windows 組合 interop API。如果您只有組件的 Windows 元數據,則 WinRT 類可能會實現無法直接看到的其他 COM 接口。根據對這些掩蔽的接口的了解,您可以在 C++ 中輕松查詢它們。當然,這會導致要做的工作更多一點,因為您脫離了 Windows 組合 API 提供給主流開發人員的清潔抽象。我要做的第一件事情是,創建一個渲染設備,并且我將使用 Direct3D 11,因為 Windows 組合尚不支持 Direct3D 12: ~~~ ComPtr<ID3D11Device> direct3dDevice; ~~~ 然后,我將準備設備創建標記: ~~~ unsigned flags = D3D11_CREATE_DEVICE_BGRA_SUPPORT | ???????????????? D3D11_CREATE_DEVICE_SINGLETHREADED; #ifdef _DEBUG flags |= D3D11_CREATE_DEVICE_DEBUG; #endif ~~~ BGRA 支持允許我使用更易上手的 Direct2D API 來通過此設備進行渲染,然后 D3D11CreateDevice 函數自行創建硬件設備: ~~~ check(D3D11CreateDevice(nullptr, // Adapter ??????????????????????? D3D_DRIVER_TYPE_HARDWARE, ??????????????????????? nullptr, // Module ??????????????????????? flags, ??????????????????????? nullptr, 0, // Highest available feature level ???????????????????? ???D3D11_SDK_VERSION, ??????????????????????? set(direct3dDevice), ??????????????????????? nullptr, // Actual feature level ??????????????????????? nullptr)); // Device context ~~~ 之后,我需要查詢設備的 DXGI 接口,因為這是我創建 Direct2D 設備所需要的: ~~~ ComPtr<IDXGIDevice3> dxgiDevice = direct3dDevice.As<IDXGIDevice3>(); ~~~ 現在可以創建 Direct2D 設備了: ~~~ ComPtr<ID2D1Device> direct2dDevice; ~~~ 此時,我將再次為增加的診斷啟用調試層: ~~~ D2D1_CREATION_PROPERTIES properties = {}; #ifdef _DEBUG properties.debugLevel = D2D1_DEBUG_LEVEL_INFORMATION; #endif ~~~ 我可以先創建一個 Direct2D 工廠來創建該設備。如果我需要創建任何獨立于設備的資源,這將會非常有用。在這里我將只使用 D2D1-CreateDevice 函數提供的快捷方式: ~~~ check(D2D1CreateDevice(get(dxgiDevice), properties, set(direct2dDevice))); ~~~ 渲染設備準備好了。我有了可以根據自身需要隨意進行渲染的 Direct2D 設備。現在,我需要將此渲染設備告訴 Windows 組合引擎。這正是那些掩蔽的接口進入的地方。對于我自始至終都在使用的排序器,我可以查詢 ICompositorInterop 接口: ~~~ namespace abi = ABI::Windows::UI::Composition; ComPtr<abi::ICompositorInterop> compositorInterop; check(compositor->QueryInterface(set(compositorInterop))); ~~~ ICompositorInterop 提供了從 DXGI 設計面創建組合設計面的方法(如果您想要在組合可視化樹中包含現有交換鏈,這絕對方便),但是它還提供了一些更有趣的別的方法。其 CreateGraphicsDevice 方法將創建一個給出渲染設備的 CompositionGraphicsDevice 對象。CompositionGraphicsDevice 類是 Windows 組合 API 中的一個常規類,而不是掩蔽的接口,但是它未提供構造函數,因此您需要使用 C++ 和 ICompositorInterop 接口來創建它: ~~~ CompositionGraphicsDevice device = nullptr; check(compositorInterop->CreateGraphicsDevice(get(direct2dDevice), set(device))); ~~~ 由于 CompositionGraphicsDevice 是 WinRT 類型,因此我可以再次使用現代 C++,而非借助指針以及手動錯誤處理。而且是 CompositionGraphicsDevice 最終允許我創建組合設計面的: ~~~ using namespace Windows::Graphics::DirectX; CompositionDrawingSurface surface = ? compositionDevice.CreateDrawingSurface(Size{ 100, 100 }, ??? DirectXPixelFormat::B8G8R8A8UIntNormalized, ??? CompositionAlphaMode::Premultiplied); ~~~ 在此,我將創建一個大小為 100 x 100 像素的設計面。注意,這表示實際像素,而非其余 Windows 組合假設并提供的邏輯和 DPI 感知坐標。該設計面還提供了 Direct2D 支持的 32 位 alpha 混合渲染。當然,Direct3D 和 Direct2D 尚未通過 Windows 運行時提供,因此又回到掩蔽的接口來實際繪制到此設計面: ~~~ ComPtr<abi::ICompositionDrawingSurfaceInterop> surfaceInterop; check(surface->QueryInterface(set(surfaceInterop))); ~~~ Windows 組合很像在它之前的 DirectComposition,它在 IComposition-DrawingSurfaceInterop 接口上提供 BeginDraw 和 EndDraw 方法,這些方法將納入典型調用并將典型方法替代為通過相同名稱執行的 Direct2D 方法調用: ~~~ ComPtr<ID2D1DeviceContext> dc; POINT offset = {}; check(surfaceInterop->BeginDraw(nullptr, // Update rect ??????????????????????????????? __uuidof(dc), ??????????????????????????????? reinterpret_cast<void **>(set(dc)), ??????????????????????????????? &offset)); ~~~ Windows 組合獲取在創建組合設備時提供的原始渲染設備,并使用它創建設備上下文或渲染目標。我可以選擇以物理像素提供一個剪切矩形,但是在此我只選擇對渲染設計面進行不受限訪問。BeginDraw 也會再次返回一個以物理像素計算的偏移,以表明預期的繪圖表面的由來。這并不一定是渲染目標的左上角,必須要小心地調整或轉換任何繪圖命令使他們正確地接納此偏移。同樣,不要在渲染目標上調用 BeginDraw,因為 Windows 組合已經為您執行該操作。該渲染目標邏輯上由組合 API 擁有,必須小心謹慎,不要在調用 EndDraw 后按住它。渲染目標現已準備好,但不了解視圖的邏輯或有效 DPI。我可以使用 Windows::Graphics::Display 命名空間獲取當前視圖的邏輯 DPI 并設置 Direct2D 將用于進行渲染的 DPI: ~~~ using namespace Windows::Graphics::Display; DisplayInformation display = DisplayInformation::GetForCurrentView(); float const dpi = display.LogicalDpi(); dc->SetDpi(dpi, dpi); ~~~ 開始渲染之前的最后一步是,通過某種方法處理組合偏移。一個簡單的解決辦法就是使用偏移制作轉換矩陣。不過記住,Direct2D 以邏輯像素計算,所以我不僅需要使用偏移,還需要使用新確立的 DPI 值: ~~~ dc->SetTransform(D2D1::Matrix3x2F::Translation(offset.x * 96.0f / dpi, ????????????????????????????????????????? ?????offset.y * 96.0f / dpi)); ~~~ 此時,在設計面的 interop 接口上調用 EndDraw 方法之前,您可以盡情地繪制,以確保所有成批的 Direct2D 繪制命令得到處理,且對設計面所做的更改也反映在組合可視化樹中: ~~~ check(surfaceInterop->EndDraw()); ~~~ 當然,我尚未將設計面與視覺對象關聯,并且正如我所提到的,視覺對象不再提供內容屬性,且必須使用畫筆渲染。慶幸的是,排序器將創建一個畫筆來表示預先存在的設計面: ~~~ CompositionSurfaceBrush brush = compositor.CreateSurfaceBrush(surface); ~~~ 然后,我可以創建一個常規的子畫面畫筆,并使用此畫筆讓視覺對象發光: ~~~ SpriteVisual visual = compositor.CreateSpriteVisual(); visual.Brush(brush); visual.Size(Vector2{ ... }); ~~~ 如果這樣的互操作性對于您來說不夠,您甚至可以采用 XAML 元素并檢索基礎組合視覺對象。下面是使用 C# 的一個例子: ~~~ using Windows.UI.Xaml.Hosting; Visual visual = ElementCompositionPreview.GetElementVisual(button); ~~~ 盡管 ElementCompositionPreview 看起來像是臨時的狀態,而事實上它已做好制作準備,可被已提交到 Windows 應用商店的應用使用。對于任意 UI 元素,靜態 GetElementVisual 方法將從基礎組合可視化樹中返回視覺對象。注意,它返回 Visual,而非 ContainerVisual 或 SpriteVisual,因此您不能直接使用視覺對象子項或應用畫筆,但是您可以調整 Windows 組合提供的許多視覺對象屬性。ElementCompositionPreview 幫助程序類提供了一些其他的靜態方法,用于以控制的方式添加子視覺對象。您可以更改視覺對象的偏移,以及類似于將繼續在 XAML 級別運行的 UI 點擊測試這樣的功能。您甚至可以直接使用 Windows 組合應用動畫,而不用破壞構建于其上的 XAML 基礎架構。讓我們創建一個簡單的標量動畫來旋轉按鈕。我需要從視覺對象中檢索排序器,然后像以前一樣創建一個動畫對象: ~~~ Compositor compositor = visual.Compositor; ScalarKeyFrameAnimation animation = compositor.CreateScalarKeyFrameAnimation(); ~~~ 讓我們構建一個簡單的動畫來始終使用線性緩動函數緩慢旋轉按鈕: ~~~ animation.InsertKeyFrame(1.0f, (float) (2 * Math.PI), ? compositor.CreateLinearEasingFunction()); ~~~ 然后,我可以指明一次旋轉花費 3 秒并一直繼續: ~~~ animation.Duration = TimeSpan.FromSeconds(3); animation.IterationBehavior = AnimationIterationBehavior.Forever; ~~~ 最后,我可以簡單地將動畫連接到 XAML 提供的視覺對象,指示組合引擎對其 RotationAngle 屬性制作動畫: ~~~ visual.StartAnimation("RotationAngle", animation); ~~~ 盡管您可能只用 XAML 就能實現這一目標,但 Windows 組合引擎提供了更強大的功能與靈活性,因為它駐留在更低的抽象級別,無疑會提供更出色的性能。再舉個例子,Windows 組合提供了 XAML 目前不支持的四元數動畫。 關于 Windows 組合引擎還有很多話題可以談。依我個人淺見,這是迄今最具突破性的 WinRT API。可供您任意使用的功能無比強大,而且,與很多其他大型 UI 和圖形 API 不同,它不會影響性能,甚至不會占用您太多學習時間。在許多方面,Windows 組合都展現出 Windows 平臺的美妙與震撼。 您可以在 Twitter?[@WinComposition](https://twitter.com/@WinComposition)?找到 Windows Composition 團隊。 * * * Kenny Kerr?*是加拿大的計算機程序員,是 Pluralsight 的作者,也是一名 Microsoft MVP。他的博客網址是?[kennykerr.ca](http://kennykerr.ca/),您可以通過 Twitter?[@kennykerr](https://twitter.com/@kennykerr)?關注他。*
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看