title: WM_DRAWCLIPBOARD stops firing after form is opened
body: <p>I am using <code>WndProc</code> and <code>WM_DRAWCLIPBOARD</code> to monitor the Windows clipboard and save text and images copied. It's working well except for one scenario. I am using <code>NotifyIcon</code> and have the application docked to the notification area by default (<code>ShowInTaskbar</code> = False, <code>WindowState</code> = Minimized). The copy logic works well except after I open my form. When I right click the icon for the app and click Open, <code>WM_DRAWCLIPBOARD</code> isn't called anymore when I copy a piece of text or image, although <code>WndProc</code> is called constantly.</p>
  
  <p>Does <code>NotifyIcon</code> use a different thread than the main UI, if so it could be that the <code>NotifyIcon</code> thread isn't listening to the UI thread. Note that I'm not actually <code>Form.Show()</code>ing, rather I
  m just maximizing the form and showing the taskbar icon. The opposite is done when the form is "closed". Here is my code I am using. It's just one class/form, so here is all of it.</p>
  
  <pre><code>using System;
  using System.Collections.Generic;
  using System.ComponentModel;
  using System.Data;
  using System.Drawing;
  using System.IO;
  using System.Linq;
  using System.Runtime.InteropServices;
  using System.Text;
  using System.Threading.Tasks;
  using System.Windows.Forms;
  
  namespace Copy_Storer
  {
  [DefaultEvent("ClipboardChanged")]
  public partial class frmMain : Form
  {
      IntPtr _NextClipboardViewer;
      bool _AppStarting = true;
  
      public frmMain()
      {
          InitializeComponent();
          _NextClipboardViewer = (IntPtr)SetClipboardViewer((int)this.Handle);
      }
  
      private void frmMain_Load(object sender, EventArgs e)
      {
          nfyApp.ShowBalloonTip(10000);
          cmsCSRightClick.ItemClicked += new ToolStripItemClickedEventHandler(cmsCSRightClick_ItemClicked);
          _AppStarting = false;
      }
  
      [DllImport("User32.dll")]
      public static extern int
                SetClipboardViewer(int hWndNewViewer);
  
      [DllImport("User32.dll", CharSet = CharSet.Auto)]
      public static extern bool
             ChangeClipboardChain(IntPtr hWndRemove,
                                  IntPtr hWndNewNext);
  
      [DllImport("user32.dll", CharSet = CharSet.Auto)]
      public static extern int SendMessage(IntPtr hwnd, int wMsg,
                                           IntPtr wParam,
                                           IntPtr lParam);
  
      void DisplayClipboardData()
      {
          object dataConverted = null;
          string destinationFileName = string.Empty;
          string destinationFilePath = string.Empty;
          string dataType = string.Empty;
  
          // Problem: After opening the form, the clipboard monitoring function stops working.
  
          try
          {
              IDataObject iData = new DataObject();
              iData = Clipboard.GetDataObject();
  
              if (iData.GetDataPresent(DataFormats.Text) || iData.GetDataPresent(DataFormats.UnicodeText) ||
                  iData.GetDataPresent(DataFormats.Rtf))
              {
                  // First check if the file already exists.
                  dataConverted = iData.GetData(DataFormats.Text); //http://social.msdn.microsoft.com/Forums/vstudio/en-US/9a09cb14-5eb3-4b74-9cf1-ac9e0ae641fc/convert-string-to-unicode?forum=csharpgeneral
                  destinationFileName = string.Format("{0} {1}.txt", "CopiedText", DateTime.Today.ToString("MM-dd-yy"));
                  destinationFilePath = string.Format("{0}\\{1}", Path.GetTempPath(), destinationFileName);
                  dataType = DataFormats.Text.ToString();
  
  
                  if (File.Exists(destinationFilePath))
                  {
                      // Append to the file
                      File.AppendAllText(destinationFilePath, string.Format("\r\n{0}", dataConverted));
                  }
                  else
                  {
                      // Create the file
                      File.WriteAllText(destinationFilePath, dataConverted.ToString());
                  }
              }
              else if (iData.GetDataPresent(DataFormats.Bitmap))
              {
                  // Works for most (or all?) image types.
                  dataConverted = iData.GetData(DataFormats.Bitmap);
                  destinationFileName = string.Format("{0} {1} {2}.bmp", "CopiedImage", new Random().Next(1, 10000).ToString(), DateTime.Today.ToString("MM-dd-yy"));
                  destinationFilePath = string.Format("{0}\\{1}", Path.GetTempPath(), destinationFileName);
                  dataType = DataFormats.Bitmap.ToString();
  
                  while (File.Exists(destinationFilePath))
                  {
                      // Write a new path.
                      destinationFileName = string.Format("{0} {1} {2}.bmp", "CopiedImage", new Random().Next(1, 100000).ToString(), DateTime.Today.ToString("MM-dd-yy"));
                      destinationFilePath = string.Format("{0}\\{1}", Path.GetTempPath(), destinationFileName);
                  }
  
                  Bitmap copiedImage = (Bitmap)dataConverted;
                  copiedImage.Save(destinationFilePath);
              }
  
              // Add file to grid.
              FileInfo f = new FileInfo(destinationFilePath);
              string[] newRow = new string[] {destinationFileName, destinationFilePath, dataType, f.Length.ToString()};
              dgvFilesCopied.Rows.Add(newRow);
          }
          catch (Exception e)
          {
              MessageBox.Show(e.ToString());
          }
      }
  
      protected override void Dispose(bool disposing)
      {
          ChangeClipboardChain(this.Handle, _NextClipboardViewer);
          if (disposing)
          {
              if (components != null)
              {
                  components.Dispose();
              }
          }
          base.Dispose(disposing);
      }
  
      protected override void WndProc(ref System.Windows.Forms.Message m)
      {
          // When user opens main form, WndProc is still reacting
  
          // defined in winuser.h
          const int WM_DRAWCLIPBOARD = 0x308;
          const int WM_CHANGECBCHAIN = 0x030D;
          bool randomValue = true;
  
          if (m.Msg == /*WM_SIZE*/ 0x0005) 
          {
              if (this.WindowState == FormWindowState.Minimized) randomValue = false;
          }
  
          switch (m.Msg)
          {
              case WM_DRAWCLIPBOARD:
                  if (!_AppStarting)
                  {
                      DisplayClipboardData();
                      SendMessage(_NextClipboardViewer, m.Msg, m.WParam, m.LParam);
                  }
                  break;
  
              case WM_CHANGECBCHAIN:
                  if (m.WParam == _NextClipboardViewer)
                      _NextClipboardViewer = m.LParam;
                  else
                      SendMessage(_NextClipboardViewer, m.Msg, m.WParam, m.LParam);
                  break;
  
              default:
                  base.WndProc(ref m);
                  break;
          }
      }
  
      private void cmsCSRightClick_ItemClicked(object sender, ToolStripItemClickedEventArgs e)
      {
          switch (e.ClickedItem.Text)
          {
              case "Open":
                  // We want to show the form.
                  ShowHideMainForm(true);
                  break;
          }
      }
      private void nfyApp_MouseDoubleClick(object sender, MouseEventArgs e)
      {
          // Show files saved
          ShowHideMainForm(true);
          if (dgvFilesCopied.Rows.Count &lt; 1)
          {
              lblHeader.Text = "No files have been copied recently.";
          }
      }
  
      private void frmMain_FormClosing(object sender, FormClosingEventArgs e)
      {
          // We only want to hide the form when using the X button of the form.
          ShowHideMainForm(false);
  
          e.Cancel = true;
          // The form/app can be closed when the icon is right clicked -&gt; Close.
      }
  
      private void ShowHideMainForm(bool show)
      {
          if (show)
          {
              this.ShowInTaskbar = true;
              this.WindowState = FormWindowState.Normal;
          }
          else
          {
              this.ShowInTaskbar = false;
              this.WindowState = FormWindowState.Minimized;
          }
      }
  
      private void exitToolStripMenuItem_Click(object sender, EventArgs e)
      {
          this.Close();
      }
  }
  }
  </code></pre>
  
  <p>Would appreciate another set of eyes. Thanks.</p>