gpt4 book ai didi

xaml - Winrt 中的网格效果

转载 作者:行者123 更新时间:2023-12-01 19:13:49 25 4
gpt4 key购买 nike

在 WPF 中,大多数控件都有一个 Effect 属性,例如 Grid.Effect,它允许创建模糊网格。我想了解如何在 WinRT 中创建背景模糊的弹出窗口?

最佳答案

不执行此操作或使用 DirectX 的替代方法可能是使用新的 RenderTargetBitmap 类以及 RenderAsync() 方法,该方法允许您访问从 C# 或 VB 级别进行控制(假设您正在使用该级别),这可能比 DirectX 更容易,而且实际上速度足够快,足以让一些基本效果在 CPU 上运行。我已经在 FxContentControl 中完成了上周末在 WinRT XAML 工具包中,它似乎在一些简单的场景中工作正常,主要问题是 - 何时更新效果。

该控件目前不会模糊任何内容,而是找到内容的扩展像素并将其设为黑色,作为为 TextBlock 或任何其他控件生成笔划的穷人的方式有一些透明区域和一些不透明区域。您可以将其更改为模糊或添加一个选项以相当轻松地按需执行此操作。

这是模板化控件的默认样式:

<Style
TargetType="controls:FxContentControl">
<Setter
Property="HorizontalContentAlignment"
Value="Left" />
<Setter
Property="VerticalContentAlignment"
Value="Top" />
<Setter
Property="Template">
<Setter.Value>
<ControlTemplate
TargetType="controls:FxContentControl">
<Grid>
<Image
x:Name="BackgroundFxImage"
Stretch="None"
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
Margin="{TemplateBinding Padding}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}" />
<Grid
x:Name="RenderedGrid"
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
Margin="{TemplateBinding Padding}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}">
<ContentPresenter
x:Name="ContentPresenter"
ContentTemplate="{TemplateBinding ContentTemplate}"
ContentTransitions="{TemplateBinding ContentTransitions}"
Content="{TemplateBinding Content}" />
</Grid>
<Image
x:Name="ForegroundFxImage"
Stretch="None"
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
Margin="{TemplateBinding Padding}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}" />
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>

代码如下:

using System;
using System.Threading.Tasks;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Media.Imaging;
using WinRTXamlToolkit.Imaging;

namespace WinRTXamlToolkit.Controls
{
public class FxContentControl : ContentControl
{
private Image _backgroundFxImage;
private Image _foregroundFxImage;
private ContentPresenter _contentPresenter;
private Grid _renderedGrid;

public FxContentControl()
{
this.DefaultStyleKey = typeof(FxContentControl);
}

protected override async void OnApplyTemplate()
{
base.OnApplyTemplate();
_backgroundFxImage = this.GetTemplateChild("BackgroundFxImage") as Image;
_foregroundFxImage = this.GetTemplateChild("ForegroundFxImage") as Image;
_contentPresenter = this.GetTemplateChild("ContentPresenter") as ContentPresenter;
_renderedGrid = this.GetTemplateChild("RenderedGrid") as Grid;

if (_renderedGrid != null)
{
_renderedGrid.SizeChanged += this.OnContentPresenterSizeChanged;
}

if (_renderedGrid.ActualHeight > 0)
{
await this.UpdateFx();
}
}

private async void OnContentPresenterSizeChanged(object sender, SizeChangedEventArgs sizeChangedEventArgs)
{
await this.UpdateFx();
}

private async Task UpdateFx()
{
await this.UpdateBackgroundFx();
}

private async Task UpdateBackgroundFx()
{
if (_renderedGrid.ActualHeight < 1 ||
_backgroundFxImage == null)
{
return;
}

var rtb = new RenderTargetBitmap();
await rtb.RenderAsync(_renderedGrid);

var pw = rtb.PixelWidth;
var ph = rtb.PixelHeight;

var wb = _backgroundFxImage.Source as WriteableBitmap;

if (wb == null ||
wb.PixelWidth != pw ||
wb.PixelHeight != ph)
{
wb = new WriteableBitmap(pw, ph);
}

await ProcessContentImage(rtb, wb, pw, ph);

_backgroundFxImage.Source = wb;
}

protected virtual async Task ProcessContentImage(RenderTargetBitmap rtb, WriteableBitmap wb, int pw, int ph)
{
var rtbBuffer = await rtb.GetPixelsAsync();
var rtbPixels = rtbBuffer.GetPixels();
var wbBuffer = wb.PixelBuffer;
var wbPixels = wbBuffer.GetPixels();

// Expand
int expansion = 1;

for (int x = 0; x < pw; x++)
for (int y = 0; y < ph; y++)
{
int x1min = Math.Max(0, x - expansion);
int x1max = Math.Min(x + expansion, pw - 1);
int y1min = Math.Max(0, y - expansion);
int y1max = Math.Min(y + expansion, ph - 1);
//bool found = false;
byte maxa = 0;

for (int x1 = x1min; x1 <= x1max; x1++)
for (int y1 = y1min; y1 <= y1max; y1++)
{
var a = rtbPixels.Bytes[4 * (y1 * pw + x1) + 3];
if (a > maxa)
maxa = a;
}
wbPixels.Bytes[4 * (y * pw + x)] = 0;
wbPixels.Bytes[4 * (y * pw + x) + 1] = 0;
wbPixels.Bytes[4 * (y * pw + x) + 2] = 0;
wbPixels.Bytes[4 * (y * pw + x) + 3] = maxa;
}

wbPixels.UpdateFromBytes();
}
}
}

它还使用以下 IBuffer 包装器:

using System;
using System.IO;
using System.Runtime.InteropServices.WindowsRuntime;
using Windows.Storage.Streams;

namespace WinRTXamlToolkit.Imaging
{
// ReSharper disable InconsistentNaming - This class extends IBuffer
/// <summary>
/// Contains extensions for an IBuffer interface in the context of a WriteableBitmap,
/// which exposes one to access its pixels.
/// </summary>
public static class IBufferExtensions
// ReSharper restore InconsistentNaming
{
/// <summary>
/// Gives access to the pixels of a WriteableBitmap given an IBuffer
/// exposed by Pixels property.
/// </summary>
/// <remarks>
/// Note that creating this object copies the pixels buffer
/// into the Bytes byte array for quick pixel access
/// and the array needs to be copied back to the pixels buffer
/// to update the bitmap with a call to UpdateFromBytes().
/// This is acceptable for convenience and possibly best for
/// performance in some scenarios, but it does add some upfront
/// overhead as well overhead to update the bitmap at the end.
/// This is only a theory and for better performance it might be
/// good to test different approaches.
/// The goal of this approach is code simplicity. For best performance
/// using native code and/or DirectX is recommended.
/// </remarks>
public class PixelBufferInfo
{
private readonly Stream _pixelStream;

/// <summary>
/// The bytes of the pixel stream.
/// </summary>
public byte[] Bytes;

/// <summary>
/// Initializes a new instance of the <see cref="PixelBufferInfo" /> class.
/// </summary>
/// <param name="pixelBuffer">The pixel buffer returned by WriteableBitmap.PixelBuffer.</param>
public PixelBufferInfo(IBuffer pixelBuffer)
{
_pixelStream = pixelBuffer.AsStream();
this.Bytes = new byte[_pixelStream.Length];
_pixelStream.Seek(0, SeekOrigin.Begin);
_pixelStream.Read(this.Bytes, 0, Bytes.Length);
//this.Pixels = bytes.ToPixels();
}

/// <summary>
/// Updates the associated pixel buffer from bytes.
/// </summary>
public void UpdateFromBytes()
{
_pixelStream.Seek(0, SeekOrigin.Begin);
_pixelStream.Write(Bytes, 0, Bytes.Length);
}
}

/// <summary>
/// Gets the pixels access wrapper for a PixelBuffer property of a WriteableBitmap.
/// </summary>
/// <param name="pixelBuffer">The pixel buffer.</param>
/// <returns></returns>
public static PixelBufferInfo GetPixels(this IBuffer pixelBuffer)
{
return new PixelBufferInfo(pixelBuffer);
}
}
}

关于xaml - Winrt 中的网格效果,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19596177/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com