zoukankan      html  css  js  c++  java
  • 【WP开发】读写剪贴板

    在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()方法清理剪贴板中的内容。

    随后,我把示例源代码上传,大家可以下载下来玩玩。

    下载地址:http://files.cnblogs.com/files/tcjiaan/ClipboardApp.zip

    ===============================

    这里补充一下,现在Win10和VS2015都是预览版,如果你害怕出现小问题,那你得谨慎使用,如果你像我这样,不干正经事,只是体验一下,可以在电脑上装来耍耍。我比较穷,只有一台笔记本,买不起新电脑,就花几百块钱买了一台国产的山寨平板,8寸的屏幕是小了点,不过还是可以当电脑用的。所以我的笔记本用来开发实验,山寨板用来看看电子书,看看电影电视剧,和林妹妹聊聊天,还是可以用的。

    要注意的是,装Win10预览版一定要装最新发布的Build 10041版本,否则面向Win 10通用应用的XAML设计器无法加载。一开始我也犯了这个错误,后来查看一下清单中的XML文件,才发现它要求的是Build 10030以上的版本,而大于这个版本的就只有最近发布的Build 10041了。

    另外,有一件事,需要向各位读者表示道歉的,有位细心的朋友发现《精通C# 5.0》中第54页,定义的Book结构有一个属性应该是ISBN,我弄错为ISBM。这是我的疏忽,偏偏编辑在审稿时没有注意,我在定稿时也没看到。因此,向各位表示歉意。

  • 相关阅读:
    使用FolderBrowserDialog组件选择文件夹
    使用OpenFileDialog组件打开多个文
    使用OpenFileDialog组件打开对话框
    获取弹出对话框的相关返回值
    PAT 甲级 1139 First Contact (30 分)
    PAT 甲级 1139 First Contact (30 分)
    PAT 甲级 1138 Postorder Traversal (25 分)
    PAT 甲级 1138 Postorder Traversal (25 分)
    PAT 甲级 1137 Final Grading (25 分)
    PAT 甲级 1137 Final Grading (25 分)
  • 原文地址:https://www.cnblogs.com/tcjiaan/p/4369128.html
Copyright © 2011-2022 走看看