vbAccelerator - Contents of code file: AniCursor\frmTestAnimatedCursor.cs

using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;
using System.IO;

using Microsoft.MSDNMag.AsyncUtils;
using vbAccelerator.Components.Win32;

namespace AniCursorTester
{
   /// <summary>
   /// Summary description for Form1.
   /// </summary>
   public class frmTestAnimatedCursor : System.Windows.Forms.Form
   {
      private AniCursor aniCursor = null;
      private ThreadedAniCursor threadCursor = null;
      private System.Windows.Forms.CheckBox chkSetCursor;
      private System.Windows.Forms.CheckBox chkDrawThreaded;
      private System.Windows.Forms.Button btnBlock;
      /// <summary>
      /// Required designer variable.
      /// </summary>
      private System.ComponentModel.Container components = null;

      public frmTestAnimatedCursor()
      {
         //
         // Required for Windows Form Designer support
         //
         InitializeComponent();

         // AniCursor class:
         string file = Path.Combine(System.Environment.CurrentDirectory,
          "globe.ani");
         aniCursor = new AniCursor(file);
         this.Paint += new PaintEventHandler(frmTestAnimatedCursor_Paint);     
             

         // ThreadedAniCursor class:
         threadCursor = new ThreadedAniCursor(this);
         threadCursor.AniCursor = aniCursor;
         threadCursor.Location = new Point(32, 148);
         threadCursor.Size = new Size(32, 32);

         // events;
         this.Closing += new CancelEventHandler(frmTestAnimatedCursor_Closing);
         
      }

      /// <summary>
      /// Clean up any resources being used.
      /// </summary>
      protected override void Dispose( bool disposing )
      {
         if( disposing )
         {
            if (components != null) 
            {
               components.Dispose();
            }
         }
         base.Dispose( disposing );
      }

      #region Windows Form Designer generated code
      /// <summary>
      /// Required method for Designer support - do not modify
      /// the contents of this method with the code editor.
      /// </summary>
      private void InitializeComponent()
      {
         System.Resources.ResourceManager resources = new
          System.Resources.ResourceManager(typeof(frmTestAnimatedCursor));
         this.chkSetCursor = new System.Windows.Forms.CheckBox();
         this.chkDrawThreaded = new System.Windows.Forms.CheckBox();
         this.btnBlock = new System.Windows.Forms.Button();
         this.SuspendLayout();
         // 
         // chkSetCursor
         // 
         this.chkSetCursor.FlatStyle = System.Windows.Forms.FlatStyle.System;
         this.chkSetCursor.Location = new System.Drawing.Point(24, 12);
         this.chkSetCursor.Name = "chkSetCursor";
         this.chkSetCursor.Size = new System.Drawing.Size(208, 20);
         this.chkSetCursor.TabIndex = 0;
         this.chkSetCursor.Text = "&Set Cursor";
         this.chkSetCursor.CheckedChanged += new
          System.EventHandler(this.chkSetCursor_CheckedChanged);
         // 
         // chkDrawThreaded
         // 
         this.chkDrawThreaded.FlatStyle = System.Windows.Forms.FlatStyle.System;
         this.chkDrawThreaded.Location = new System.Drawing.Point(24, 36);
         this.chkDrawThreaded.Name = "chkDrawThreaded";
         this.chkDrawThreaded.Size = new System.Drawing.Size(208, 20);
         this.chkDrawThreaded.TabIndex = 1;
         this.chkDrawThreaded.Text = "&Draw on Background Thread";
         this.chkDrawThreaded.CheckedChanged += new
          System.EventHandler(this.chkDrawThreaded_CheckedChanged);
         // 
         // btnBlock
         // 
         this.btnBlock.FlatStyle = System.Windows.Forms.FlatStyle.System;
         this.btnBlock.Location = new System.Drawing.Point(56, 64);
         this.btnBlock.Name = "btnBlock";
         this.btnBlock.Size = new System.Drawing.Size(120, 32);
         this.btnBlock.TabIndex = 2;
         this.btnBlock.Text = "&Blocking Operation";
         this.btnBlock.Click += new System.EventHandler(this.btnBlock_Click);
         // 
         // frmTestAnimatedCursor
         // 
         this.AutoScaleBaseSize = new System.Drawing.Size(5, 14);
         this.ClientSize = new System.Drawing.Size(292, 266);
         this.Controls.AddRange(new System.Windows.Forms.Control[] {
                                                        this.btnBlock,
                                                        this.chkDrawThreaded,
                                                        this.chkSetCursor});
         this.Font = new System.Drawing.Font("Tahoma", 8.25F,
          System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point,
          ((System.Byte)(0)));
         this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));
         this.Name = "frmTestAnimatedCursor";
         this.Text = "Animated Cursor Sample";
         this.Load += new System.EventHandler(this.frmTestAnimatedCursor_Load);
         this.ResumeLayout(false);

      }
      #endregion

      /// <summary>
      /// The main entry point for the application.
      /// </summary>
      [STAThread]
      static void Main() 
      {
         Application.Run(new frmTestAnimatedCursor());
      }


      private void frmTestAnimatedCursor_Load(object sender, System.EventArgs e)
      {
         threadCursor.Handle = this.Handle;
      }
      private void frmTestAnimatedCursor_Closing(object sender, CancelEventArgs
       e)
      {
         if (!threadCursor.IsDone)
         {
            threadCursor.CancelAndWait();
         }
      }

      private void frmTestAnimatedCursor_Paint(object sender, PaintEventArgs p)
      {
         p.Graphics.FillRectangle(SystemBrushes.Control, 32, 148, 32, 32);
         aniCursor.Draw(p.Graphics, 32, 148);
      }

      private void chkSetCursor_CheckedChanged(object sender, System.EventArgs
       e)
      {
         if (chkSetCursor.Checked)
         {
            this.Cursor = aniCursor.Cursor;
         }
         else
         {
            this.Cursor = null;
         }   
      }

      private void btnBlock_Click(object sender, System.EventArgs e)
      {   
         if (!chkSetCursor.Checked)
         {
            this.Cursor = aniCursor.Cursor;
         }

         // Emulate a long blocking operation by sending 
         // the UI thread to sleep:
         System.Threading.Thread.Sleep(5000);

         if (!chkSetCursor.Checked)
         {
            this.Cursor = null;
         }
      }

      private void chkDrawThreaded_CheckedChanged(object sender,
       System.EventArgs e)
      {
         if (chkDrawThreaded.Checked)
         {
            threadCursor.Start();
         }
         else
         {
            threadCursor.Cancel();
         }
      }

   }   

   public class ThreadedAniCursor : AsyncOperation
   {
      private IntPtr handle = IntPtr.Zero;
      private AniCursor aniCursor;
      private System.Drawing.Size size = new Size(32, 32);
      private System.Drawing.Point pos = new Point(0, 0);
      private int interval = 100;

      protected override void DoWork()
      {
         if (this.handle == IntPtr.Zero)
         {
            throw new InvalidOperationException("Handle property must be
             assigned");
         }
         if (this.aniCursor == null)
         {
            throw new InvalidOperationException("AniCursor object must be
             assigned");
         }
         runCursor();
         if (CancelRequested)
         {
            AcknowledgeCancel();
         }
      }

      private void runCursor()
      {
         while (!CancelRequested)
         {
            OnCursor();
            System.Threading.Thread.Sleep(this.interval);
         }
      }

      protected virtual void OnCursor()
      {
         lock(this)
         {
            Graphics gfx = Graphics.FromHwnd(this.handle);
            aniCursor.Draw(gfx, pos.X, pos.Y, size.Width, size.Height, false);
            gfx.Dispose();
            aniCursor.Step();
         }
      }

      /// <summary>
      /// Gets/sets the interval between frames of the cursor.
      /// </summary>
      public int Interval
      {
         get
         {
            lock(this)
            {
               return this.interval;
            }
         }
         set
         {
            lock(this)
            {
               this.interval = value;
            }
         }
      }

      /// <summary>
      /// Gets/sets the size to draw the cursor.
      /// </summary>
      public System.Drawing.Size Size
      {         
         get
         {
            lock(this)
            {
               return this.size;
            }
         }
         set
         {
            lock(this)
            {
               this.size = value;
            }
         }
      }
      /// <summary>
      /// Gets/sets the location in the window to draw
      /// the cursor
      /// </summary>
      public System.Drawing.Point Location
      {
         get
         {
            lock(this)
            {
               return this.pos;
            }
         }
         set
         {
            lock(this)
            {
               this.pos = value;
            }
         }
      }

      /// <summary>
      /// Gets/sets the window handle to draw onto
      /// </summary>
      public IntPtr Handle
      {
         get
         {
            lock(this)
            {
               return this.handle;
            }
         }
         set
         {
            lock(this)
            {
               this.handle = value;
            }
         }
      }
      
      /// <summary>
      /// Assigns the animated cursor
      /// </summary>
      public vbAccelerator.Components.Win32.AniCursor AniCursor
      {
         get
         {
            lock(this)
            {
               return this.aniCursor;   
            }
         }
         set
         {
            lock(this)
            {
               this.aniCursor = value;
            }
         }
      }
      
      /// <summary>
      /// Creates a new instance of the Threaded AniCursor class
      /// </summary>
      /// <param name="isi">The object to receive notifications.
      /// Note that only the Cancelled and Failed events will
      /// be fired - this object never completes.</param>
      /// <remarks>Start the cursor running with Start and 
      /// stop it running using Cancel or CancelAndWait.
      /// CancelAndWait ensures that the class has completed
      /// before it returns</remarks>
      public ThreadedAniCursor(
         ISynchronizeInvoke isi         
         ) : base(isi)
      {         
      }
   }


}