C#监控剪切板

  昨天看到一同学用灵格斯复制一个单词,发现复制的单词自动增加到了另C#写的程序里面去了。一时感觉还挺新鲜的,就想探讨一下。 

  这个功能稍微一想就可以推想是不是监控了剪切板来实现的。一问果然是这样。嗯今天无聊就想自己写个来试试。要想监控剪切板其实只要使用几个剪切板相关的API函数就可以了。跟这个功能相关的要用到下面两个函数:SetClipboardViewer,ChangClipboardChain。SetClipboardViewer函数是为剪切板添加一个监控的窗口,剪切板维护了一个监控它的链表,每当有复制的时候,剪切板就会向这些窗口发送一个WM_DRAWCLPBOARD消息,这个消息里包含了下一个要通知到的窗口,每个接收到这个消息的窗口都应该保存一个下一个要通知的窗口,当它接收到WM_DRAWCLPBOARD时应该继续发送一个WM_DRAWCLPBOARD消息给下一个要通知的窗口。SetClipboardViewer返回一个监控剪切板的最前的窗口的句柄。当一个窗口不需要监控剪切板时可以使用ChangClipboardChain来改变剪切板消息的发送流程。当一个窗口要去掉对剪切板的监控的时候,系统会发送一个WM_CHANGCBCHAIN消息通知其他窗口要删除一个监控的窗口。这个窗口的wParam保存了要删除的窗口的句柄,lParam保存了这个要删除窗口的下一个窗口的句柄即下次要发送WM_DRAWCLPBOARD时,你应该发给它了,所以你要在WM_CHANGCBCHAIN的时候更新保存的下一个窗口的句柄。 

  好了原理就是上面说的那么简单,那么这里给出C#的实现版本。

namespace ClipboardMonitor
{
    public partial class Form1 : Form
    {
        [DllImport("user32.dll")]
        protected static extern int SetClipboardViewer(int hWndViewer);
        [DllImport("user32.dll")]
        protected static extern bool ChangeClipboardChain(IntPtr hWndResume,IntPtr hWndNext);
        [DllImport("user32.dll")]
        protected static extern int SendMessage(IntPtr hWnd, int nMsg, IntPtr wParam, IntPtr lParam);
 
        IntPtr hNextClipboardViewer;//下一个监视的窗口
 
        void ShowNotify()
        {
            MessageBox.Show(Clipboard.GetText());
        }
        public Form1()
        {
            InitializeComponent();
            hNextClipboardViewer = (IntPtr)SetClipboardViewer((int)this.Handle);
        }
 
        protected override void WndProc(ref Message m)
        {
            const int WM_DRAWCLPBORAD = 0x308;
            const int WM_CHANGCBCHAIN = 0X030D;
 
            switch (m.Msg)
            {
                case WM_DRAWCLPBORAD:
                    if (Clipboard.ContainsText())
                    {//包含文本格式
                        ShowNotify();
                    }
                    SendMessage(hNextClipboardViewer, m.Msg, m.WParam, m.LParam);
                    break;
                case WM_CHANGCBCHAIN:
                    if (hNextClipboardViewer == m.WParam)
                    {//更新要发送消息的下一个窗口的句柄
                        hNextClipboardViewer = m.LParam;
                    }
                    else
                    {
                        SendMessage(hNextClipboardViewer, m.Msg, m.WParam, m.LParam);
                    }
                    break;
                default:
                  base.WndProc(ref m);
                     break;
            }
        }
    }
}

在关闭窗口的时候:

protected override void Dispose(bool disposing)
        {
            if (disposing & (components != null))
            {
                ChangeClipboardChain(this.Handle, hNextClipboardViewer);
                components.Dispose();
            }
            base.Dispose(disposing);
        }

 简单吧