原文:
重新想象 Windows 8 Store Apps (40) - 剪切板: 复制/粘贴文本, html, 图片, 文件
重新想象 Windows 8 Store Apps (40) - 剪切板: 复制/粘贴文本, html, 图片, 文件
作者:webabcd
介绍
重新想象 Windows 8 Store Apps 之 剪切板
- Clipboard - 剪切板
- 复制/粘贴文本
- 复制/粘贴html
- 复制/粘贴图片
- 复制/粘贴文件
示例
1、演示剪切板的基本应用
Clipboard/Demo.xaml
<Page x:Class="XamlDemo.Clipboard.Demo" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="using:XamlDemo.Clipboard" 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"> <TextBlock Name="lblMsg" FontSize="14.667" /> <Button Name="btnCopyText" Content="复制一段文本到剪切板" Click="btnCopyText_Click_1" Margin="0 10 0 0" /> <Button Name="btnPasteText" Content="粘贴剪切板中的文本" Click="btnPasteText_Click_1" Margin="0 10 0 0" /> <Button Name="btnShowAvailableFormats" Content="获取剪切板中包含的数据的格式类型" Click="btnShowAvailableFormats_Click_1" Margin="0 10 0 0" /> <Button Name="btnClear" Content="清除剪切板中的全部内容" Click="btnClear_Click_1" Margin="0 10 0 0" /> </StackPanel> </Grid> </Page>
Clipboard/Demo.xaml.cs
/* * Clipboard - 剪切板 * SetContent() - 将指定的 DataPackage 存入剪切板 * GetContent() - 从剪切板中获取 DataPackage 对象 * Clear() - 清除剪切板中的全部数据 * Flush() - 正常情况下,关闭 app 后,此 app 保存到剪切板的数据就会消失;调用此方法后,即使关闭 app,剪切板中的数据也不会消失 * ContentChanged - 剪切板中的数据发生变化时所触发的事件 * * DataPackage - 用于封装 Clipboard 或 ShareContract 的数据(详细说明见 ShareContract 的 Demo) * SetText(), SetUri(), SetHtmlFormat(), SetRtf(), SetBitmap(), SetStorageItems(), SetData(), SetDataProvider() - 设置复制到剪切板的各种格式的数据(注:一个 DataPackage 可以有多种不同格式的数据) * RequestedOperation - 操作类型(DataPackageOperation 枚举: None, Copy, Move, Link),没发现此属性有任何作用 * * DataPackageView - DataPackage 对象的只读版本,从剪切板获取数据或者共享目标接收数据均通过此对象来获取 DataPackage 对象的数据(详细说明见 ShareContract 的 Demo) */ using System; using Windows.ApplicationModel.DataTransfer; using Windows.UI.Xaml; using Windows.UI.Xaml.Controls; using Windows.UI.Xaml.Navigation; namespace XamlDemo.Clipboard { public sealed partial class Demo : Page { public Demo() { this.InitializeComponent(); } protected override void OnNavigatedTo(NavigationEventArgs e) { Windows.ApplicationModel.DataTransfer.Clipboard.ContentChanged += Clipboard_ContentChanged; } protected override void OnNavigatedFrom(NavigationEventArgs e) { Windows.ApplicationModel.DataTransfer.Clipboard.ContentChanged -= Clipboard_ContentChanged; } void Clipboard_ContentChanged(object sender, object e) { lblMsg.Text += Environment.NewLine; lblMsg.Text += "剪切板中的内容发生了变化"; } // 复制一段文本到剪切板 private void btnCopyText_Click_1(object sender, RoutedEventArgs e) { // 构造保存到剪切板的 DataPackage 对象 DataPackage dataPackage = new DataPackage(); dataPackage.SetText("I am webabcd: " + DateTime.Now.ToString()); try { Windows.ApplicationModel.DataTransfer.Clipboard.SetContent(dataPackage); // 保存 DataPackage 对象到剪切板 Windows.ApplicationModel.DataTransfer.Clipboard.Flush(); // 当此 app 关闭后,依然保留剪切板中的数据 lblMsg.Text = "已将内容复制到剪切板"; } catch (Exception ex) { lblMsg.Text = ex.ToString(); } } // 显示剪切板中的文本数据 private async void btnPasteText_Click_1(object sender, RoutedEventArgs e) { // 获取剪切板中的数据 DataPackageView dataPackageView = Windows.ApplicationModel.DataTransfer.Clipboard.GetContent(); // 如果剪切板中有文本数据,则获取并显示该文本 if (dataPackageView.Contains(StandardDataFormats.Text)) { try { string text = await dataPackageView.GetTextAsync(); lblMsg.Text = text; } catch (Exception ex) { lblMsg.Text = ex.ToString(); } } else { lblMsg.Text = "剪切板中无文本内容"; } } // 显示剪切板中包含的数据的格式类型,可能会有 StandardDataFormats 枚举的格式,也可能会有自定义的格式(关于自定义格式可以参见:ShareContract 的 Demo) private void btnShowAvailableFormats_Click_1(object sender, RoutedEventArgs e) { DataPackageView dataPackageView = Windows.ApplicationModel.DataTransfer.Clipboard.GetContent(); if (dataPackageView != null && dataPackageView.AvailableFormats.Count > 0) { var availableFormats = dataPackageView.AvailableFormats.GetEnumerator(); while (availableFormats.MoveNext()) { lblMsg.Text += Environment.NewLine; lblMsg.Text += availableFormats.Current; } } else { lblMsg.Text = "剪切板中无任何内容"; } } // 清除剪切板中的全部数据 private void btnClear_Click_1(object sender, RoutedEventArgs e) { Windows.ApplicationModel.DataTransfer.Clipboard.Clear(); } } }
2、演示如何复制 html 数据到剪切板,以及如何从剪切板中获取 html 数据
Clipboard/CopyHtml.xaml
<Page x:Class="XamlDemo.Clipboard.CopyHtml" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="using:XamlDemo.Clipboard" 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"> <TextBlock Name="lblMsg" FontSize="14.667" /> <Button Name="btnCopyHtml" Content="复制一段 html 到剪切板" Click="btnCopyHtml_Click_1" Margin="0 10 0 0" /> <Button Name="btnPasteHtml" Content="粘贴剪切板中的 html" Click="btnPasteHtml_Click_1" Margin="0 10 0 0" /> </StackPanel> </Grid> </Page>
Clipboard/CopyHtml.xaml.cs
/* * 演示如何复制 html 数据到剪切板,以及如何从剪切板中获取 html 数据 * * HtmlFormatHelper - 在 Clipboard 中传递 html 数据或在 ShareContract 中传递 html 数据时的帮助类 * CreateHtmlFormat() - 封装需要传递的 html 字符串,以便以 html 方式传递数据 * GetStaticFragment() - 解封装传递过来的经过封装的 html 数据,从而获取初始需要传递的 html 字符串 */ using System; using Windows.ApplicationModel.DataTransfer; using Windows.UI.Xaml; using Windows.UI.Xaml.Controls; namespace XamlDemo.Clipboard { public sealed partial class CopyHtml : Page { public CopyHtml() { this.InitializeComponent(); } // 复制 html 字符串到剪切板 private void btnCopyHtml_Click_1(object sender, RoutedEventArgs e) { DataPackage dataPackage = new DataPackage(); // 封装一下需要复制的 html 数据,以便以 html 的方式将数据复制到剪切板 string htmlFormat = HtmlFormatHelper.CreateHtmlFormat("<body>I am webabcd</body>"); dataPackage.SetHtmlFormat(htmlFormat); try { Windows.ApplicationModel.DataTransfer.Clipboard.SetContent(dataPackage); lblMsg.Text = "已将内容复制到剪切板"; } catch (Exception ex) { lblMsg.Text = ex.ToString(); } } // 显示剪切板中的 html 数据 private async void btnPasteHtml_Click_1(object sender, RoutedEventArgs e) { DataPackageView dataPackageView = Windows.ApplicationModel.DataTransfer.Clipboard.GetContent(); if (dataPackageView.Contains(StandardDataFormats.Html)) { try { // 封装后的数据 string htmlFormat = await dataPackageView.GetHtmlFormatAsync(); // 封装前的数据 string htmlFragment = HtmlFormatHelper.GetStaticFragment(htmlFormat); lblMsg.Text = "htmlFormat(封装后的数据): "; lblMsg.Text += Environment.NewLine; lblMsg.Text += htmlFormat; lblMsg.Text += Environment.NewLine; lblMsg.Text += Environment.NewLine; lblMsg.Text += "htmlFragment(封装前的数据): "; lblMsg.Text += Environment.NewLine; lblMsg.Text += htmlFragment; } catch (Exception ex) { lblMsg.Text = ex.ToString(); } } else { lblMsg.Text = "剪切板中无 html 内容"; } } } }
3、演示如何复制图片内容剪切板,以及如何从剪切板中获取图片内容,以及数据的延迟复制
Clipboard/CopyImage.xaml
<Page x:Class="XamlDemo.Clipboard.CopyImage" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="using:XamlDemo.Clipboard" 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"> <TextBlock Name="lblMsg" FontSize="14.667" /> <Image Name="imgBitmap" Stretch="None" HorizontalAlignment="Left" Margin="0 10 0 0" /> <Button Name="btnCopyImage" Content="复制图片内容到剪切板" Click="btnCopyImage_Click_1" Margin="0 10 0 0" /> <Button Name="btnCopyImageWithDeferral" Content="复制数据提供器到剪切板,当“粘贴”操作被触发时由数据提供器生成用于粘贴的图片数据" Click="btnCopyImageWithDeferral_Click_1" Margin="0 10 0 0" /> <Button Name="btnPasteImage" Content="粘贴剪切板中的图片内容" Click="btnPasteImage_Click_1" Margin="0 10 0 0" /> </StackPanel> </Grid> </Page>
Clipboard/CopyImage.xaml.cs
/* * 1、演示如何复制图片内容剪切板,以及如何从剪切板中获取图片内容 * 2、演示如何通过 SetDataProvider() 延迟数据的复制,即在“粘贴”操作触发后由数据提供器生成相关数据 */ using System; using Windows.ApplicationModel.DataTransfer; using Windows.Graphics.Imaging; using Windows.Storage; using Windows.Storage.Streams; using Windows.UI.Core; using Windows.UI.Xaml; using Windows.UI.Xaml.Controls; using Windows.UI.Xaml.Media.Imaging; namespace XamlDemo.Clipboard { public sealed partial class CopyImage : Page { public CopyImage() { this.InitializeComponent(); } // 复制图片内容到剪切板 private void btnCopyImage_Click_1(object sender, RoutedEventArgs e) { DataPackage dataPackage = new DataPackage(); dataPackage.SetBitmap(RandomAccessStreamReference.CreateFromUri(new Uri("ms-appx:///Assets/Logo.png", UriKind.Absolute))); try { Windows.ApplicationModel.DataTransfer.Clipboard.SetContent(dataPackage); lblMsg.Text = "已将内容复制到剪切板"; } catch (Exception ex) { lblMsg.Text = ex.ToString(); } } // 延迟复制 private async void btnCopyImageWithDeferral_Click_1(object sender, RoutedEventArgs e) { StorageFile imageFile = await StorageFile.GetFileFromApplicationUriAsync(new Uri("ms-appx:///Assets/Logo.png", UriKind.Absolute)); DataPackage dataPackage = new DataPackage(); dataPackage.SetDataProvider(StandardDataFormats.Bitmap, async (request) => { /* * 当从剪切板中获取 StandardDataFormats.Bitmap 数据时,会执行到此处以提供相关数据 */ if (imageFile != null) { // 开始异步处理 var deferral = request.GetDeferral(); try { using (var imageStream = await imageFile.OpenAsync(FileAccessMode.Read)) { // 将图片缩小一倍 BitmapDecoder imageDecoder = await BitmapDecoder.CreateAsync(imageStream); var inMemoryStream = new InMemoryRandomAccessStream(); var imageEncoder = await BitmapEncoder.CreateForTranscodingAsync(inMemoryStream, imageDecoder); imageEncoder.BitmapTransform.ScaledWidth = (uint)(imageDecoder.OrientedPixelWidth * 0.5); imageEncoder.BitmapTransform.ScaledHeight = (uint)(imageDecoder.OrientedPixelHeight * 0.5); await imageEncoder.FlushAsync(); // 指定需要复制到剪切板的数据 request.SetData(RandomAccessStreamReference.CreateFromStream(inMemoryStream)); await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () => { lblMsg.Text = "数据已生成"; }); } } finally { // 通知系统已完成异步操作 deferral.Complete(); } } }); try { Windows.ApplicationModel.DataTransfer.Clipboard.SetContent(dataPackage); lblMsg.Text = "已将数据提供器复制到剪切板,在“粘贴”操作时才会生成数据"; } catch (Exception ex) { lblMsg.Text = ex.ToString(); } } // 显示剪切板中的图片内容 private async void btnPasteImage_Click_1(object sender, RoutedEventArgs e) { DataPackageView dataPackageView = Windows.ApplicationModel.DataTransfer.Clipboard.GetContent(); if (dataPackageView.Contains(StandardDataFormats.Bitmap)) { try { IRandomAccessStreamReference randomStream = await dataPackageView.GetBitmapAsync(); if (randomStream != null) { using (IRandomAccessStreamWithContentType imageStream = await randomStream.OpenReadAsync()) { BitmapImage bitmapImage = new BitmapImage(); bitmapImage.SetSource(imageStream); imgBitmap.Source = bitmapImage; } } } catch (Exception ex) { lblMsg.Text = ex.ToString(); } } else { lblMsg.Text = "剪切板中无 bitmap 内容"; } } } }
4、演示如何复制指定的文件到剪切板,以及如何从剪切板中获取文件并保存到指定的路径
Clipboard/CopyFile.xaml
<Page x:Class="XamlDemo.Clipboard.CopyFile" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="using:XamlDemo.Clipboard" 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"> <TextBlock Name="lblMsg" FontSize="14.667" TextWrapping="Wrap" Margin="0 0 10 0" /> <Button Name="btnCopyFile" Content="复制一个文件到剪切板" Click="btnCopyFile_Click_1" Margin="0 10 0 0" /> <Button Name="btnPasteFile" Content="粘贴剪切板中的文件到指定的路径" Click="btnPasteFile_Click_1" Margin="0 10 0 0" /> </StackPanel> </Grid> </Page>
Clipboard/CopyFile.xaml.cs
/* * 演示如何复制指定的文件到剪切板,以及如何从剪切板中获取文件并保存到指定的路径 */ using System; using System.Linq; using System.Collections.Generic; using Windows.ApplicationModel.DataTransfer; using Windows.Storage; using Windows.UI.Xaml; using Windows.UI.Xaml.Controls; namespace XamlDemo.Clipboard { public sealed partial class CopyFile : Page { public CopyFile() { this.InitializeComponent(); } // 保存文件到剪切板 private async void btnCopyFile_Click_1(object sender, RoutedEventArgs e) { StorageFile file = await ApplicationData.Current.LocalFolder.CreateFileAsync(@"webabcdTest\clipboard.txt", CreationCollisionOption.ReplaceExisting); await FileIO.WriteTextAsync(file, "I am webabcd: " + DateTime.Now.ToString()); DataPackage dataPackage = new DataPackage(); dataPackage.SetStorageItems(new List<StorageFile>() { file }); dataPackage.RequestedOperation = DataPackageOperation.Move; try { Windows.ApplicationModel.DataTransfer.Clipboard.SetContent(dataPackage); lblMsg.Text = "已将文件复制到剪切板"; } catch (Exception ex) { lblMsg.Text = ex.ToString(); } } // 从剪切板中获取文件并保存到指定的路径 private async void btnPasteFile_Click_1(object sender, RoutedEventArgs e) { DataPackageView dataPackageView = Windows.ApplicationModel.DataTransfer.Clipboard.GetContent(); if (dataPackageView.Contains(StandardDataFormats.StorageItems)) { try { IReadOnlyList<IStorageItem> storageItems = await dataPackageView.GetStorageItemsAsync(); StorageFile file = storageItems.First() as StorageFile; if (file != null) { StorageFile newFile = await file.CopyAsync(ApplicationData.Current.TemporaryFolder, file.Name, NameCollisionOption.ReplaceExisting); if (newFile != null) { lblMsg.Text = string.Format("已将文件从{0}复制到{1}", file.Path, newFile.Path); } } } catch (Exception ex) { lblMsg.Text = ex.ToString(); } } else { lblMsg.Text = "剪切板中无 StorageItems 内容"; } } } }
OK
[源码下载]