zoukankan      html  css  js  c++  java
  • C# clipboard

    C#操作剪切板(Clipboard)

     

    剪切板是Windows系统提供的功能,从我最早接触到的Windows 3.2版本开始,就一直带着了。以前使用C++的时候,是直接使用Windows API对其进行操作的,到了.NET下,在WinForm中也有一个对剪切板的封装类,即System.Windows.Forms.Clipboard,这个类其实是通过COM组件间接地使用剪切板的,我个人觉得COM是一个设计非常糟糕的东西,难懂坑多还不可移植,但微软现存的大量代码又是基于COM的,所以又无法彻底舍弃,关于不可移植这个并不难理解,前面说了,剪切板是Windows提供的功能,你在Linux下,或者在MacOS下,尽管有类似的功能,但跟Windows的肯定不同,所以最新的.NET Core中是不能使用剪切板功能的。

    往剪切板里存取字符串

    字符串是最最常用的数据对象了,我们就往剪切板里写一个字符串吧,我总结了一下,见下表:

    方法1 Clipboard.SetText(str);  很可能有问题
    方法2 Clipboard.SetData(DataFormats.Text,str);  很可能有问题
    方法3 Clipboard.SetDataObject(str);  大多数时候没问题

    嗯?怎么这么不确定?确实如此,这是我进行了大量试验的结果,且程序在调试和非调试中还有不同的表现,可能出现的异常有以下两个:

    (异常1:COMException)

    (异常2:ExternalException)

    两个异常都没有进一步的提示信息,异常的原因很类似,就是剪切板访问不了,而我使用方法3的时候,在非调试状态下还没发现过什么问题。我实在找不到进一步的规律了,先这样用吧。

    那么如何从剪切板获取字符串呢?对应的,有两种方法:

    方法1 string str = (string)Clipboard.GetData(DataFormats.Text) 很可能有问题
    方法2 string str = Clipboard.GetText(); 大多数时候没问题

    具体原因我同样不太清楚,这似乎是微软留下的一个bug,SO上有个讨论,可以去看看:StackOverflow

    另外还有两点需要注意:

    1. 方法3这种往剪切板里写文本内容的方式,在这个程序结束之后,剪切板内容将会失效,要使得程序结束后剪切板内容继续有效的话,得使用Clipboard.SetDataObject(str, true);这个方法,第二个参数true表示让剪切板内容在程序结束后继续有效,但我发现加上这个参数之后,增加了出现异常的可能性。
    2. 必须在给程序的入口函数(通常是Main函数)加上STAThreadAttribute这个注解,否则对剪切板的访问会报错:在可以调用 OLE 之前,必须将当前线程设置为单线程单元(STA)模式。

    往剪切板里存取自定义数据

    C#的对象的数据结构并不能为剪切板所理解,所以你要把你自定义的数据放到剪切板去的话要把它序列化,在实际操作中,是要你提供一个“可序列化”的对象,下面是个简单的例子:

    复制代码
    [Serializable]
    public class User {
        public int age { get; set; }
        public string name { get; set; }
    }
    
    class Program {
        [STAThread]
        static void Main(string[] args) {
            User userIn = new User();
            userIn.name = "Jack";
            userIn.age = 18;
            Clipboard.SetData("mydata", userIn);
            User userOut = (User)Clipboard.GetData("mydata");
            Console.WriteLine(userOut.name +" | " + userOut.age);
        }
    }
    复制代码

    注意User这个类前面的Serializable注解,如果没有这个注解,是没法成功将对象写入剪切板的。如果数据比较复杂,可以考虑把数据自行序列化到一个Stream对象去,再把Stream对象写入剪切板,获取的时候对Stream对象自行反序列化,还原数据。例子就不写了。

    最后要注意的一点是由于这里的数据类型是“mydata”,你也可以指定别的名字,这种类型数据只有你自己的程序能读懂,也就是说,你是不能打开记事本或者Photoshop,直接把你这个User对象贴上去的。

  • 相关阅读:
    C#控件随窗体大小改变而改变
    Java泛型
    php的stristr()函数,查找字符
    java设计模式之桥梁模式(Bridge)
    怎样从本地删除git远程仓库里面的文件
    VS code 修改主题设置代码对其齐线
    vue+webpack安装sass过程中遇到权限不够,直接删除node_modus文件夹重新安装,node_modus先取得管理员权限才能删
    转:git合并冲突解决方法
    git命令行解决冲突文件步骤
    dos常用命令
  • 原文地址:https://www.cnblogs.com/lingdanglfw/p/14091107.html
Copyright © 2011-2022 走看看