如何使用 WritableBitmapEx 从 xaml 控件创建位图图像。在我的 winRT 应用程序中,我需要创建我的窗口的快照以实现 Pin to Tile(固定辅助磁贴)。我发现 winRT 中缺少 WritableBitmap.render()。如何使用 WritableBitmapEx 实现此功能。
3 回答
不知何故,他们错过了实现 WriteableBitmap。Render()虽然我听说它可能会出现在 SDK 的更高版本中,但现在您的选择是使用 WriteableBitmap 并使用您的控件内容逐像素填充它,也许在WriteableBitmapEx的帮助下或者使用 DirectX,也许在 SharpDX 的帮助下,它是 DirectX 的包装器,您可以在 C# 应用程序中使用。如果你想渲染任何文本,你确实需要使用 DirectX/Direct2D/DirectWrite。如果您的 UI 很简单,那么使用 DirectX 并不太难。有一个样本似乎是从这里开始的好地方。
编辑*
然后还有一个我开始在WinRT XAML 工具包中实现的WriteableBitmap.Render() 扩展方法,它对渲染可视化树有一些有限但可能有用的支持。如有必要,我计划扩展它以支持更多 UI 元素。它目前支持具有纯色或渐变背景的典型文本块和形状。
编辑 2*
Windows 8.1 添加了RenderTargetBitmap.RenderAsync()
非常有用的 API,尽管它有一些限制,例如它要求渲染的 UI 是可视化树的一部分(尽管它可以在隐藏面板中),错过视频播放、DirectX 内容,我WebView
也相信内容.
自提出此问题以来,WritableBitmapEx 已更新,现在支持 WinRT - 所以它应该可以正常工作。
有大量的演示来展示这一点并回答了一些 SO 问题:https ://gist.github.com/2834070
我一直在使用 Windows.Storage.Streams 中的 RandomAccessStreamReference 类来创建位图。一个例子(这实际上是共享代码):
var reference = RandomAccessStreamReference.CreateFromUri(new Uri(item.ImagePath.AbsoluteUri));
request.Data.SetBitmap(reference);
还要记住,对于固定辅助磁贴,您可以传入磁贴上徽标的 URI,而无需创建实际的位图,只要徽标是应用程序包的一部分,如下所示:
var uri = new Uri(item.TileImagePath.AbsoluteUri);
var tile = new SecondaryTile(
item.UniqueId, // Tile ID
item.ShortTitle, // Tile short name
item.Title, // Tile display name
item.UniqueId, // Activation argument
TileOptions.ShowNameOnLogo, // Tile options
uri // Tile logo URI
);
await tile.RequestCreateAsync();
最后,如果要在辅助磁贴上使用的图像是在线的,而不是应用程序包的一部分,则必须先将其复制到本地,然后才能使用它。这是一些执行此操作的代码:
// This is the URI that you will then pass as the last parameter into
// the Secondary Tile constructor, like the code above:
var logoUri = await GetLocalImageAsync(restaurant.ImagePath, restaurant.Key);
// and here's the method that does the meat of the work:
/// <summary>
/// Copies an image from the internet (http protocol) locally to the AppData LocalFolder.
/// This is used by some methods (like the SecondaryTile constructor) that do not support
/// referencing images over http but can reference them using the ms-appdata protocol.
/// </summary>
/// <param name="internetUri">The path (URI) to the image on the internet</param>
/// <param name="uniqueName">A unique name for the local file</param>
/// <returns>Path to the image that has been copied locally</returns>
private async Task<Uri> GetLocalImageAsync(string internetUri, string uniqueName)
{
if (string.IsNullOrEmpty(internetUri))
{
return null;
}
using (var response = await HttpWebRequest.CreateHttp(internetUri).GetResponseAsync())
{
using (var stream = response.GetResponseStream())
{
var desiredName = string.Format("{0}.jpg", uniqueName);
var file = await ApplicationData.Current.LocalFolder.CreateFileAsync(desiredName, CreationCollisionOption.ReplaceExisting);
using (var filestream = await file.OpenStreamForWriteAsync())
{
await stream.CopyToAsync(filestream);
return new Uri(string.Format("ms-appdata:///local/{0}.jpg", uniqueName), UriKind.Absolute);
}
}
}
}