C# 窗体应用程序 获取剪贴板格式侦听器,以便在用户粘贴内容时仅接收消息

本文关键字:消息 用户 剪贴板 获取 应用程序 窗体 格式 侦听器 | 更新日期: 2023-09-27 18:31:39

我正在做一个项目,该项目跟踪用户必须复制和过去数据的频率,因此如果用户不断从一个表单粘贴到另一个表单,我们可以自动化零件,以便表单自动填充。这正在企业呼叫中心用于质量保证人员。表格做了一堆其他的事情,但对于这个问题来说并不重要。

就目前而言,表单应用程序使用键盘挂钩来捕获用户何时执行 control+v。当它捕获 control+v 组合时,它会抓取剪贴板的内容并将其发送到程序的处理部分。这一切都运行良好,但是当用户右键单击复制/粘贴时,它无法拾取,我必须为此走不同的路线。

为了尝试捕获用户何时使用右键单击复制/粘贴消息,我认为收听剪贴板进行更改同样容易。我用AddClipboardFormatListener(this.Handle);和 WndProc 方法的覆盖完成了此操作,如下所示:

protected override void WndProc(ref Message m)
    {
        base.WndProc(ref m);
        if (m.Msg == WM_CLIPBOARDUPDATE)
        {
            IDataObject iData = Clipboard.GetDataObject();      // Clipboard's data.
            uint processID = 0;
            IntPtr ForeGroundWindowHandle = GetForegroundWindow();
            GetWindowThreadProcessId(ForeGroundWindowHandle, out processID);
            if (iData.GetDataPresent(DataFormats.Text))
            {
                string text = (string)iData.GetData(DataFormats.Text);
                ClipboardEventQueue.Enqueue(new ClipboardDataStorage(text, Convert.ToInt32(processID)));
                LogWrite(text); 
            }
            else if (iData.GetDataPresent(DataFormats.Bitmap))
            {
                Bitmap image = (Bitmap)iData.GetData(DataFormats.Bitmap);
                ClipboardEventQueue.Enqueue(new ClipboardDataStorage("Clipboard copied an image", Convert.ToInt32(processID)));
                LogWrite("Clipboard copied an image");
            }
        }
    }
问题是仅当用户

复制到剪贴板时,才会发送WM_CLIPBOARDUPDATE消息。我只关心他们实际粘贴的内容。有没有办法在用户粘贴某些内容时获得消息,或者我是否必须使用鼠标钩子通过跟踪右键单击来完成此操作?

C# 窗体应用程序 获取剪贴板格式侦听器,以便在用户粘贴内容时仅接收消息

我想在任何粘贴完成时抓住。因此,如果他们打开一个 Chrome 中的网页并复制街道地址,然后将其粘贴到 其他一些程序,我也想捕捉那个糊状物。

不幸的是,剪贴板并不完全允许这种功能。剪贴板基于两个主要事件 - 广告和请求。假设我们有应用程序"X"和"Y"正在运行。所有其他正在运行的应用程序都可以看到 X 何时播发剪贴板上可用的新数据。WM_CLIPBOARDUPDATE消息将发送到每个应用程序。但是当Y请求这些数据时,只有X知道。WM_RENDERFORMAT消息直接从 X 转到 Y。

作为一种非常笨拙的解决方法,您可以收听广告。每当有人宣传新数据时,您都会向他们请求所有数据。然后,控制剪贴板,并再次播发数据。这样,您就可以窃取数据的所有权,因此您可以确定何时有人从剪贴板请求。按照此处的教程将窗口设置为剪贴板查看器。在他们的 WndProc 循环中,试试这个:

protected override void WndProc(ref Message m)
{
    ...
    if (m.Msg == WM_DRAWCLIPBOARD)
    {
        IDataObject iData = Clipboard.GetDataObject();
        ClipBoard.SetDataObject(iData);
    }
    if (m.Msg == WM_RENDERFORMAT)
        Console.WriteLine("Clipboard data requested");
}