重新想象 Windows 8.1 Store Apps (81) - 控件增强: 加载本地 html, 智能替换 html 中的 url 引用, 通过 Share Contract 分享 WebView 中的内容, 为 WebView 截图
作者:webabcd
介绍
重新想象 Windows 8.1 Store Apps 之控件增强
- WebView 加载本地 html,智能替换 html 中的 url 引用
- WebView 通过 Share Contract 分享
- WebView 截图
示例
1、演示如何通过 WebView 加载本地 html, 以及智能替换 html 中的 url 引用
WebView/Local.xaml
<Page x:Class="Windows81.Controls.WebView.Local" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="using:Windows81.Controls.WebView" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d"> <Grid Background="Transparent"> <StackPanel Margin="120 0 0 0"> <Button Name="btnHtml" Content="解析指定的 html 字符串" Click="btnHtml_Click" /> <Button Name="btnPackageHtml" Content="解析 package 中的 html" Margin="0 10 0 0" Click="btnPackageHtml_Click" /> <Button Name="btnAppDataHtml" Content="解析 appData 中的 html" Margin="0 10 0 0" Click="btnAppDataHtml_Click" /> <Button Name="btnSmart" Content="智能替换 html 中的 url 引用" Margin="0 10 0 0" Click="btnSmart_Click" /> <WebView Name="webView" Width="800" Height="300" HorizontalAlignment="Left" Margin="0 10 0 0" /> </StackPanel> </Grid> </Page>
WebView/Local.xaml.cs
/* * 本例演示如何通过 WebView 加载指定的 html 字符串,加载 package 中的 html,加载 appData 中的 html * 还会演示如何以内容流的方式加载 html 数据,其有如下作用: * 1、可以实现完全从本地加载全部页面数据(包括 html,js,css,图片等) * 2、可以实现智能替换 html 中的 url 引用 * * WebView - 内嵌浏览器 * * * 提示: * 在 win8 中 WebView 会挡住所有元素(包括 AppBar),而在 win8.1 中不会再有这种情况了 * 如果想看看 win8 中全屏 WebView 如何不挡 AppBar,以及如何使用 WebViewBrush 以达到不遮挡其他元素的目的,请参看:http://www.cnblogs.com/webabcd/archive/2013/03/04/2942242.html * * 注:win8 和 win8.1 中的 WebView 有很多区别,在 win8.1 中使用 WebView 请参考本系列教程,在 win8 中使用 WebView 请看考:http://www.cnblogs.com/webabcd/archive/2013/03/04/2942242.html */ using System; using System.Threading.Tasks; using Windows.Foundation; using Windows.Storage; using Windows.Storage.Streams; using Windows.UI.Xaml; using Windows.UI.Xaml.Controls; using Windows.Web; using Windows.Web.Http; namespace Windows81.Controls.WebView { public sealed partial class Local : Page { public Local() { this.InitializeComponent(); } private void btnHtml_Click(object sender, RoutedEventArgs e) { // 解析指定的 html 字符串 webView.NavigateToString("<html><body>I am webabcd</body></html>"); } private void btnPackageHtml_Click(object sender, RoutedEventArgs e) { // 解析 package 中的 html string url = "ms-appx-web:///Controls/WebView/HtmlDemo.html"; webView.Navigate(new Uri(url)); } private async void btnAppDataHtml_Click(object sender, RoutedEventArgs e) { // 将程序包内的 html 文件复制到 ApplicationData 中的 LocalFolder StorageFolder localFolder = await ApplicationData.Current.LocalFolder.CreateFolderAsync("webabcdTest", CreationCollisionOption.OpenIfExists); StorageFile htmlFile = await StorageFile.GetFileFromApplicationUriAsync(new Uri("ms-appx:///Controls/WebView/HtmlDemo.html")); await htmlFile.CopyAsync(localFolder, "HtmlDemo.html", NameCollisionOption.ReplaceExisting); // 解析 appData 中的 html string url = "ms-appdata:///local/webabcdTest/HtmlDemo.html"; webView.Navigate(new Uri(url)); } // 以内容流的方式加载 html 数据 // 智能替换 html 中的 url 引用 // 在本例中,html 页面来自本地,html 中的引用来自远程 private void btnSmart_Click(object sender, RoutedEventArgs e) { // 构造可传递给 NavigateToLocalStreamUri() 的 URI Uri url = webView.BuildLocalStreamUri("contentIdentifier", "/Controls/WebView/HtmlDemo.html"); // 实例化一个实现 IUriToStreamResolver 接口的类 StreamUriWinRTResolver myResolver = new StreamUriWinRTResolver(); // 所有 url(包括 html 的 url 以及 html 内所有引用的 url)都会通过 StreamUriWinRTResolver 来返回数据流 webView.NavigateToLocalStreamUri(url, myResolver); } } // 实现 IUriToStreamResolver 接口(用于将 url 以内容流的方式返回) public sealed class StreamUriWinRTResolver : IUriToStreamResolver { // IUriToStreamResolver 接口只有一个需要实现的方法 // 根据 uri 返回对应的内容流 public IAsyncOperation<IInputStream> UriToStreamAsync(Uri uri) { string path = uri.AbsolutePath; return GetContent(path).AsAsyncOperation(); } // 根据 uri 返回对应的内容流 private async Task<IInputStream> GetContent(string path) { string url; // 按需求修改 url 引用 if (path == "/Controls/WebView/HtmlDemo.html") url = "ms-appx://" + path; else url = "http://ajax.googleapis.com" + path; if (url.StartsWith("http")) { // http 方式获取内容数据 HttpResponseMessage response = await new HttpClient().GetAsync(new Uri(url), HttpCompletionOption.ResponseHeadersRead); return await response.Content.ReadAsInputStreamAsync(); } else { // 获取本地数据 StorageFile fileRead = await Windows.Storage.StorageFile.GetFileFromApplicationUriAsync(new Uri(url, UriKind.Absolute)); return await fileRead.OpenAsync(FileAccessMode.Read); } } } }
本地 Html:
WebView/HtmlDemo.html
<!--此 html 用于演示如何通过 WebView 加载本地 html,以及如何以内容流的方式加载 html 数据--> <!doctype html> <html> <head> <title></title> <script type="text/javascript" src="/ajax/libs/jquery/1.7.2/jquery.min.js"></script> </head> <body> <p>i am html2</p> <p id="lblMsg"></p> <script type="text/javascript"> document.getElementById("lblMsg").innerHTML = window.jQuery; </script> </body> </html>
2、演示如何通过 Share Contract 分享 WebView 中的内容(复制到剪切板也是同理)
WebView/Share.xaml
<Page x:Class="Windows81.Controls.WebView.Share" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="using:Windows81.Controls.WebView" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d"> <Grid Background="Transparent"> <StackPanel Margin="120 0 0 0"> <Button Name="btnShare" Content="通过 Share Contract 分享 WebView 中的被选中的文本内容" Click="btnShare_Click" /> <WebView Name="webView" Width="400" Height="300" Source="http://webabcd.cnblogs.com/" HorizontalAlignment="Left" Margin="0 10 0 0" /> </StackPanel> </Grid> </Page>
WebView/Share.xaml.cs
/* * 本例演示如何通过 Share Contract 分享 WebView 中的内容(复制到剪切板也是同理) * * WebView - 内嵌浏览器 * CaptureSelectedContentToDataPackageAsync() - 获取 DataPackage 对象 * DataRequested - 共享操作开始时触发的事件(事件参数 DataRequestedEventArgs) * * DataRequestedEventArgs - 共享操作开始时触发的事件 * GetDeferral() - 获取异步操作对象,同时开始异步操作,之后通过 Complete() 通知完成异步操作 * * 关于 DataPackage 等共享相关的知识点请参见:http://www.cnblogs.com/webabcd/archive/2013/07/04/3171085.html * * * * 提示: * 在 win8 中 WebView 会挡住所有元素(包括 AppBar),而在 win8.1 中不会再有这种情况了 * 如果想看看 win8 中全屏 WebView 如何不挡 AppBar,以及如何使用 WebViewBrush 以达到不遮挡其他元素的目的,请参看:http://www.cnblogs.com/webabcd/archive/2013/03/04/2942242.html * * 注:win8 和 win8.1 中的 WebView 有很多区别,在 win8.1 中使用 WebView 请参考本系列教程,在 win8 中使用 WebView 请看考:http://www.cnblogs.com/webabcd/archive/2013/03/04/2942242.html */ using System; using Windows.ApplicationModel.DataTransfer; using Windows.UI.Xaml; using Windows.UI.Xaml.Controls; namespace Windows81.Controls.WebView { public sealed partial class Share : Page { private DataTransferManager _dataTransferManager; public Share() { this.InitializeComponent(); } private void btnShare_Click(object sender, RoutedEventArgs e) { _dataTransferManager = DataTransferManager.GetForCurrentView(); _dataTransferManager.DataRequested += _dataTransferManager_DataRequested; DataTransferManager.ShowShareUI(); } // 分享 WebView 中的被选中的文本内容 async void _dataTransferManager_DataRequested(DataTransferManager sender, DataRequestedEventArgs args) { DataRequest request = args.Request; DataRequestDeferral deferral = args.Request.GetDeferral(); DataPackage dataPackage = await webView.CaptureSelectedContentToDataPackageAsync(); DataPackageView dataPackageView = dataPackage.GetView(); // 如果用户选择了一段内容,则通过 WebView.CaptureSelectedContentToDataPackageAsync() 获取到的数据里就会有 StandardDataFormats.Text 格式的内容,此内容就是用户所选中的内容 if (dataPackageView.Contains(StandardDataFormats.Text)) { dataPackage.Properties.Title = "Title"; dataPackage.Properties.Description = "Description"; request.Data = dataPackage; } else { request.FailWithDisplayText("没有选中任何内容"); } _dataTransferManager.DataRequested -= _dataTransferManager_DataRequested; deferral.Complete(); } } }
3、演示如何对 WebView 中的内容截图
WebView/Capture.xaml
<Page x:Class="Windows81.Controls.WebView.Capture" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="using:Windows81.Controls.WebView" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d"> <Grid Background="Transparent"> <StackPanel Margin="120 0 0 0"> <Button Name="btnCapture" Content="对此 WebView 中的当前内容截图" Click="btnCapture_Click" /> <WebView Name="webView" Width="400" Height="300" Source="http://webabcd.cnblogs.com/" HorizontalAlignment="Left" Margin="0 10 0 0" /> <StackPanel Margin="0 10 0 0" Orientation="Horizontal"> <Image Name="imageOriginal" Width="400" Height="300" HorizontalAlignment="Left" /> <Image Name="imageSmall" Width="400" Height="300" HorizontalAlignment="Left" Margin="10 0 0 0" /> </StackPanel> </StackPanel> </Grid> </Page>
WebView/Capture.xaml.cs
/* * 本例演示如何对 WebView 中的内容截图 * * WebView - 内嵌浏览器 * * * 提示: * 在 win8 中 WebView 会挡住所有元素(包括 AppBar),而在 win8.1 中不会再有这种情况了 * 如果想看看 win8 中全屏 WebView 如何不挡 AppBar,以及如何使用 WebViewBrush 以达到不遮挡其他元素的目的,请参看:http://www.cnblogs.com/webabcd/archive/2013/03/04/2942242.html * * 注:win8 和 win8.1 中的 WebView 有很多区别,在 win8.1 中使用 WebView 请参考本系列教程,在 win8 中使用 WebView 请看考:http://www.cnblogs.com/webabcd/archive/2013/03/04/2942242.html */ using System; using System.Runtime.InteropServices.WindowsRuntime; using System.Threading.Tasks; using Windows.Graphics.Imaging; using Windows.Storage.Streams; using Windows.UI.Xaml; using Windows.UI.Xaml.Controls; using Windows.UI.Xaml.Media.Imaging; namespace Windows81.Controls.WebView { public sealed partial class Capture : Page { public Capture() { this.InitializeComponent(); } private async void btnCapture_Click(object sender, RoutedEventArgs e) { // 对 WebView 中的内容截图,并将原始图像数据放入内存流 InMemoryRandomAccessStream ms = new InMemoryRandomAccessStream(); await webView.CapturePreviewToStreamAsync(ms); // 显示原始截图 BitmapImage bitmapImage = new BitmapImage(); bitmapImage.SetSource(ms); imageOriginal.Source = bitmapImage; // 定义缩略图的大小(最长边定义为 180) int longlength = 180, width = 0, height = 0; double srcwidth = webView.ActualWidth, srcheight = webView.ActualHeight; double factor = srcwidth / srcheight; if (factor < 1) { height = longlength; width = (int)(longlength * factor); } else { width = longlength; height = (int)(longlength / factor); } // 显示原始截图的缩略图 BitmapSource small = await resize(width, height, ms); imageSmall.Source = small; } // 返回指定原图的缩略图数据 private async Task<BitmapSource> resize(int width, int height, IRandomAccessStream source) { WriteableBitmap small = new WriteableBitmap(width, height); BitmapDecoder decoder = await BitmapDecoder.CreateAsync(source); BitmapTransform transform = new BitmapTransform(); transform.ScaledHeight = (uint)height; transform.ScaledWidth = (uint)width; PixelDataProvider pixelData = await decoder.GetPixelDataAsync( BitmapPixelFormat.Bgra8, BitmapAlphaMode.Straight, transform, ExifOrientationMode.RespectExifOrientation, ColorManagementMode.DoNotColorManage); pixelData.DetachPixelData().CopyTo(small.PixelBuffer); return small; } } }
OK
[源码下载]