大家新年好!今天是除夕夜,写篇文章润润手。
今天学习一下WINDOWS中的一个API方法“AddClipboardFormatListener”,用于实时监控剪切板的变化,虽然.NET中有剪切板类,但想达到实时监控的效果还得配合上Timer定期如50毫秒检查一次,我觉得设计上就不是很合理,WINDOWS上其实调用“AddClipboardFormatListener”API就能够满足我们,并且不是用Timer这种蠢办法。
话不多说,上干货。
using System;
using System.Runtime.InteropServices;
using System.Windows.Forms;
public class ClipboardMonitor : Control
{
public event EventHandler ClipboardUpdate;
public ClipboardMonitor()
{
ClipboardUpdate += (sender, args) => { };
NativeMethods.SetParent(Handle, NativeMethods.HWND_MESSAGE);
NativeMethods.AddClipboardFormatListener(Handle);
}
protected override void WndProc(ref Message m)
{
const int WM_CLIPBOARDUPDATE = 0x031D;
if (m.Msg == WM_CLIPBOARDUPDATE)
{
OnClipboardUpdate(EventArgs.Empty);
}
base.WndProc(ref m);
}
protected virtual void OnClipboardUpdate(EventArgs e)
{
ClipboardUpdate?.Invoke(this, e);
}
protected override void Dispose(bool disposing)
{
NativeMethods.RemoveClipboardFormatListener(Handle);
base.Dispose(disposing);
}
private static class NativeMethods
{
public static readonly IntPtr HWND_MESSAGE = new IntPtr(-3);
[DllImport("user32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool AddClipboardFormatListener(IntPtr hwnd);
[DllImport("user32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool RemoveClipboardFormatListener(IntPtr hwnd);
[DllImport("user32.dll", SetLastError = true)]
public static extern IntPtr SetParent(IntPtr hWndChild, IntPtr hWndNewParent);
}
}
接下来讲解一下这段代码,在这个自定义Control中,我们创建了一个隐藏的Control,并使用AddClipboardFormatListener函数将其注册为剪切板的监听器。当剪切板的内容发生变化时,Windows会发送一个WM_CLIPBOARDUPDATE消息到这个Control,我们可以在WndProc方法中捕获这个消息,并触发ClipboardUpdate事件。
这段代码有个小技巧,AddClipboardFormatListener函数需要一个顶级窗口的句柄作为参数。在这个例子中,我们使用SetParent函数将Control的父窗口设置为HWND_MESSAGE,值为-3,这个值代表是一个特殊的窗口,用于接收没有父窗口的消息。
另外,由于AddClipboardFormatListener函数会增加对窗口的引用计数,所以在Control被销毁时,我们需要使用RemoveClipboardFormatListener函数来取消监听,否则可能会导致内存泄漏。
本文暂时没有评论,来添加一个吧(●'◡'●)