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。这是我的疏忽,偏偏编辑在审稿时没有注意,我在定稿时也没看到。因此,向各位表示歉意。

  • 相关阅读:
    .NET Worker Service 如何优雅退出
    .NET 中的 Worker Service 入门介绍
    一图看懂 ASP.NET Core 中的服务生命周期
    创建支持依赖注入、Serilog 日志和 AppSettings 的 .NET 5 控制台应用
    Asp.Net Core 5 REST API 使用 RefreshToken 刷新 JWT
    Asp.Net Core 5 REST API 使用 JWT 身份验证
    Asp.Net Core 5 REST API
    JWT 介绍
    在 .NET Core 5 中集成 Create React app
    在 .NET Core 中构建 REST API
  • 原文地址:https://www.cnblogs.com/tcjiaan/p/4369128.html
Copyright © 2011-2022 走看看