context: //
  //This library is free software; you can redistribute it and/or
  //modify it under the terms of the GNU Lesser General Public
  //License as published by the Free Software Foundation; either
  //version 2.1 of the License, or (at your option) any later version.
  //
  //This library is distributed in the hope that it will be useful,
  //but WITHOUT ANY WARRANTY; without even the implied warranty of
  //MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  //Lesser General Public License for more details.
  //
  //You should have received a copy of the GNU Lesser General Public
  //License along with this library; if not, write to the Free Software
  //Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  //=============================================================================
  
  using System;
  using System.ComponentModel;
  using System.Drawing;
  using System.Drawing.Drawing2D;
  using System.Drawing.Text;
  using System.Windows.Forms;
  using System.Threading;
  using System.Drawing.Imaging;
  using System.IO;
  using System.Text;
  
  using System.Runtime.InteropServices;
  //using System.Diagnostics;
  
  namespace ZedGraph
  {
  	partial class ZedGraphControl
  	{
  
  	#region ContextMenu
  
  		// Revision: JCarpenter 10/06
  		/// <summary>
  		/// Public enumeration that specifies the type of 
  		/// object present at the Context Menu's mouse location
  		/// </summary>
  		public enum ContextMenuObjectState
  		{
  			/// <summary>
  			/// The object is an Inactive Curve Item at the Context Menu's mouse position
  			/// </summary>
  			InactiveSelection,
  			/// <summary>
  			/// The object is an active Curve Item at the Context Menu's mouse position
  			/// </summary>
  			ActiveSelection,
  			/// <summary>
  			/// There is no selectable object present at the Context Menu's mouse position
  			/// </summary>
  			Background
  		}
  
  		//Revision: JCarpenter 10/06
  		/// <summary>
  		/// Find the object currently under the mouse cursor, and return its state.
  		/// </summary>
  		private ContextMenuObjectState GetObjectState()
  		{
  			ContextMenuObjectState objState = ContextMenuObjectState.Background;
  
  			// Determine object state
  			Point mousePt = this.PointToClient( Control.MousePosition );
  			int iPt;
  			GraphPane pane;
  			object nearestObj;
  
  			using ( Graphics g = this.CreateGraphics() )
  			{
  				if ( this.MasterPane.FindNearestPaneObject( mousePt, g, out pane,
  						out nearestObj, out iPt ) )
  				{
  					CurveItem item = nearestObj as CurveItem;
  
  					if ( item != null && iPt >= 0 )
  					{
  						if ( item.IsSelected )
  							objState = ContextMenuObjectState.ActiveSelection;
  						else
  							objState = ContextMenuObjectState.InactiveSelection;
  					}
  				}
  			}
  
  			return objState;
  		}
  
  		/// <summary>
  		/// protected method to handle the popup context menu in the <see cref="ZedGraphControl"/>.
  		/// </summary>
  		/// <param name="sender"></param>
  		/// <param name="e"></param>
  		private void contextMenuStrip1_Opening( object sender, CancelEventArgs e )
  		{
  			// disable context menu by default
  			e.Cancel = true;
  			ContextMenuStrip menuStrip = sender as ContextMenuStrip;
  
  			//Revision: JCarpenter 10/06
  			ContextMenuObjectState objState = GetObjectState();
  
  			if ( _masterPane != null && menuStrip != null )
  			{
  				menuStrip.Items.Clear();
  
  				_isZooming = false;
  				_isPanning = false;
  				Cursor.Current = Cursors.Default;
  
  				_menuClickPt = this.PointToClient( Control.MousePosition );
  				GraphPane pane = _masterPane.FindPane( _menuClickPt );
  
  				if ( _isShowContextMenu )
  				{
  					string menuStr = string.Empty;
  
  					ToolStripMenuItem item = new ToolStripMenuItem();
  					item.Name = "copy";
  					item.Tag = "copy";
  					item.Text = ZedGraphLocale.copy;
  					item.Click += new System.EventHandler( this.MenuClick_Copy );
  					menuStrip.Items.Add( item );
  
  					item = new ToolStripMenuItem();
  					item.Name = "save_as";
  					item.Tag = "save_as";
  					item.Text = ZedGraphLocale.save_as;
  					item.Click += new System.EventHandler( this.MenuClick_SaveAs );
  					menuStrip.Items.Add( item );
  
  					item = new ToolStripMenuItem();
  					item.Name = "page_setup";
  					item.Tag = "page_setup";
  					item.Text = ZedGraphLocale.page_setup;
  					item.Click += new System.EventHandler( this.MenuClick_PageSetup );
  					menuStrip.Items.Add( item );
  
  					item = new ToolStripMenuItem();
  					item.Name = "print";
  					item.Tag = "print";
  					item.Text = ZedGraphLocale.print;
  					item.Click += new System.EventHandler( this.MenuClick_Print );
  					menuStrip.Items.Add( item );
  
  					item = new ToolStripMenuItem();
  					item.Name = "show_val";
  					item.Tag = "show_val";
  					item.Text = ZedGraphLocale.show_val;
  					item.Click += new System.EventHandler( this.MenuClick_ShowValues );
  					item.Checked = this.IsShowPointValues;
  					menuStrip.Items.Add( item );
  
  					item = new ToolStripMenuItem();
  					item.Name = "unzoom";
  					item.Tag = "unzoom";
  
  					if (pane == null || pane.ZoomStack.IsEmpty)
  					{
  					    menuStr = ZedGraphLocale.unzoom;
  					}
  					else
  					{
  						switch ( pane.ZoomStack.Top.Type )
  						{
  							case ZoomState.StateType.Zoom:
  							case ZoomState.StateType.WheelZoom:
  								menuStr = ZedGraphLocale.unzoom;
  								break;
  							case ZoomState.StateType.Pan:
  								menuStr = ZedGraphLocale.unpan;
  								break;
  							case ZoomState.StateType.Scroll:
  								menuStr = ZedGraphLocale.unscroll;
  								break;
  						}
  					}
  
  					//menuItem.Text = "Un-" + ( ( pane == null || pane.zoomStack.IsEmpty ) ?
  					//	"Zoom" : pane.zoomStack.Top.TypeString );
  					item.Text = menuStr;
  					item.Click += new EventHandler( this.MenuClick_ZoomOut );
  					if ( pane == null || pane.ZoomStack.IsEmpty )
  						item.Enabled = false;
  					menuStrip.Items.Add( item );
  
  					item = new ToolStripMenuItem();
  					item.Name = "undo_all";
  					item.Tag = "undo_all";
  					menuStr = ZedGraphLocale.undo_all;
  					item.Text = menuStr;
  					item.Click += new EventHandler( this.MenuClick_ZoomOutAll );
  					if ( pane == null || pane.ZoomStack.IsEmpty )
  						item.Enabled = false;
  					menuStrip.Items.Add( item );
  
  					item = new ToolStripMenuItem();
  					item.Name = "set_default";
  					item.Tag = "set_default";
  					menuStr = ZedGraphLocale.set_default;
  					item.Text = menuStr;
  					item.Click += new EventHandler( this.MenuClick_RestoreScale );
  					if ( pane == null )
  						item.Enabled = false;
  					menuStrip.Items.Add( item );
  
  					// if e.Cancel is set to false, the context menu does not display
  					// it is initially set to false because the context menu has no items
  					e.Cancel = false;
  
  					// Provide Callback for User to edit the context menu
  					//Revision: JCarpenter 10/06 - add ContextMenuObjectState objState
  					if ( this.ContextMenuBuilder != null )
  						this.ContextMenuBuilder( this, menuStrip, _menuClickPt, objState );
  				}
  			}
  		}
  
  		/// <summary>
  		/// Handler for the "Copy" context menu item.  Copies the current image to a bitmap on the
  		/// clipboard.
  		/// </summary>
  		/// <param name="sender"></param>
  		/// <param name="e"></param>
  		protected void MenuClick_Copy( System.Object sender, System.EventArgs e )
  		{
  			Copy( _isShowCopyMessage );
  		}
  
  		/// <summary>
  		/// Handler for the "Copy" context menu item.  Copies the current image to a bitmap on the
  		/// clipboard.
  		/// </summary>
  		/// <param name="isShowMessage">boolean value that determines whether or not a prompt will be
  		/// displayed.  true to show a message of "Image Copied to ClipBoard".</param>
  		public void Copy( bool isShowMessage )
  		{
  			if ( _masterPane != null )
  			{
  				//Clipboard.SetDataObject( _masterPane.GetImage(), true );
  
  				// Threaded copy mode to avoid crash with MTA
  				// Contributed by Dave Moor
  				Thread ct = new Thread( new ThreadStart( this.ClipboardCopyThread ) );
  				//ct.ApartmentState = ApartmentState.STA;
  				ct.SetApartmentState( ApartmentState.STA );
  				ct.Start();
  				ct.Join();
  
  				if ( isShowMessage )
  				{
  					string str = ZedGraphLocale.copied_to_clip;
  					//MessageBox.Show( "Image Copied to ClipBoard" );
  					MessageBox.Show( str );
  				}
  			}
  		}
  
  		/// <summary>
  		/// A threaded version of the copy method to avoid crash with MTA
  		/// </summary>
  		private void ClipboardCopyThread()
  		{
  			Clipboard.SetDataObject( ImageRender(), true );
  		}
  
  		// 
  		/// <summary>
  		/// Setup for creation of a new image, applying appropriate anti-alias properties and
  		/// returning the resultant image file
  		/// </summary>
  		/// <returns></returns>
  		private Image ImageRender()
  		{
  			return _masterPane.GetImage( _masterPane.IsAntiAlias );
  		}
  
  		/// <summary>
  		/// Special handler that copies the current image to an Emf file on the clipboard.
  		/// </summary>
  		/// <remarks>This version is similar to the regular <see cref="Copy" /> method, except that
  		/// it will place an Emf image (vector) on the ClipBoard instead of the regular bitmap.</remarks>
  		/// <param name="isShowMessage">boolean value that determines whether or not a prompt will be
  		/// displayed.  true to show a message of "Image Copied to ClipBoard".</param>
  		public void CopyEmf(bool isShowMessage)
  		{
  			if (_masterPane != null)
  			{
  				// Threaded copy mode to avoid crash with MTA
  				// Contributed by Dave Moor
  				Thread ct = new Thread(new ThreadStart(this.ClipboardCopyThreadEmf));
  				//ct.ApartmentState = ApartmentState.STA;
  				ct.SetApartmentState(ApartmentState.STA);
  				ct.Start();
  				ct.Join();
  
  				if (isShowMessage)
  				{
  					string str = ZedGraphLocale.copied_to_clip;
  					MessageBox.Show(str);
  				}
  			}
  		}
  
  		/// <summary>
  		/// A threaded version of the copy method to avoid crash with MTA
  		/// </summary>
  		private void ClipboardCopyThreadEmf()
  		{
  			using (Graphics g = this.CreateGraphics())
  			{
  				IntPtr hdc = g.GetHdc();
  				Metafile metaFile = new Metafile(hdc, EmfType.EmfPlusOnly);
  				g.ReleaseHdc(hdc);
  
  				using (Graphics gMeta = Graphics.FromImage(metaFile))
  				{
  					this._masterPane.Draw( gMeta );
  				}
  
  				//IntPtr hMeta = metaFile.GetHenhmetafile();
  				ClipboardMetafileHelper.PutEnhMetafileOnClipboard( this.Handle, metaFile );
  				//System.Windows.Forms.Clipboard.SetDataObject(hMeta, true);
  
  				//g.Dispose();
  			}
  		}
  
  		/// <summary>
  		/// Handler for the "Save Image As" context menu item.  Copies the current image to the selected
  		/// file.
  		/// </summary>
  		/// <param name="sender"></param>
  		/// <param name="e"></param>
  		protected void MenuClick_SaveAs( System.Object sender, System.EventArgs e )
  		{
  			SaveAs();
  		}
  
  		/// <summary>
  		/// Handler for the "Save Image As" context menu item.  Copies the current image to the selected
  		/// file in either the Emf (vector), or a variety of Bitmap formats.
  		/// </summary>
  		/// <remarks>
  		/// Note that <see cref="SaveAsBitmap" /> and <see cref="SaveAsEmf" /> methods are provided
  		/// which allow for Bitmap-only or Emf-only handling of the "Save As" context menu item.
  		/// </remarks>
  		public void SaveAs()
  		{
  			SaveAs( null );
  		}
  
  		/// <summary>
  		/// Copies the current image to the selected file in  
  		/// Emf (vector), or a variety of Bitmap formats.
  		/// </summary>
  		/// <param name="DefaultFileName">
  		/// Accepts a default file name for the file dialog (if "" or null, default is not used)
  		/// </param>
  		/// <returns>
  		/// The file name saved, or "" if cancelled.
  		/// </returns>
  		/// <remarks>
  		/// Note that <see cref="SaveAsBitmap" /> and <see cref="SaveAsEmf" /> methods are provided
  		/// which allow for Bitmap-only or Emf-only handling of the "Save As" context menu item.
  		/// </remarks>
  		public String SaveAs( String DefaultFileName )
  		{
  			if ( _masterPane != null )
  			{
  				SaveFileDialog.Filter =
  					"Emf Format (*.emf)|*.emf|" +
  					"PNG Format (*.png)|*.png|" +
  					"Gif Format (*.gif)|*.gif|" +
  					"Jpeg Format (*.jpg)|*.jpg|" +
  					"Tiff Format (*.tif)|*.tif|" +
  					"Bmp Format (*.bmp)|*.bmp";
  
  				if ( DefaultFileName != null && DefaultFileName.Length > 0 )
  				{
  					String ext = System.IO.Path.GetExtension( DefaultFileName ).ToLower();
  					switch (ext)
  					{
  						case ".emf": SaveFileDialog.FilterIndex = 1; break;
  						case ".png": SaveFileDialog.FilterIndex = 2; break;
  						case ".gif": SaveFileDialog.FilterIndex = 3; break;
  						case ".jpeg":
  						case ".jpg": SaveFileDialog.FilterIndex = 4; break;
  						case ".tiff":
  						case ".tif": SaveFileDialog.FilterIndex = 5; break;
  						case ".bmp": SaveFileDialog.FilterIndex = 6; break;
  					}
  					//If we were passed a file name, not just an extension, use it
  					if ( DefaultFileName.Length > ext.Length )
  					{
  						SaveFileDialog.FileName = DefaultFileName;
  					}
  				}
  
  				if ( SaveFileDialog.ShowDialog() == DialogResult.OK )
  				{
  
gt: 					Stream myStream = SaveFileDialog.OpenFile();