How can I implement a copy handler that catches the paste event?

Mike Weaver 0 Reputation points
2024-01-03T19:19:25.45+00:00

I have tried to format the code below to copy a file/directory when the paste event is triggered, but it gives me an error with the code below. Is there a way to implement this properly to monitor files and directories before they are copied? This is the best example that I could find that monitors paste events, but I could not run the code without getting an error. I would rather not use a fileSystemWatcher if at all possible.

Thanks!

The error comes on the first line posted here below:

        clipboardViewerNext = SetClipboardViewer(Form.ActiveForm.Handle);
using System;
using System.IO;
using System.Windows.Forms;

public partial class CopyHookForm : Form
{
    public CopyHookForm()
    {
        InitializeComponent();
    }

    private void Form1_Load(object sender, EventArgs e)
    {
        // Subscribe to the clipboard's content changed event
        ClipboardMonitor.ClipboardChanged += ClipboardMonitor_ClipboardChanged;
    }

    private void ClipboardMonitor_ClipboardChanged(object sender, EventArgs e)
    {
        // Check if the clipboard contains file or folder data
        if (Clipboard.ContainsFileDropList())
        {
            var files = Clipboard.GetFileDropList();

            foreach (var file in files)
            {
                try
                {
                    if (File.Exists(file))
                    {
                        // Copy file to the current directory
                        string destinationFile = Path.Combine(Environment.CurrentDirectory, Path.GetFileName(file));
                        File.Copy(file, destinationFile, true);
                        MessageBox.Show($"File copied to: {destinationFile}", "File Copied", MessageBoxButtons.OK, MessageBoxIcon.Information);
                    }
                    else if (Directory.Exists(file))
                    {
                        // Copy folder to the current directory
                        string destinationFolder = Path.Combine(Environment.CurrentDirectory, Path.GetFileName(file));
                        CopyFolder(file, destinationFolder);
                        MessageBox.Show($"Folder copied to: {destinationFolder}", "Folder Copied", MessageBoxButtons.OK, MessageBoxIcon.Information);
                    }
                }
                catch (Exception ex)
                {
                    MessageBox.Show($"Error copying {file}: {ex.Message}", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                }
            }
        }
    }

    private void CopyFolder(string sourceFolder, string destinationFolder)
    {
        if (!Directory.Exists(destinationFolder))
        {
            Directory.CreateDirectory(destinationFolder);
        }

        foreach (var file in Directory.GetFiles(sourceFolder))
        {
            string destinationFile = Path.Combine(destinationFolder, Path.GetFileName(file));
            File.Copy(file, destinationFile, true);
        }

        foreach (var subfolder in Directory.GetDirectories(sourceFolder))
        {
            string destinationSubfolder = Path.Combine(destinationFolder, Path.GetFileName(subfolder));
            CopyFolder(subfolder, destinationSubfolder);
        }
    }
}

public static class ClipboardMonitor
{
    public static event EventHandler ClipboardChanged;

    private static IntPtr clipboardViewerNext;

    public static void Start()
    {
        clipboardViewerNext = SetClipboardViewer(Form.ActiveForm.Handle);
    }

    public static void Stop()
    {
        ChangeClipboardChain(Form.ActiveForm.Handle, clipboardViewerNext);
    }

    [DllImport("user32.dll", SetLastError = true)]
    private static extern IntPtr SetClipboardViewer(IntPtr hWndNewViewer);

    [DllImport("user32.dll", SetLastError = true)]
    [return: MarshalAs(UnmanagedType.Bool)]
    private static extern bool ChangeClipboardChain(IntPtr hWndRemove, IntPtr hWndNewNext);

    [DllImport("user32.dll", SetLastError = true)]
    private static extern int SendMessage(IntPtr hWnd, int Msg, IntPtr wParam, IntPtr lParam);

    private const int WM_DRAWCLIPBOARD = 0x308;
    private const int WM_CHANGECBCHAIN = 0x30D;

    public static void WndProc(ref Message m)
    {
        switch (m.Msg)
        {
            case WM_DRAWCLIPBOARD:
                ClipboardChanged?.Invoke(null, EventArgs.Empty);
                SendMessage(clipboardViewerNext, m.Msg, m.WParam, m.LParam);
                break;

            case WM_CHANGECBCHAIN:
                if (m.WParam == clipboardViewerNext)
                {
                    clipboardViewerNext = m.LParam;
                }
                else
                {
                    SendMessage(clipboardViewerNext, m.Msg, m.WParam, m.LParam);
                }
                break;
        }
    }
}

class Program
{
    static void Main()
    {
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);

        // Start the clipboard monitor
        ClipboardMonitor.Start();

        Application.Run(new CopyHookForm());

        // Stop the clipboard monitor when the application exits
        ClipboardMonitor.Stop();
    }
}
Windows
Windows
A family of Microsoft operating systems that run across personal computers, tablets, laptops, phones, internet of things devices, self-contained mixed reality headsets, large collaboration screens, and other devices.
5,825 questions
.NET
.NET
Microsoft Technologies based on the .NET software framework.
4,103 questions
C#
C#
An object-oriented and type-safe programming language that has its roots in the C family of languages and includes support for component-oriented programming.
11,545 questions
0 comments No comments
{count} votes

1 answer

Sort by: Most helpful
  1. gekka 12,201 Reputation points MVP Volunteer Moderator
    2024-01-04T00:25:14.5333333+00:00

    Form.ActiveForm is not exist before window is created and Form.ActiveForm is not exist after all windows are closed.

    public partial class CopyHookForm : Form
    {
        ...
            
        protected override void WndProc(ref Message m)
        {
            ClipboardMonitor.WndProc(ref m);
            base.WndProc(ref m);
        }
    }
    
    public static class ClipboardMonitor
    {
        ...
    
        public static void Start(IntPtr hwnd)
        {
            clipboardViewerNext = SetClipboardViewer(hwnd);
        }
    
        public static void Stop(IntPtr hwnd)
        {
            ChangeClipboardChain(hwnd, clipboardViewerNext);
        }
    
        ...
    }
    
    class Program
    {
        [STAThread]//Need STA
        static void Main()
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
    
    
            var hookform = new CopyHookForm();
            hookform.HandleCreated += (s, e) =>
            {
                // Must do after the handle is created
                // In applications with multiple windows, ActiveForm is unstable.
                ClipboardMonitor.Start(hookform.Handle);
            };
            hookform.FormClosed += (s, e) =>
            {
                // Must do before the handle is destroy
                // Must do the same as the Hooked handle
                ClipboardMonitor.Stop(hookform.Handle);
            };
    
            Application.Run(hookform);
        }
    }
    

Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.