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);
}
简单吧