Windows 8 使用WritableBitmapEx从xaml控件创建位图图像

Windows 8 使用WritableBitmapEx从xaml控件创建位图图像,windows-8,windows-runtime,Windows 8,Windows Runtime,如何使用WritableBitmapEx从xaml控件创建位图图像。在我的winRT应用程序中,我需要创建窗口的快照,以实现Pin-to-Tile(固定辅助Tile)。我发现winRT中缺少WritableBitmap.render()。如何使用WritableBitmapEx实现此功能。我一直在使用Windows.Storage.Streams中的RandomAccessStreamReference类来创建位图。一个示例(这实际上是用于共享的代码): 还请记住,对于固定辅助磁贴,您可以在磁贴

如何使用WritableBitmapEx从xaml控件创建位图图像。在我的winRT应用程序中,我需要创建窗口的快照,以实现Pin-to-Tile(固定辅助Tile)。我发现winRT中缺少WritableBitmap.render()。如何使用WritableBitmapEx实现此功能。

我一直在使用Windows.Storage.Streams中的RandomAccessStreamReference类来创建位图。一个示例(这实际上是用于共享的代码):

还请记住,对于固定辅助磁贴,您可以在磁贴上传递徽标的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);
                }
            }
        }
    }
//这是您随后将作为最后一个参数传递到的URI
//二级平铺构造函数,如上面的代码:
var logoUri=wait GetLocalImageAsync(restaurant.ImagePath,restaurant.Key);
//以下是完成工作的方法:
/// 
///将映像从internet(http协议)本地复制到AppData LocalFolder。
///某些方法(如SecondaryTile构造函数)不支持
///通过http引用图像,但可以使用ms appdata协议引用图像。
/// 
///internet上图像的路径(URI)
///本地文件的唯一名称
///已在本地复制的图像的路径
专用异步任务GetLocalImageAsync(字符串internetUri,字符串uniqueName)
{
if(string.IsNullOrEmpty(internetUri))
{
返回null;
}
使用(var response=wait HttpWebRequest.CreateHttp(internetUri.GetResponseAsync())
{
使用(var stream=response.GetResponseStream())
{
var desiredName=string.Format(“{0}.jpg”,uniqueName);
var file=wait ApplicationData.Current.LocalFolder.CreateFileAsync(desiredName,CreationCollisionOption.ReplaceExisting);
使用(var filestream=await file.OpenStreamForWriteAsync())
{
等待stream.CopyToAsync(filestream);
返回新的Uri(string.Format(“ms-appdata:///local/{0}.jpg“,uniqueName),UriKind.Absolute);
}
}
}
}

自提出此问题以来,WritableBitmapEx已经更新,现在支持WinRT-因此它应该可以正常工作


有大量的演示可以展示这一点,并回答了许多问题:

不知怎的,他们错过了实现WriteableBitmap。据我所知,它可能会出现在SDK的更高版本中,但现在您可以选择使用WriteableBitmap并使用控件的内容逐像素填充它,可能需要借助DirectX,或者使用DirectX,也许在SharpDX的帮助下,它是DirectX的包装器,您可以在C#应用程序中使用。如果要呈现任何文本,确实需要使用DirectX/Direct2D/DirectWrite。如果您的UI很简单,那么使用DirectX并不难。有一个样本似乎是一个很好的起点

编辑*

还有一个是我在中开始实现的,它对渲染可视树的支持有一定的限制,但可能有帮助。我计划在必要时扩展它以支持更多的UI元素。它目前支持具有纯色或渐变背景的典型文本块和形状

编辑2*


Windows 8.1添加了API,这是非常有用的,尽管它有一些限制,例如,它要求呈现的UI是可视化树的一部分(虽然它可以位于隐藏面板中),错过视频播放、DirectX内容,我相信
WebView
内容也会有帮助。

这不是我期望得到的答案。在这里,您演示了创建PinToTile的方法。我被问到的是一些不同的问题。我没有一个可以用手固定的图像;我的要求是,我有一个带有一些数据的控件(比如网格或画布),我需要从该控件创建一个图像,然后我需要将该图像固定到启动屏幕。希望你能理解我的问题。我可以在wp7和wpf中使用writeableBitmap.Render()方法从控件创建图像。但在温特,不要。我需要解决这个问题。太好了。RenderTargetBitmap.RenderAsync()是大多数方案的最佳解决方案。WritableBitmapEx.Render在Windows Phone 8.1 RT上不可用,但在8.1 Silverlight中可用。@user925327与以前的版本相比,很可能缺少一些方法,但现在有很多方法可以使用。
        // 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);
                }
            }
        }
    }