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对象贴上去的。

 

posted @ 2017-09-02 11:41  guogangj  阅读(11292)  评论(0编辑  收藏