在WP 8.1中只有Silverlight App支持操作剪贴板的API,Runtime App并不支持。不过,在WP 10中也引入了可以操作剪贴板的API。
顺便说点题外话,有人会说,我8.1的开发还没学了,Win10又来了,那我怎么学得过来?放心,学得过来的D,因为只要你对有WPF的基础,再加上对RT App的学习就足够应付Win 10上的app开发了。实际上,面向10的API都是在8.1的基础上增加一点新的API而已,你不需要学习新的知识就可以直接玩10的开发了。
而且,你在10上依然可以继续使用8.1的API。当然我指的是RuntimeApp,Silverlight的API有可能将来不用。虽然RT API使用起来看着和以往的.net类库没什么区别,而实际上RT库是基于COM的形式存在的,如果你足够细心的话,通过在RT应用发生异常的时候,你都会看到来自COM的HRESULT值,在调用试的时候,你也能看到许多RT库的类型显示为COM对象。这是很有力的证据。
所以我大胆估计,RT库就是为了优化性能而出现的,随同新的编译器和.net 4.6的发布,.net的性能会有更可观的优化,这是肯定的事情。而对于Win 10,微软也确实在努力优化,尽管现在是预览版,问题肯定会多一些,但我使用Build 10041后,确实感觉到反应速度快了很多,因为我的笔记本配置不算很高,对性能是有一点儿敏感的。
好了,屁话说得太多了,为了避免大家向我扔石头(如果你要扔的话,建议你扔玛瑙),下面我再简单说说“通用应用程序项目”(UAP),耍W10开发必须了解这个。
通过框架是在面向8.1(VS UD2)的时候出现,在这个通用应用中是分为三个项目的,相信大家有所了解。
1、面向Windows Phone的应用。
2、面向Windows的应用。
3、共享代码。
平台共用的代码通常会放到第三个项目中,不过这样做有时候也觉得代码管理起来不方便。
在面向10的项目中直接就合并成一个项目,而不再按平台分开,直接就统一到一个项目中,生成的应用程序你喜欢在手机上运行也行,在平板上运行也行,没有平板在普通PC上耍也可以。
在VS的“对象浏览器”窗口中,你会发现有一个名为Universal App Platform的子集,它就是包含通用API的各个库的集合,把多个平台可以共享的API都放到一起了,开发者就不必去管理共享代码了。
当然你也可以继续使用面向8.1的项目,这些项目模板在“Store Apps”节点下面。
好了,有了上面的介绍,再进入咱们今天的正题就轻松了。
首先,参照上面截图自己新项一个Windows 10的空白应用程序项目。
这里我给出的示例比较简单,就是复制和粘贴一张图片。还是和以前一样,用XAML代码来布局UI。
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<StackPanel Orientation="Horizontal" VerticalAlignment="Top">
<Image Name="imgSrc" Width="200" Height="200" />
<Button Content="复制" Click="OnCopy"/>
</StackPanel>
<StackPanel Grid.Row="1" VerticalAlignment="Top" Orientation="Horizontal">
<Image Name="imgDes" Width="200" Height="200"/>
<Button Content="粘贴" Click="OnSet"/>
</StackPanel>
</Grid>
然后在页面加载后从项目目录中读出一个图像文件。
public MainPage()
{
this.InitializeComponent();
this.Loaded += OnPageLoaded;
}
private async void OnPageLoaded(object sender, RoutedEventArgs e)
{
// 加载项目中的图片
StorageFile imgFile = await StorageFile.GetFileFromApplicationUriAsync(new Uri("ms-appx:///1.jpg"));
// 打开文件流
IRandomAccessStream stream = await imgFile.OpenReadAsync();
// 显示图像
BitmapImage bmp = new BitmapImage();
bmp.DecodePixelWidth = 250;
await bmp.SetSourceAsync(stream);
this.imgSrc.Source = bmp;
// 将流对象放入Tag属性中暂存,稍后会用得上
this.Tag = RandomAccessStreamReference.CreateFromStream(stream.CloneStream());
stream.Dispose();
}
文件流一般来说,用完就应该马上关闭,不要借着别人的钱不还,但是,我们随后要把文件流中的内容写入剪贴板,而文件流被关闭后又无法操作了,于是,我调用CloneStream方法直接将流复制一份,这样原来的文件流可以关闭了,并且不影响后面的操作。并且赋值给Tag属性,随后在其他代码中可以从Tag属性取出流对象。
下面代码将流中的数据写入剪贴板:
// 从Tag属性中取出文件流
RandomAccessStreamReference stream = this.Tag as RandomAccessStreamReference;
if (stream != null)
{
// 创建数据包装
DataPackage package = new DataPackage();
// 放入内容
package.SetBitmap(stream);
// 将数据放入ClipBoard
Clipboard.SetContent(package);
}
下面代码从剪贴板读出数据,即“粘贴”:
// 从clip board中取出数据
DataPackageView pack = Clipboard.GetContent();
// 如果Count为0,表示剪贴板中没有可用的内容
if (pack.AvailableFormats.Count == 0)
{
return;
}
else
{
foreach (string format in pack.AvailableFormats)
{
System.Diagnostics.Debug.WriteLine(format);
}
}
// 验证格式是否正确
if (pack.AvailableFormats.Where(s=>s == StandardDataFormats.Bitmap).Count() > 0)
{
// 读出流
RandomAccessStreamReference streamref = await pack.GetBitmapAsync();
using (IRandomAccessStream streamIn = await streamref.OpenReadAsync())
{
// 显示图片
BitmapImage bmp = new BitmapImage();
bmp.DecodePixelWidth = 250;
await bmp.SetSourceAsync(streamIn);
this.imgDes.Source = bmp;
}
Clipboard.Clear(); //清除剪贴板中的内容
}
完事了,例子就这么简单。结果如下图。
下面就给大家介绍一下知识点。
1、操作剪贴板用的是Clipboard类(命名空间:Windows.ApplicationModel.DataTransfer),这个类是静态的,也就是说它的成员也是静态的,不用new就可以直接用。
2、要向剪贴板写入数据,就用SetContent方法,要从剪贴板中读出数据就用GetContent方法。
3、在写入的时候,数据是通过DataPackage类来包装的,而读取时则是通过DataPackageView类来操作的。那么,这两个家伙有什么区别呢?
看到了吧,一个是SetXXXXX,一个是GetXXXXXX。因此,DataPackage是用于创建数据包的,而DataPackageView是用来读数据包的。
4、操作也不难,写什么类型的数据就用什么方法,如写文本用SetText,读文本用GetTextAsync。本示例是读写图像,所以写的时候调用SetBitmap方法,读的时候调用GetBitmapAsync方法。注意,图像的内容是用RandomAccessStreamReference类来封装的流对象,通过静态的CreateFromStream方法可以从现存的流创建新的RandomAccessStreamReference实例。
5、用DataPackageView方法检索内容之前,应当访问AvailableFormats属性,检查一下剪贴板上的内容是否可用,或者是空的。该属性是一个字符串列表,如果列表中元素个数为0,说明剪贴板中的数据无效。
6、Clipboard.Clear()方法清理剪贴板中的内容。
随后,我把示例源代码上传,大家可以下载下来玩玩。
===============================
这里补充一下,现在Win10和VS2015都是预览版,如果你害怕出现小问题,那你得谨慎使用,如果你像我这样,不干正经事,只是体验一下,可以在电脑上装来耍耍。我比较穷,只有一台笔记本,买不起新电脑,就花几百块钱买了一台国产的山寨平板,8寸的屏幕是小了点,不过还是可以当电脑用的。所以我的笔记本用来开发实验,山寨板用来看看电子书,看看电影电视剧,和林妹妹聊聊天,还是可以用的。
要注意的是,装Win10预览版一定要装最新发布的Build 10041版本,否则面向Win 10通用应用的XAML设计器无法加载。一开始我也犯了这个错误,后来查看一下清单中的XML文件,才发现它要求的是Build 10030以上的版本,而大于这个版本的就只有最近发布的Build 10041了。
另外,有一件事,需要向各位读者表示道歉的,有位细心的朋友发现《精通C# 5.0》中第54页,定义的Book结构有一个属性应该是ISBN,我弄错为ISBM。这是我的疏忽,偏偏编辑在审稿时没有注意,我在定稿时也没看到。因此,向各位表示歉意。