C#监控剪切板[转帖]

来源:互联网 发布:卖正品猫粮的淘宝店 编辑:程序博客网 时间:2024/06/05 09:23

C#监控剪切板

2009-11-24 16:44

  昨天看到一同学用灵格斯复制一个单词,发现复制的单词自动增加到了另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);

        }

 

简单吧

原创粉丝点击