Windows系统剪切板内容变化监控

思路

Windows操作系统是基于“消息”机制运行,任何行为都有与之对应的消息,剪切板的内容变化也不列外,当剪切板的内容发生变化时会发出 WM_CLIPBOARDUPDATE 消息,所以我们的思路就是监听这个消息,如果收到了WM_CLIPBOARDUPDATE就说明是剪切板发生变化了,此时再去读取剪切板的内容即可

实现步骤

首先通过User32.dll 中的AddClipboardFormatListener 函数,将我们自己程序的主窗口句柄添加到剪切板的侦听器列表中,这样每当剪贴板的内容发生更改时,该窗口将发布WM_CLIPBOARDUPDATE 消息

		[DllImport("User32.dll")]
        private static extern bool AddClipboardFormatListener(IntPtr hwnd);


如果添加成功再通过HwndSource类中的AddHook函数添加一个委托,当接收到消息时会执行该委托函数,在该函数中去判断消息是否为WM_CLIPBOARDUPDATE,WM_CLIPBOARDUPDATE的值是0x031D

封装帮助类

在我的工作中经常会用到剪切板的监控,因此封装为一个帮助类更方便

public class ClipboardMonitHelper : IDisposable
    {
        public Action<string>? ClipboardUpdate;

        private HwndSource _hwndSource;

        private const int WM_CLIPBOARDUPDATE = 0x031D;

        public ClipboardMonitHelper(Window window)
        {
            WindowInteropHelper helper = new WindowInteropHelper(window);
            _hwndSource = HwndSource.FromHwnd(helper.Handle);

            AddHook();
        }

        /// <summary>
        /// 将指定窗口的句柄添加到剪切板的侦听器列表中
        /// 将窗口添加到剪贴板格式侦听器列表后,每当剪贴板的内容发生更改时,该窗口将发布 WM_CLIPBOARDUPDATE 消息。
        /// </summary>
        /// <param name="hwnd"></param>
        /// <returns></returns>
        [DllImport("User32.dll")]
        private static extern bool AddClipboardFormatListener(IntPtr hwnd);

        [DllImport("User32.dll")]
        private static extern bool RemoveClipboardFormatListener(IntPtr hwnd);

        private void AddHook()
        {
            bool r = AddClipboardFormatListener(_hwndSource.Handle);
            if (r)
            {
                _hwndSource.AddHook(new HwndSourceHook(OnHooked));
            }
        }

        private void RemoveHook()
        {
            bool r = RemoveClipboardFormatListener(_hwndSource.Handle);
            if (r)
            {
                _hwndSource.RemoveHook(new HwndSourceHook(OnHooked));
            }
        }

        private IntPtr OnHooked(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
        {
            if (msg == WM_CLIPBOARDUPDATE)
            {
                string txt = Clipboard.GetText();
                ClipboardUpdate?.Invoke(txt);
            }
            return IntPtr.Zero;
        }

        public void Dispose()
        {
            RemoveHook();
        }
    }

使用帮助类

 public partial class MainWindow : Window
    {
        private ClipboardMonitHelper clipboardMonit;

        public MainWindow()
        {
            InitializeComponent();
            this.Loaded += MainWindow_Loaded;
        }

        private void MainWindow_Loaded(object sender, RoutedEventArgs e)
        {
            clipboardMonit = new ClipboardMonitHelper(this);
            clipboardMonit.ClipboardUpdate += OnUpdate;
        }

        private void OnUpdate(string obj)
        {
            Debug.WriteLine(obj);
        }
    }

特别要说明的是:要在Loaded 事件中去实例化帮助类,帮助类的构造需要传入当前程序的主窗体,然而Loaded 完成时才能生成窗体,因此需要等主窗体加载完成后才能去实例化

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值