Click here to Skip to main content
16,015,504 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
This was provided in Clipboarder in 8Gadgets but after I copied ~18k files it crashed even after a clean install after format of Revo Uninstaller and a machine restart, I want to hear a sound when clipboard changes or even when clipboard is set.
I'm on .NET Framework.

What I have tried:

using System.Windows.Forms;
using System.Media;
using System.Threading;
using System.Runtime.InteropServices;

namespace ClipboardMonitor
{
    public partial class Form1 : Form
    {
        private DataObject lastClipboardData;
        private System.Windows.Forms.Timer clipboardTimer;

        public Form1()
        {
            InitializeComponent();

            clipboardTimer = new System.Windows.Forms.Timer();
            clipboardTimer.Interval = 100; // Adjust interval as needed
            clipboardTimer.Tick += ClipboardTimer_Tick;
            clipboardTimer.Start();
        }

        private void ClipboardTimer_Tick(object sender, EventArgs e)   

        {
            DataObject currentClipboardData = Clipboard.GetDataObject();
            if (currentClipboardData != lastClipboardData)
            {
                lastClipboardData = currentClipboardData;
                PlaySound();
            }
        }

        private void PlaySound()
        {
            // Replace with your desired sound file
            System.Media.SoundPlayer player = new System.Media.SoundPlayer("notification.wav");
            player.Play();
        }
    }
}


The code above plays the sound repeatedly (wrongly).
Posted
Updated 14-Aug-24 4:06am

using System;
using System.Windows.Forms;
using System.Media;
using System.Threading;
using System.Runtime.InteropServices;
using System.Text;
using System.Drawing;

namespace playSoundWhenClipboardChanges
{
    public partial class FormMain : Form
    {

        public FormMain()
        {
            InitializeComponent();

            AddClipboardFormatListener(this.Handle);    // Add our window to the clipboard's format listener list.

        }








        /// <summary>
        /// Places the given window in the system-maintained clipboard format listener list.
        /// </summary>
        [DllImport("user32.dll", SetLastError = true)]
        [return: MarshalAs(UnmanagedType.Bool)]
        static extern bool AddClipboardFormatListener(IntPtr hwnd);

        /// <summary>
        /// Removes the given window from the system-maintained clipboard format listener list.
        /// </summary>
        [DllImport("user32.dll", SetLastError = true)]
        [return: MarshalAs(UnmanagedType.Bool)]
        static extern bool RemoveClipboardFormatListener(IntPtr hwnd);

        /// <summary>
        /// Sent when the contents of the clipboard have changed.
        /// </summary>
        private const int WM_CLIPBOARDUPDATE = 0x031D;









        protected override void WndProc(ref Message m)
        {
            base.WndProc(ref m);


            

            if (m.Msg == WM_CLIPBOARDUPDATE)
            {
                PlaySound();
                return;

                IDataObject iData = Clipboard.GetDataObject();      // Clipboard's data.

                /* Depending on the clipboard's current data format we can process the data differently. 
                 * Feel free to add more checks if you want to process more formats. */
                if (iData.GetDataPresent(DataFormats.Text))
                {
                    string text = (string)iData.GetData(DataFormats.Text);
                    // do something with it
                }
                else if (iData.GetDataPresent(DataFormats.Bitmap))
                {
                    Bitmap image = (Bitmap)iData.GetData(DataFormats.Bitmap);
                    // do something with it
                }
            }
        }


















        private void PlaySound()
        {
            // Replace with your desired sound file
            System.Media.SoundPlayer player = new System.Media.SoundPlayer(Properties.Resources.clipboardChangeSound);
            player.Play();
        }

        private void FormMain_FormClosing(object sender, FormClosingEventArgs e)
        {
            RemoveClipboardFormatListener(this.Handle);     // Remove our window from the clipboard's format listener list.
        }
    }
}


and when changing from window to shown only in tray:


out of tray:

private void showFormOutOfTray()
{
     RemoveClipboardFormatListener(this.Handle);     // Remove our window from the clipboard's format listener list.


    this.Show();
    this.ShowInTaskbar = true;
    this.WindowState = FormWindowState.Normal;
    this.BringToFront();
    notifyIconMain.Visible = false;

    AddClipboardFormatListener(this.Handle);    // Add our window to the clipboard's format listener list.
}


to tray:

private void hideFormToTray()
{
    RemoveClipboardFormatListener(this.Handle);     // Remove our window from the clipboard's format listener list.

    notifyIconMain.Visible = true;
    this.ShowInTaskbar = false;
    this.WindowState = FormWindowState.Minimized;

    AddClipboardFormatListener(this.Handle);    // Add our window to the clipboard's format listener list.
}
 
Share this answer
 
v5
Rather than checking the clipboard content in a loop, use one of the methods mentioned in the Microsoft documentation:

Monitoring Clipboard Contents | Using the Clipboard - Win32 apps | Microsoft Learn[^]

The simplest option would appear to be calling GetClipboardSequenceNumber[^], which will return an integer that will be incremented each time the clipboard contents change. However, the docs do say that "this is a not a notification method and should not be used in a polling loop".

To receive a notification, the recommended approach is to call AddClipboardFormatListener[^] to register your window as a "format listener", which will receive a WM_CLIPBOARDUPDATE message whenever the contents of the clipboard have changed. You will also need to call RemoveClipboardFormatListener[^] when your window closes.

The older approach of creating a "clipboard viewer" window is no longer recommended, and should only be used if you need to support systems older than Windows Vista. It's much more fiddly to set up, easy to get wrong, and liable to breaking the clipboard functionality completely, requiring a reboot.
 
Share this answer
 
Comments
John Smith 27 14-Aug-24 11:28am    
I found the answer with your guidance.
Thx.
Pete O'Hanlon 15-Aug-24 0:47am    
I like this solution. Definitely worthy of a 5.

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900