uwp - 无法在 UWP 中创建 CompositionTarget
问题描述
我正在使用CreateTargetForCurrentView API,方法是在 通过
auto visual = ElementCompositionPreview::GetElementVisual(elem);
auto compositor = visual->Compositor;
在此之后,由于我想创建一个Visual的树,它们之间有一种排序感,以便我可以根据我的用例将视觉放在另一个之上,因此我创建了一个ContainerVisual来托管这棵视觉树。
auto containerVisual = compositor->CreateContainerVisual();
现在因为这ContainerVisual
需要附加到root
CompositionTarget 的,所以我这样做了(从这里获取参考):
auto compositionTarget = compositor->CreateTargetForCurrentView();
但这会导致DCOMPOSITION_ERROR_WINDOW_ALREADY_COMPOSED
根据文档暗示:
IDCompositionDevice::CreateTargetForHwnd 方法是使用 hwnd 和 topmost 参数调用的,其可视化树已经存在。
如果我理解正确,这意味着IDCompositionDevice::CreateTargetForHwnd在我的 UWP 应用程序的生命周期中以某种方式被调用。此 APIWin32
是未在应用程序中直接使用的 API。现在我的问题是,在 UWP 应用程序中,Windows.UI.Composition
命名空间下的 API 或投影下的任何其他API C++/Cx
,我应该寻找可能在内部调用IDCompositionDevice::CreateTargetForHwnd
导致此异常的 API 吗?或者更好的是,是否有任何 API 可用于CompositionTarget
从 aView
或中提取 a Window
?我看到类中有一个属性CompositionRootVisual
可CoreApplicationView
用于直接附加,但它已在其中一个 API 更新中ContainerVisual
被删除。
| public class Windows.ApplicationModel.Core.CoreApplicationView {
- public Visual CompositionRootVisual { get; set; }
| }
奇怪的是,即使是文档也提到了将 a 附加ContainerVisual
到 a的这条路线,View
但文档显然已经过时了。
解决方案
如果要在 XAML 和可视层之间进行互操作,我们不应该纠缠于CompositionTarget
. 让我们回到如何使用ContainerVisual
来创建可视化树。参考文档,我们可以使用ElementCompositionPreview.GetElementVisual(UIElement)
方法来获取任何页面元素的背景视觉,并使用ElementCompositionPreview.SetElementChildVisual(UIElement, Visual)方法将创建的视觉带到 UIElement 的视觉树中。上述文档和本文档Using the Visual Layer with XAML中有一些代码,展示了如何从 a 中获取视觉对象UIElement
并将视觉对象设置为 a UIElement
。
以下是您可以参考的示例代码:
添加命名空间和标题:
#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();
获取视觉对象并设置视觉对象的代码:
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;
}
推荐阅读
- haskell - 使用镜头映射记录的两个字段
- r - R 使用 Dplyr 创建一个列,该列包含基于 5 个其他列的值的 6 个可能值中的 1 个
- ruby - 如何在一行中获得多个N输入
- javascript - 识别从反应代码中的多个复选框检查的输入并将它们存储在一个空数组中
- javascript - 开玩笑 focus() 不是一个函数
- powershell - PowerShell 输出文件双空格分隔符
- javascript - 使用 json.parse() 无法正确返回数据
- r - 一旦用户在 R Shiny 中选择了多个选项,就禁用 selectinput
- snowflake-cloud-data-platform - 基于 dbt 中元数据表的动态模型生成
- r - 我可以使用非降价 R 获得 R-Markdown 绘图的漂亮视觉效果吗?