无法在 UWP 中创建 CompositionTarget [英] Can't create a CompositionTarget in UWP

查看:17
本文介绍了无法在 UWP 中创建 CompositionTarget的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用的是 CreateTargetForCurrentView API 通过在 UIElement 的 合成器对象通过

I was using the CreateTargetForCurrentView API by invoking it on a UIElement's Compositor object extracted via

auto visual = ElementCompositionPreview::GetElementVisual(elem);
auto compositor = visual->Compositor;

在此之后,因为我想创建一棵树 视觉 s 之间有一种排序感,以便我可以根据我的用例将视觉放在另一个之上,我创建了一个 ContainerVisual 来托管这个视觉树.

After this, since I want to create a tree of Visuals with a sense of ordering amongst them so that I can position the visual one above the other as per my use case, I created a ContainerVisual to host this tree of visuals.

auto containerVisual = compositor->CreateContainerVisual();

现在由于这个 ContainerVisual 需要附加到 CompositionTarget 的 root,我这样做了(从 此处):

Now since this ContainerVisual needs to be attached to the root of a CompositionTarget, I did so (taking the reference from here):

auto compositionTarget = compositor->CreateTargetForCurrentView();

但这会导致 DCOMPOSITION_ERROR_WINDOW_ALREADY_COMPOSED 根据 docs 暗示:

but this leads to a DCOMPOSITION_ERROR_WINDOW_ALREADY_COMPOSED which as per the docs implies:

IDCompositionDevice::CreateTargetForHwnd 方法被调用已存在可视化树的 hwnd 和最顶层参数.

The IDCompositionDevice::CreateTargetForHwnd method was called with hwnd and topmost parameters for which a visual tree already exists.

如果我理解正确,这意味着 IDCompositionDevice::CreateTargetForHwnd 在我的 UWP 应用程序的生命周期中以某种方式被调用.此 API 是一个 Win32 API,未直接在应用程序中使用.现在我的问题是,在 UWP 应用程序中,Windows.UI.Composition 命名空间下的什么 API 或任何其他 API,在 C++/Cx 投影下,我应该寻找那个可能在内部调用导致此异常的 IDCompositionDevice::CreateTargetForHwnd?或者更好的是,是否有任何 API 可用于从 ViewWindow 中提取 CompositionTarget?我看到 CoreApplicationView 类中有一个属性 CompositionRootVisual 可用于直接附加 ContainerVisual 但它在其中一个中被删除API 更新按照 this.

If I understand correctly, this means IDCompositionDevice::CreateTargetForHwnd has been called somehow during the lifecycle of my UWP app. This API is a Win32 API that isn't being used directly in the app. Now my question is, in a UWP app, what API under Windows.UI.Composition namespace or any other, under the C++/Cx projection, should I be looking for that might be internally invoking IDCompositionDevice::CreateTargetForHwnd that's leading to this exception? Or better still, is there any API that can be used to extract a CompositionTarget from a View or Window? I see that there was a property CompositionRootVisual in the CoreApplicationView class that could be used to attach the ContainerVisual directly but it was removed in one of the API updates as per this.

| public class Windows.ApplicationModel.Core.CoreApplicationView {
-   public Visual CompositionRootVisual { get; set; }
| }

奇怪的是,即使是 docs 指的是将 ContainerVisual 附加到 View 的这条路线,但文档显然已经过时了.

Strangely even the docs refer to this route of attaching a ContainerVisual to a View but the documentation is apparently outdated.

推荐答案

如果要在 XAML 和可视层之间进行互操作,我们不应该纠结于 CompositionTarget.让我们回到如何使用 ContainerVisual 创建可视化树.请参阅文档,我们可以使用 ElementCompositionPreview.GetElementVisual(UIElement) 方法来获取任何页面元素的背景视觉,并使用 ElementCompositionPreview.SetElementChildVisual(UIElement, Visual) 方法将创建的视觉对象一个 UIElement 的可视化树.上面的文档和本文档中有一些代码 将视觉层与 XAML 结合使用,展示了如何从 UIElement 获取视觉对象并将视觉对象设置为 UIElement.

If you want to interop between XAML and the Visual Layer, we shouldn’t be entangled in CompositionTarget. Let’s back to how to use ContainerVisual to create a visual tree. Refer to the document, we could use ElementCompositionPreview.GetElementVisual(UIElement) method to grab the backing visual for any page element, and use ElementCompositionPreview.SetElementChildVisual(UIElement, Visual) method to take a created visual to a UIElement’s visual tree. There are some code in the above document and this document Using the Visual Layer with XAML, showing how to grab a visual from a UIElement and set a visual to a UIElement.

以下是您可以参考的示例代码:

Here is the sample code you could refer to:

添加命名空间和标题:

#include "windowsnumerics.h"

using namespace Windows::UI::Xaml::Hosting;
using namespace Windows::UI::Composition;
using namespace Windows::Foundation::Numerics;
using namespace Windows::UI;

声明一些成员:

private:
    Compositor^ _compositor;
    ContainerVisual^ _root;
    Visual^ CreateChildElement();

抓取视觉对象和设置视觉对象的代码:

The code to grab a visual and set a visual:

void App2::MainPage::Button_Click(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e)
{
    _compositor = ElementCompositionPreview::GetElementVisual(this)->Compositor;
    _root = _compositor->CreateContainerVisual();
    for (int i = 0; i < 5; i++)
    {
        _root->Children->InsertAtTop(CreateChildElement());
    }
    ElementCompositionPreview::SetElementChildVisual(this, _root);

}

Visual^ App2::MainPage::CreateChildElement()
{
    auto element = _compositor->CreateContainerVisual();
    element->Size = float2(100.0f, 100.0f);

    //
    // Position this visual randomly within our window
    //
    element->Offset = float3(((float)rand() / RAND_MAX) * 400, ((float)rand() / RAND_MAX) * 400, 0.0f);

    //
    // The outer rectangle is always white
    //
    auto visual = _compositor->CreateSpriteVisual();
    element->Children->InsertAtTop(visual);
    visual->Brush = _compositor->CreateColorBrush(ColorHelper::FromArgb(0xFF, 0xFF, 0x11, 0xFF));
    visual->Size = float2(100.0f, 100.0f);

    //
    // The inner rectangle is inset from the outer by three pixels all around
    //
    auto child = _compositor->CreateSpriteVisual();
    visual->Children->InsertAtTop(child);
    child->Offset = float3(3.0f, 3.0f, 0.0f);
    child->Size = float2(94.0f, 94.0f);

    //
    // Pick a random color for every rectangle
    //
    byte red = (byte)(0xFF * (0.2f + (((float)rand()/RAND_MAX) / 0.8f)));
    byte green = (byte)(0xFF * (0.2f + (((float)rand() / RAND_MAX) / 0.8f)));
    byte blue = (byte)(0xFF * (0.2f + (((float)rand() / RAND_MAX) / 0.8f)));
    child->Brush = _compositor->CreateColorBrush(ColorHelper::FromArgb(0xFF, red, green, blue));

    //
    // Make the subtree root visual partially transparent. This will cause each visual in the subtree
    // to render partially transparent, since a visual's opacity is multiplied with its parent's
    // opacity
    //
    element->Opacity = 0.8f;

    return element;

}

这篇关于无法在 UWP 中创建 CompositionTarget的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆