Anonymous avatar Anonymous committed 3f25e04

Comments (0)

Files changed (29)

+
+Microsoft Visual Studio Solution File, Format Version 10.00
+# Visual Studio 2008
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WinTest", "WinTest\WinTest.csproj", "{609227AC-69FB-43D6-8E44-9817D260C2D0}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WpfTest", "WpfTest\WpfTest.csproj", "{EDC6DE6A-C1EA-4192-AB34-63E6F4E6A835}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "StickyWindowLibrary", "StickyWindowLibrary\StickyWindowLibrary.csproj", "{AF76FEA7-CD9D-4093-B617-BC9C44DE99C6}"
+EndProject
+Global
+	GlobalSection(SolutionConfigurationPlatforms) = preSolution
+		Debug|Any CPU = Debug|Any CPU
+		Release|Any CPU = Release|Any CPU
+	EndGlobalSection
+	GlobalSection(ProjectConfigurationPlatforms) = postSolution
+		{609227AC-69FB-43D6-8E44-9817D260C2D0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{609227AC-69FB-43D6-8E44-9817D260C2D0}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{609227AC-69FB-43D6-8E44-9817D260C2D0}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{609227AC-69FB-43D6-8E44-9817D260C2D0}.Release|Any CPU.Build.0 = Release|Any CPU
+		{EDC6DE6A-C1EA-4192-AB34-63E6F4E6A835}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{EDC6DE6A-C1EA-4192-AB34-63E6F4E6A835}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{EDC6DE6A-C1EA-4192-AB34-63E6F4E6A835}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{EDC6DE6A-C1EA-4192-AB34-63E6F4E6A835}.Release|Any CPU.Build.0 = Release|Any CPU
+		{AF76FEA7-CD9D-4093-B617-BC9C44DE99C6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{AF76FEA7-CD9D-4093-B617-BC9C44DE99C6}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{AF76FEA7-CD9D-4093-B617-BC9C44DE99C6}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{AF76FEA7-CD9D-4093-B617-BC9C44DE99C6}.Release|Any CPU.Build.0 = Release|Any CPU
+	EndGlobalSection
+	GlobalSection(SolutionProperties) = preSolution
+		HideSolutionNode = FALSE
+	EndGlobalSection
+EndGlobal

StickyWindowLibrary/IFormAdapter.cs

+////////////////////////////////////////////////////////////////////////////////
+// StickyWindows
+// 
+// Copyright (c) 2009 Riccardo Pietrucci
+//
+// This software is provided 'as-is', without any express or implied warranty.
+// In no event will the author be held liable for any damages arising from 
+// the use of this software.
+// Permission to use, copy, modify, distribute and sell this software for any 
+// purpose is hereby granted without fee, provided that the above copyright 
+// notice appear in all copies and that both that copyright notice and this 
+// permission notice appear in supporting documentation.
+//
+//////////////////////////////////////////////////////////////////////////////////
+
+
+using System;
+using System.Collections.Generic;
+using System.Drawing;
+using System.Text;
+
+namespace StickyWindowLibrary
+{
+    public interface IFormAdapter
+    {
+        IntPtr Handle { get; }
+        Rectangle Bounds { get; set; }
+        Size MaximumSize { get; set; }
+        Size MinimumSize { get; set; }
+        bool Capture { get; set; }
+        void Activate();
+        Point PointToScreen(Point point);
+    }
+}

StickyWindowLibrary/Properties/AssemblyInfo.cs

+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following 
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("StickyWindow")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("Reply")]
+[assembly: AssemblyProduct("StickyWindow")]
+[assembly: AssemblyCopyright("Copyright © Reply 2009")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible 
+// to COM components.  If you need to access a type in this assembly from 
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("d24729f9-6580-47a7-bf7b-13aed0ebe2bb")]
+
+// Version information for an assembly consists of the following four values:
+//
+//      Major Version
+//      Minor Version 
+//      Build Number
+//      Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers 
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]

StickyWindowLibrary/StickyWindow.cs

+////////////////////////////////////////////////////////////////////////////////
+// StickyWindows
+// 
+// Copyright (c) 2004 Corneliu I. Tusnea
+//
+// This software is provided 'as-is', without any express or implied warranty.
+// In no event will the author be held liable for any damages arising from 
+// the use of this software.
+// Permission to use, copy, modify, distribute and sell this software for any 
+// purpose is hereby granted without fee, provided that the above copyright 
+// notice appear in all copies and that both that copyright notice and this 
+// permission notice appear in supporting documentation.
+//
+// Notice: Check CodeProject for details about using this class
+//
+//////////////////////////////////////////////////////////////////////////////////
+
+using System;
+using System.Windows.Forms;
+using StickyWindowLibrary;
+
+#region Blue.Win32Imports
+
+namespace Blue.Private.Win32Imports
+{
+	using System.Runtime.InteropServices;
+
+	/// <summary>
+	/// Win32 is just a placeholder for some Win32 imported definitions
+	/// </summary>
+	public class Win32
+	{
+		[DllImport("user32.dll", CharSet=CharSet.Ansi, CallingConvention=CallingConvention.Cdecl)]
+		public static extern short GetAsyncKeyState(int vKey);
+		[DllImport("user32.dll", CharSet=CharSet.Ansi, CallingConvention=CallingConvention.Cdecl)]
+		public static extern IntPtr GetDesktopWindow();
+
+		/// <summary>
+		/// VK is just a placeholder for VK (VirtualKey) general definitions
+		/// </summary>
+		public class VK
+		{
+			public const int VK_SHIFT          = 0x10;
+			public const int VK_CONTROL        = 0x11;
+			public const int VK_MENU           = 0x12;
+			public const int VK_ESCAPE         = 0x1B;
+
+			public static bool IsKeyPressed ( int KeyCode )
+			{
+				return (GetAsyncKeyState(KeyCode) & 0x0800)==0;
+			}
+		}
+
+		/// <summary>
+		/// WM is just a placeholder class for WM (WindowMessage) definitions
+		/// </summary>
+		public class WM
+		{
+			public const int WM_MOUSEMOVE                    = 0x0200;
+			public const int WM_NCMOUSEMOVE                  = 0x00A0;
+			public const int WM_NCLBUTTONDOWN                = 0x00A1;
+			public const int WM_NCLBUTTONUP                  = 0x00A2;
+			public const int WM_NCLBUTTONDBLCLK              = 0x00A3;
+			public const int WM_LBUTTONDOWN                  = 0x0201;
+			public const int WM_LBUTTONUP                    = 0x0202;
+			public const int WM_KEYDOWN                      = 0x0100;
+		}
+
+		/// <summary>
+		/// HT is just a placeholder for HT (HitTest) definitions
+		/// </summary>
+		public class HT
+		{
+			public const int HTERROR             = (-2);
+			public const int HTTRANSPARENT       = (-1);
+			public const int HTNOWHERE           = 0;
+			public const int HTCLIENT            = 1;
+			public const int HTCAPTION           = 2;
+			public const int HTSYSMENU           = 3;
+			public const int HTGROWBOX           = 4;
+			public const int HTSIZE              = HTGROWBOX;
+			public const int HTMENU              = 5;
+			public const int HTHSCROLL           = 6;
+			public const int HTVSCROLL           = 7;
+			public const int HTMINBUTTON         = 8;
+			public const int HTMAXBUTTON         = 9;
+			public const int HTLEFT              = 10;
+			public const int HTRIGHT             = 11;
+			public const int HTTOP               = 12;
+			public const int HTTOPLEFT           = 13;
+			public const int HTTOPRIGHT          = 14;
+			public const int HTBOTTOM            = 15;
+			public const int HTBOTTOMLEFT        = 16;
+			public const int HTBOTTOMRIGHT       = 17;
+			public const int HTBORDER            = 18;
+			public const int HTREDUCE            = HTMINBUTTON;
+			public const int HTZOOM              = HTMAXBUTTON;
+			public const int HTSIZEFIRST         = HTLEFT;
+			public const int HTSIZELAST          = HTBOTTOMRIGHT;
+
+			public const int HTOBJECT            = 19;
+			public const int HTCLOSE             = 20;
+			public const int HTHELP              = 21;
+		}
+
+		public class Bit
+		{
+			public static int HiWord ( int iValue )
+			{
+				return ( (iValue >> 16 ) & 0xFFFF );
+			}
+			public static int LoWord( int iValue )
+			{
+				return ( iValue & 0xFFFF );
+			}
+		}
+	}
+}
+#endregion
+
+
+namespace Blue.Windows
+{
+	using System.Drawing;
+	using System.Collections;
+
+	using Blue.Private.Win32Imports;
+
+	/// <summary>
+	/// A windows that Sticks to other windows of the same type when moved or resized.
+	/// You get a nice way of organizing multiple top-level windows.
+	/// Quite similar with WinAmp 2.x style of sticking the windows
+	/// </summary>
+	public class StickyWindow : System.Windows.Forms.NativeWindow
+	{
+		/// <summary>
+		/// Global List of registered StickyWindows
+		/// </summary>
+		private static ArrayList	GlobalStickyWindows = new ArrayList();
+
+		#region ResizeDir
+		private enum ResizeDir
+		{
+			Top		= 2,
+			Bottom	= 4,
+			Left	= 8,
+			Right	= 16
+		};
+		#endregion
+
+		#region Message Processor
+		// Internal Message Processor
+		private delegate bool ProcessMessage( ref Message m );
+		private ProcessMessage	MessageProcessor;
+
+		// Messages processors based on type
+		private ProcessMessage	DefaultMessageProcessor;
+		private ProcessMessage	MoveMessageProcessor;
+		private ProcessMessage	ResizeMessageProcessor;
+		#endregion
+
+		#region Internal properties
+		// Move stuff
+		private bool		movingForm;
+		private Point		formOffsetPoint;	// calculated offset rect to be added !! (min distances in all directions!!)
+		private Point		offsetPoint;		// primary offset
+
+		// Resize stuff
+		private bool		resizingForm;
+		private ResizeDir	resizeDirection;
+		private Rectangle	formOffsetRect;		// calculated rect to fix the size
+		private Point		mousePoint;			// mouse position
+
+		// General Stuff
+        private IFormAdapter originalForm;		// the form
+		private Rectangle	formRect;			// form bounds
+		private Rectangle	formOriginalRect;	// bounds before last operation started
+		#endregion
+
+		// public properties
+		private static int	stickGap = 20;		// distance to stick
+		private bool		stickOnResize;
+		private bool		stickOnMove;
+		private bool		stickToScreen;
+		private bool		stickToOther;
+
+		#region Public operations and properties
+
+		/// <summary>
+		/// Distance in pixels betwen two forms or a form and the screen where the sticking should start
+		/// Default value = 20
+		/// </summary>
+		public int	StickGap
+		{
+			get { return stickGap; }
+			set { stickGap = value; }
+		}
+		/// <summary>
+		/// Allow the form to stick while resizing
+		/// Default value = true
+		/// </summary>
+		public bool StickOnResize
+		{
+			get { return stickOnResize; }
+			set { stickOnResize = value; }
+		}
+		/// <summary>
+		/// Allow the form to stick while moving
+		/// Default value = true
+		/// </summary>
+		public bool StickOnMove
+		{
+			get { return stickOnMove; }
+			set { stickOnMove = value; }
+		}
+		/// <summary>
+		/// Allow sticking to Screen Margins
+		/// Default value = true
+		/// </summary>
+		public bool StickToScreen
+		{
+			get { return stickToScreen; }
+			set { stickToScreen = value; }
+		}
+		/// <summary>
+		/// Allow sticking to other StickWindows
+		/// Default value = true
+		/// </summary>
+		public bool StickToOther
+		{
+			get { return stickToOther; }
+			set { stickToOther = value; }
+		}
+
+		/// <summary>
+		/// Register a new form as an external reference form.
+		/// All Sticky windows will try to stick to the external references
+		/// Use this to register your MainFrame so the child windows try to stick to it, when your MainFrame is NOT a sticky window
+		/// </summary>
+		/// <param name="frmExternal">External window that will be used as reference</param>
+		public static void RegisterExternalReferenceForm ( IFormAdapter frmExternal )
+		{
+			GlobalStickyWindows.Add ( frmExternal );
+		}
+
+        /// <summary>
+        /// Register a new form as an external reference form.
+        /// All Sticky windows will try to stick to the external references
+        /// Use this to register your MainFrame so the child windows try to stick to it, when your MainFrame is NOT a sticky window
+        /// </summary>
+        /// <param name="frmExternal">External window that will be used as reference</param>
+        public static void RegisterExternalReferenceForm ( Form frmExternal )
+        {
+            RegisterExternalReferenceForm(new WinFormAdapter(frmExternal));
+        }
+
+        /// <summary>
+        /// Register a new window as an external reference form.
+        /// All Sticky windows will try to stick to the external references
+        /// Use this to register your MainFrame so the child windows try to stick to it, when your MainFrame is NOT a sticky window
+        /// </summary>
+        /// <param name="frmExternal">External window that will be used as reference</param>
+        public static void RegisterExternalReferenceForm(System.Windows.Window winExternal)
+        {
+            RegisterExternalReferenceForm(new WpfFormAdapter(winExternal));
+        }
+
+		/// <summary>
+		/// Unregister a form from the external references.
+		/// <see cref="RegisterExternalReferenceForm"/>
+		/// </summary>
+		/// <param name="frmExternal">External window that will was used as reference</param>
+        public static void UnregisterExternalReferenceForm(IFormAdapter frmExternal)
+		{
+			GlobalStickyWindows.Remove ( frmExternal );
+		}
+
+		#endregion
+
+
+
+		#region StickyWindow Constructor
+
+        // <summary>
+        /// Make the form Sticky
+        /// </summary>
+        /// <param name="form">Form to be made sticky</param>
+        public StickyWindow(Form form)
+            : this(new WinFormAdapter(form))
+        {   
+        }
+
+        // <summary>
+        /// Make the window Sticky
+        /// </summary>
+        /// <param name="form">Window to be made sticky</param>
+        public StickyWindow(System.Windows.Window window)
+            : this(new WpfFormAdapter(window))
+        {
+        }
+
+		/// <summary>
+		/// Make the form Sticky
+		/// </summary>
+		/// <param name="form">Form to be made sticky</param>
+        public StickyWindow(IFormAdapter form)
+		{
+			resizingForm	= false;
+			movingForm		= false;
+
+			originalForm	= form;
+
+			formRect		= Rectangle.Empty;
+			formOffsetRect	= Rectangle.Empty;
+
+			formOffsetPoint	= Point.Empty;
+			offsetPoint		= Point.Empty;
+			mousePoint		= Point.Empty;
+
+			stickOnMove		= true;
+			stickOnResize	= true;
+			stickToScreen	= true;
+			stickToOther	= true;
+
+			DefaultMessageProcessor	= new ProcessMessage ( DefaultMsgProcessor );
+			MoveMessageProcessor	= new ProcessMessage ( MoveMsgProcessor );
+			ResizeMessageProcessor	= new ProcessMessage ( ResizeMsgProcessor );
+			MessageProcessor		= DefaultMessageProcessor;
+
+			AssignHandle ( originalForm.Handle );
+		}
+		#endregion
+
+		#region OnHandleChange
+		[System.Security.Permissions.PermissionSet(System.Security.Permissions.SecurityAction.Demand, Name="FullTrust")]
+		protected override void OnHandleChange()
+		{
+			if ( (int)this.Handle != 0 )
+			{
+				GlobalStickyWindows.Add ( this.originalForm );
+			} 
+			else
+			{
+				GlobalStickyWindows.Remove ( this.originalForm );
+			}
+		}
+		#endregion
+
+		#region WndProc
+		[System.Security.Permissions.PermissionSet(System.Security.Permissions.SecurityAction.Demand, Name="FullTrust")]
+		protected override void WndProc(ref Message m)
+		{
+			if ( !MessageProcessor ( ref m ) )
+				base.WndProc (ref m);
+		}
+		#endregion
+
+		#region DefaultMsgProcessor
+		/// <summary>
+		/// Processes messages during normal operations (while the form is not resized or moved)
+		/// </summary>
+		/// <param name="m"></param>
+		/// <returns></returns>
+		private bool DefaultMsgProcessor ( ref Message m )
+		{
+			switch ( m.Msg )
+			{
+				case Win32.WM.WM_NCLBUTTONDOWN:
+				{
+					originalForm.Activate();
+					mousePoint.X = (short)Win32.Bit.LoWord ( (int)m.LParam );
+					mousePoint.Y = (short)Win32.Bit.HiWord ( (int)m.LParam );
+					if ( OnNCLButtonDown( (int)m.WParam, mousePoint ) )
+					{
+						//m.Result = new IntPtr ( (resizingForm || movingForm) ? 1 : 0 );
+						m.Result = (IntPtr)( (resizingForm || movingForm) ? 1 : 0 );
+						return true;
+					}
+					break;
+				}
+			}
+
+			return false;
+		}
+		#endregion
+
+		#region OnNCLButtonDown
+		/// <summary>
+		/// Checks where the click was in the NC area and starts move or resize operation
+		/// </summary>
+		/// <param name="iHitTest"></param>
+		/// <param name="point"></param>
+		/// <returns></returns>
+		private bool OnNCLButtonDown ( int iHitTest, Point point )
+		{
+			Rectangle rParent	= originalForm.Bounds;
+			offsetPoint			= point;
+
+			switch ( iHitTest )
+			{
+				case Win32.HT.HTCAPTION:
+				{	// request for move
+					if ( stickOnMove )
+					{
+						offsetPoint.Offset ( -rParent.Left, -rParent.Top );
+						StartMove();
+						return true;
+					}
+					else
+						return false;	// leave default processing
+					
+				}
+
+				// requests for resize
+				case Win32.HT.HTTOPLEFT:
+					return StartResize ( ResizeDir.Top | ResizeDir.Left );
+				case Win32.HT.HTTOP:
+					return StartResize ( ResizeDir.Top );
+				case Win32.HT.HTTOPRIGHT:
+					return StartResize ( ResizeDir.Top | ResizeDir.Right );
+				case Win32.HT.HTRIGHT:
+					return StartResize ( ResizeDir.Right );
+				case Win32.HT.HTBOTTOMRIGHT:
+					return StartResize ( ResizeDir.Bottom | ResizeDir.Right );
+				case Win32.HT.HTBOTTOM:
+					return StartResize ( ResizeDir.Bottom );
+				case Win32.HT.HTBOTTOMLEFT:
+					return StartResize ( ResizeDir.Bottom | ResizeDir.Left );
+				case Win32.HT.HTLEFT:
+					return StartResize ( ResizeDir.Left );
+			}
+
+			return false;
+		}
+		#endregion
+
+		#region ResizeOperations
+		private bool StartResize(ResizeDir resDir)
+		{
+			if ( stickOnResize )
+			{
+				resizeDirection = resDir;
+				formRect = originalForm.Bounds;
+				formOriginalRect = originalForm.Bounds;	// save the old bounds
+
+				if ( !originalForm.Capture )	// start capturing messages
+					originalForm.Capture = true;
+
+				MessageProcessor = ResizeMessageProcessor;
+
+				return true;	// catch the message
+			} else
+				return false;	// leave default processing !
+		}
+		private bool ResizeMsgProcessor(ref Message m)
+		{
+			if ( !originalForm.Capture )
+			{
+				Cancel();
+				return false;
+			}
+
+			switch ( m.Msg )
+			{
+				case Win32.WM.WM_LBUTTONUP:
+				{	// ok, resize finished !!!
+					EndResize();
+					break;
+				}
+				case Win32.WM.WM_MOUSEMOVE:
+				{
+					mousePoint.X = (short)Win32.Bit.LoWord ( (int)m.LParam );
+					mousePoint.Y = (short)Win32.Bit.HiWord ( (int)m.LParam );
+					Resize( mousePoint );
+					break;
+				}
+				case Win32.WM.WM_KEYDOWN:
+				{
+					if ( (int)m.WParam == Win32.VK.VK_ESCAPE )
+					{
+						originalForm.Bounds = formOriginalRect;	// set back old size
+						Cancel();
+					}
+					break;
+				}
+			}
+
+			return false;
+		}
+		private void EndResize()
+		{
+			Cancel();
+		}
+		#endregion
+
+		#region Resize Computing
+		private void Resize( Point p )
+		{
+			p = originalForm.PointToScreen ( p );
+			Screen activeScr = Screen.FromPoint( p );
+			formRect = originalForm.Bounds;
+
+			int iRight			= formRect.Right;
+			int iBottom			= formRect.Bottom;
+
+			// no normalize required
+			// first strech the window to the new position
+			if ( (resizeDirection & ResizeDir.Left) == ResizeDir.Left )
+			{
+				formRect.Width	= formRect.X - p.X + formRect.Width;
+				formRect.X		= iRight - formRect.Width;
+			}
+			if ( (resizeDirection & ResizeDir.Right) == ResizeDir.Right )
+				formRect.Width	= p.X - formRect.Left;
+
+			if ( (resizeDirection & ResizeDir.Top) == ResizeDir.Top )
+			{
+				formRect.Height		= formRect.Height - p.Y + formRect.Top;
+				formRect.Y			= iBottom - formRect.Height;
+			}
+			if ( (resizeDirection & ResizeDir.Bottom) == ResizeDir.Bottom )
+				formRect.Height	= p.Y - formRect.Top;
+
+			// this is the real new position
+			// now, try to snap it to different objects (first to screen)
+
+			// CARE !!! We use "Width" and "Height" as Bottom & Right!! (C++ style)
+			//formOffsetRect = new Rectangle ( stickGap + 1, stickGap + 1, 0, 0 );
+			formOffsetRect.X	= stickGap + 1;
+			formOffsetRect.Y	= stickGap + 1;
+			formOffsetRect.Height = 0;
+			formOffsetRect.Width  = 0;
+
+			if ( stickToScreen )
+				Resize_Stick ( activeScr.WorkingArea, false );
+
+			if ( stickToOther )
+			{
+				// now try to stick to other forms
+                foreach (IFormAdapter sw in GlobalStickyWindows)
+				{
+					if ( sw != this.originalForm )
+						Resize_Stick( sw.Bounds, true );
+				}
+			}
+
+			// Fix (clear) the values that were not updated to stick
+			if ( formOffsetRect.X		== stickGap+1 )
+				formOffsetRect.X		= 0;
+			if ( formOffsetRect.Width	== stickGap+1 )
+				formOffsetRect.Width	= 0;
+			if ( formOffsetRect.Y		== stickGap+1 )
+				formOffsetRect.Y		= 0;
+			if ( formOffsetRect.Height	== stickGap+1 )
+				formOffsetRect.Height	= 0;
+
+			// compute the new form size
+			if ( (resizeDirection & ResizeDir.Left) == ResizeDir.Left )
+			{	// left resize requires special handling of X & Width acording to MinSize and MinWindowTrackSize
+				int iNewWidth = formRect.Width + formOffsetRect.Width + formOffsetRect.X;
+
+				if ( originalForm.MaximumSize.Width != 0 )
+					iNewWidth		= Math.Min ( iNewWidth, originalForm.MaximumSize.Width );
+
+				iNewWidth		= Math.Min ( iNewWidth, SystemInformation.MaxWindowTrackSize.Width );
+				iNewWidth		= Math.Max ( iNewWidth, originalForm.MinimumSize.Width );
+				iNewWidth		= Math.Max ( iNewWidth, SystemInformation.MinWindowTrackSize.Width );
+
+				formRect.X		= iRight - iNewWidth;
+				formRect.Width	= iNewWidth;
+			} 
+			else
+			{	// other resizes
+				formRect.Width	+= formOffsetRect.Width  + formOffsetRect.X;
+			}
+
+			if ( (resizeDirection & ResizeDir.Top) == ResizeDir.Top )
+			{
+				int iNewHeight	= formRect.Height + formOffsetRect.Height + formOffsetRect.Y;
+
+				if ( originalForm.MaximumSize.Height != 0 )
+					iNewHeight		= Math.Min ( iNewHeight, originalForm.MaximumSize.Height );
+
+				iNewHeight		= Math.Min ( iNewHeight, SystemInformation.MaxWindowTrackSize.Height );
+				iNewHeight		= Math.Max ( iNewHeight, originalForm.MinimumSize.Height );
+				iNewHeight		= Math.Max ( iNewHeight, SystemInformation.MinWindowTrackSize.Height );
+				
+				formRect.Y		= iBottom - iNewHeight;
+				formRect.Height	= iNewHeight;
+			} 
+			else
+			{	// all other resizing are fine 
+				formRect.Height	+= formOffsetRect.Height + formOffsetRect.Y;
+			}
+
+			// Done !!
+			originalForm.Bounds = formRect;
+		}
+
+		private void Resize_Stick ( Rectangle toRect, bool bInsideStick )
+		{
+			if ( formRect.Right >= (toRect.Left - stickGap) && formRect.Left <= (toRect.Right + stickGap) )
+			{
+				if ( (resizeDirection & ResizeDir.Top) == ResizeDir.Top )
+				{
+					if ( Math.Abs(formRect.Top - toRect.Bottom) <= Math.Abs(formOffsetRect.Top) && bInsideStick )
+						formOffsetRect.Y = formRect.Top - toRect.Bottom;	// snap top to bottom
+					else if (Math.Abs(formRect.Top - toRect.Top) <= Math.Abs(formOffsetRect.Top) )
+						formOffsetRect.Y = formRect.Top - toRect.Top;		// snap top to top
+				}
+
+				if ( (resizeDirection & ResizeDir.Bottom) == ResizeDir.Bottom )
+				{
+					if (Math.Abs(formRect.Bottom - toRect.Top) <= Math.Abs(formOffsetRect.Bottom) && bInsideStick)
+						formOffsetRect.Height = toRect.Top - formRect.Bottom;	// snap Bottom to top
+					else if (Math.Abs(formRect.Bottom - toRect.Bottom) <= Math.Abs(formOffsetRect.Bottom) )
+						formOffsetRect.Height = toRect.Bottom - formRect.Bottom;	// snap bottom to bottom
+				}
+			}
+
+			if ( formRect.Bottom >= (toRect.Top - stickGap) && formRect.Top <= (toRect.Bottom + stickGap) )
+			{
+				if ( (resizeDirection & ResizeDir.Right) == ResizeDir.Right )
+				{
+					if ( Math.Abs(formRect.Right - toRect.Left) <= Math.Abs(formOffsetRect.Right) && bInsideStick )
+						formOffsetRect.Width = toRect.Left - formRect.Right;		// Stick right to left
+					else if ( Math.Abs(formRect.Right - toRect.Right) <= Math.Abs(formOffsetRect.Right))
+						formOffsetRect.Width = toRect.Right - formRect.Right;	// Stick right to right
+				}
+
+				if ( (resizeDirection & ResizeDir.Left) == ResizeDir.Left )
+				{
+					if ( Math.Abs(formRect.Left - toRect.Right) <= Math.Abs(formOffsetRect.Left) && bInsideStick )
+						formOffsetRect.X = formRect.Left - toRect.Right;		// Stick left to right
+					else if ( Math.Abs(formRect.Left - toRect.Left) <= Math.Abs(formOffsetRect.Left))
+						formOffsetRect.X = formRect.Left - toRect.Left;		// Stick left to left
+				}
+			}
+		}
+		#endregion
+
+		#region Move Operations
+		private void StartMove()
+		{
+			formRect			= originalForm.Bounds;
+			formOriginalRect	= originalForm.Bounds;	// save original position
+
+			if ( !originalForm.Capture )	// start capturing messages
+				originalForm.Capture = true;
+
+			MessageProcessor = MoveMessageProcessor;
+		}
+
+		private bool MoveMsgProcessor(ref Message m)
+		{	// internal message loop
+			if ( !originalForm.Capture )
+			{
+				Cancel();
+				return false;
+			}
+
+			switch ( m.Msg )
+			{
+				case Win32.WM.WM_LBUTTONUP:
+				{	// ok, move finished !!!
+					EndMove();
+					break;
+				}
+				case Win32.WM.WM_MOUSEMOVE:
+				{
+					mousePoint.X = (short)Win32.Bit.LoWord ( (int)m.LParam );
+					mousePoint.Y = (short)Win32.Bit.HiWord ( (int)m.LParam );
+					Move( mousePoint );
+					break;
+				}
+				case Win32.WM.WM_KEYDOWN:
+				{
+					if ( (int)m.WParam == Win32.VK.VK_ESCAPE )
+					{
+						originalForm.Bounds = formOriginalRect;	// set back old size
+						Cancel();
+					}
+					break;
+				}
+			}
+
+			return false;
+		}
+		private void EndMove()
+		{
+			Cancel();
+		}
+		#endregion
+
+		#region Move Computing
+		private void Move( Point p )
+		{
+			p = originalForm.PointToScreen ( p );
+			Screen activeScr = Screen.FromPoint ( p );	// get the screen from the point !!
+
+			if ( !activeScr.WorkingArea.Contains ( p ) )
+			{
+				p.X = NormalizeInside ( p.X, activeScr.WorkingArea.Left, activeScr.WorkingArea.Right );
+				p.Y = NormalizeInside ( p.Y, activeScr.WorkingArea.Top, activeScr.WorkingArea.Bottom );
+			}
+
+			p.Offset ( -offsetPoint.X, -offsetPoint.Y );
+
+			// p is the exact location of the frame - so we can play with it
+			// to detect the new position acording to different bounds
+			formRect.Location = p;	// this is the new positon of the form
+
+			formOffsetPoint.X	= stickGap + 1;	// (more than) maximum gaps
+			formOffsetPoint.Y	= stickGap + 1;
+
+			if ( stickToScreen )
+				Move_Stick ( activeScr.WorkingArea, false );
+
+			// Now try to snap to other windows
+			if ( stickToOther )
+			{
+				foreach ( IFormAdapter sw in GlobalStickyWindows )
+				{
+					if ( sw != this.originalForm )
+						Move_Stick( sw.Bounds, true );
+				}
+			}
+
+			if ( formOffsetPoint.X == stickGap+1 )
+				formOffsetPoint.X = 0;
+			if ( formOffsetPoint.Y == stickGap+1 )
+				formOffsetPoint.Y = 0;
+
+			formRect.Offset ( formOffsetPoint );
+
+			originalForm.Bounds = formRect;
+		}
+
+		/// <summary>
+		/// 
+		/// </summary>
+		/// <param name="calculatedOffset">Calculate positon of the offset (snap distance)</param>
+		/// <param name="toRect">Rect to try to snap to</param>
+		/// <param name="bInsideStick">Allow snapping on the inside (eg: window to screen)</param>
+		private void Move_Stick ( Rectangle toRect, bool bInsideStick )
+		{
+			// compare distance from toRect to formRect
+			// and then with the found distances, compare the most closed position
+			if ( formRect.Bottom >= (toRect.Top - stickGap) && formRect.Top <= (toRect.Bottom + stickGap) )
+			{
+				if ( bInsideStick )
+				{
+					if ( (Math.Abs(formRect.Left - toRect.Right) <= Math.Abs(formOffsetPoint.X) ) )
+					{	// left 2 right
+						formOffsetPoint.X = toRect.Right - formRect.Left;
+					}
+					if ( (Math.Abs(formRect.Left + formRect.Width - toRect.Left) <= Math.Abs(formOffsetPoint.X) ) )
+					{	// right 2 left
+						formOffsetPoint.X = toRect.Left - formRect.Width - formRect.Left;
+					}
+				}
+
+				if ( Math.Abs(formRect.Left - toRect.Left) <= Math.Abs(formOffsetPoint.X) )
+				{	// snap left 2 left
+					formOffsetPoint.X = toRect.Left - formRect.Left;
+				}
+				if ( Math.Abs(formRect.Left + formRect.Width - toRect.Left - toRect.Width ) <= Math.Abs(formOffsetPoint.X))
+				{	// snap right 2 right
+					formOffsetPoint.X = toRect.Left + toRect.Width - formRect.Width - formRect.Left;
+				}
+			}
+			if ( formRect.Right >= (toRect.Left - stickGap) && formRect.Left <= (toRect.Right + stickGap) )
+			{
+				if ( bInsideStick )
+				{
+					if (Math.Abs(formRect.Top - toRect.Bottom) <= Math.Abs(formOffsetPoint.Y) && bInsideStick )
+					{	// Stick Top to Bottom
+						formOffsetPoint.Y = toRect.Bottom - formRect.Top;
+					}
+					if (Math.Abs(formRect.Top + formRect.Height - toRect.Top) <= Math.Abs(formOffsetPoint.Y) && bInsideStick )
+					{	// snap Bottom to Top
+						formOffsetPoint.Y =  toRect.Top - formRect.Height - formRect.Top;
+					}
+				}
+
+				// try to snap top 2 top also
+				if (Math.Abs(formRect.Top - toRect.Top) <= Math.Abs(formOffsetPoint.Y))
+				{	// top 2 top
+					formOffsetPoint.Y =  toRect.Top - formRect.Top;
+				}
+				if ( Math.Abs(formRect.Top + formRect.Height - toRect.Top - toRect.Height ) <= Math.Abs(formOffsetPoint.Y))
+				{	// bottom 2 bottom
+					formOffsetPoint.Y =  toRect.Top + toRect.Height - formRect.Height - formRect.Top;
+				}
+			}
+		}
+#endregion
+
+		#region Utilities
+		private int NormalizeInside ( int iP1, int iM1, int iM2 )
+		{
+			if ( iP1 <= iM1 )
+				return iM1;
+			else
+				if ( iP1 >= iM2 )
+					return iM2;
+			return iP1;
+		}
+		#endregion
+
+		#region Cancel
+		private void Cancel()
+		{
+			originalForm.Capture	= false;
+			movingForm				= false;
+			resizingForm			= false;
+			MessageProcessor		= DefaultMessageProcessor;
+		}
+		#endregion
+	}
+}

StickyWindowLibrary/StickyWindowLibrary.csproj

+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="3.5" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <PropertyGroup>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+    <ProductVersion>9.0.30729</ProductVersion>
+    <SchemaVersion>2.0</SchemaVersion>
+    <ProjectGuid>{AF76FEA7-CD9D-4093-B617-BC9C44DE99C6}</ProjectGuid>
+    <OutputType>Library</OutputType>
+    <AppDesignerFolder>Properties</AppDesignerFolder>
+    <RootNamespace>StickyWindowLibrary</RootNamespace>
+    <AssemblyName>StickyWindow</AssemblyName>
+    <TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
+    <FileAlignment>512</FileAlignment>
+    <StartupObject>
+    </StartupObject>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+    <DebugSymbols>true</DebugSymbols>
+    <DebugType>full</DebugType>
+    <Optimize>false</Optimize>
+    <OutputPath>bin\Debug\</OutputPath>
+    <DefineConstants>DEBUG;TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+    <DebugType>pdbonly</DebugType>
+    <Optimize>true</Optimize>
+    <OutputPath>bin\Release\</OutputPath>
+    <DefineConstants>TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+  </PropertyGroup>
+  <ItemGroup>
+    <Reference Include="PresentationCore">
+      <RequiredTargetFramework>3.0</RequiredTargetFramework>
+    </Reference>
+    <Reference Include="PresentationFramework">
+      <RequiredTargetFramework>3.0</RequiredTargetFramework>
+    </Reference>
+    <Reference Include="System" />
+    <Reference Include="System.Core">
+      <RequiredTargetFramework>3.5</RequiredTargetFramework>
+    </Reference>
+    <Reference Include="System.Drawing" />
+    <Reference Include="System.Windows.Forms" />
+    <Reference Include="System.Xml.Linq">
+      <RequiredTargetFramework>3.5</RequiredTargetFramework>
+    </Reference>
+    <Reference Include="System.Data.DataSetExtensions">
+      <RequiredTargetFramework>3.5</RequiredTargetFramework>
+    </Reference>
+    <Reference Include="System.Data" />
+    <Reference Include="System.Xml" />
+    <Reference Include="WindowsBase">
+      <RequiredTargetFramework>3.0</RequiredTargetFramework>
+    </Reference>
+    <Reference Include="WindowsFormsIntegration">
+      <RequiredTargetFramework>3.0</RequiredTargetFramework>
+    </Reference>
+  </ItemGroup>
+  <ItemGroup>
+    <Compile Include="IFormAdapter.cs" />
+    <Compile Include="Properties\AssemblyInfo.cs" />
+    <Compile Include="StickyWindow.cs" />
+    <Compile Include="WinFormAdapter.cs" />
+    <Compile Include="WpfFormAdapter.cs" />
+  </ItemGroup>
+  <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+  <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
+       Other similar extension points exist, see Microsoft.Common.targets.
+  <Target Name="BeforeBuild">
+  </Target>
+  <Target Name="AfterBuild">
+  </Target>
+  -->
+</Project>

StickyWindowLibrary/WinFormAdapter.cs

+////////////////////////////////////////////////////////////////////////////////
+// StickyWindows
+// 
+// Copyright (c) 2009 Riccardo Pietrucci
+//
+// This software is provided 'as-is', without any express or implied warranty.
+// In no event will the author be held liable for any damages arising from 
+// the use of this software.
+// Permission to use, copy, modify, distribute and sell this software for any 
+// purpose is hereby granted without fee, provided that the above copyright 
+// notice appear in all copies and that both that copyright notice and this 
+// permission notice appear in supporting documentation.
+//
+//////////////////////////////////////////////////////////////////////////////////
+
+
+using System;
+using System.Drawing;
+using System.Windows.Forms;
+
+namespace StickyWindowLibrary
+{
+    public class WinFormAdapter : IFormAdapter
+    {
+        private readonly Form _form;
+
+        public WinFormAdapter(Form form)
+        {
+            _form = form;
+        }
+
+        #region IFormAdapter Members
+
+        public IntPtr Handle
+        {
+            get { return _form.Handle; }
+        }
+
+        public Rectangle Bounds
+        {
+            get { return _form.Bounds; }
+            set { _form.Bounds = value; }
+        }
+
+        public Size MaximumSize
+        {
+            get { return _form.MaximumSize; }
+            set { _form.MaximumSize = value; }
+        }
+
+        public Size MinimumSize
+        {
+            get { return _form.MinimumSize; }
+            set { _form.MinimumSize = value; }
+        }
+
+        public bool Capture
+        {
+            get { return _form.Capture; }
+            set { _form.Capture = value; }
+        }
+
+        public void Activate()
+        {
+            _form.Activate();
+        }
+
+        public Point PointToScreen(Point point)
+        {
+            return _form.PointToScreen(point);
+        }
+
+        #endregion
+    }
+}

StickyWindowLibrary/WpfFormAdapter.cs

+////////////////////////////////////////////////////////////////////////////////
+// StickyWindows
+// 
+// Copyright (c) 2009 Riccardo Pietrucci
+//
+// This software is provided 'as-is', without any express or implied warranty.
+// In no event will the author be held liable for any damages arising from 
+// the use of this software.
+// Permission to use, copy, modify, distribute and sell this software for any 
+// purpose is hereby granted without fee, provided that the above copyright 
+// notice appear in all copies and that both that copyright notice and this 
+// permission notice appear in supporting documentation.
+//
+//////////////////////////////////////////////////////////////////////////////////
+
+
+using System;
+using System.Drawing;
+using System.Runtime.InteropServices;
+using System.Windows;
+using System.Windows.Input;
+using System.Windows.Interop;
+using Point=System.Drawing.Point;
+using Size=System.Drawing.Size;
+using System.Windows.Media;
+using System.Diagnostics;
+
+namespace StickyWindowLibrary
+{
+    public class WpfFormAdapter : IFormAdapter
+    {
+        private readonly Window _window;
+        private Point? _origin;
+
+        public WpfFormAdapter(Window window)
+        {
+            _window = window;
+        }
+
+        #region IFormAdapter Members
+
+        public IntPtr Handle
+        {
+            get
+            {
+                return new WindowInteropHelper(_window).Handle;
+            }
+        }
+
+        public Rectangle Bounds
+        {
+            get
+            {
+                // converti width ed height ad absolute
+                System.Windows.Point widthHeightPointConverted = fromRelativeToDevice(_window.ActualWidth, _window.ActualHeight, _window);
+
+                // converti coordinate da relative a screen: la libreria lavora con quelle
+                Point origin = getWindowOrigin();
+                Point pStart = this.PointToScreen(origin);
+                Point pEnd = this.PointToScreen(origin + new Size(Convert.ToInt32(widthHeightPointConverted.X), Convert.ToInt32(widthHeightPointConverted.Y)));
+                pEnd.Offset(-pStart.X, -pStart.Y); // ora pend rappresenta width + height
+
+                // imposta
+                return new Rectangle(pStart.X, pStart.Y, pEnd.X, pEnd.Y);
+            }
+            set
+            {
+                // converti width ed height a relative
+                System.Windows.Point widthHeightPointConverted = fromDeviceToRelative(value.Width, value.Height, _window);
+                // converti coordinate da screen a relative: il video non si deve alterare!
+                Point origin = getWindowOrigin();
+                Point screenPointRef = new Point(-origin.X + value.X, -origin.Y + value.Y);
+                var pStart = this.PointFromScreen(new Point(screenPointRef.X, screenPointRef.Y));
+
+                // imposta
+                _window.Left += pStart.X;
+                _window.Top += pStart.Y;
+                _window.Width = widthHeightPointConverted.X;
+                _window.Height = widthHeightPointConverted.Y;
+            }
+        }
+
+        public Size MaximumSize
+        {
+            get { return new Size(Convert.ToInt32(_window.MaxWidth), Convert.ToInt32(_window.MaxHeight)); }
+            set { 
+                _window.MaxWidth = value.Width;
+                _window.MaxHeight = value.Height;
+            }
+        }
+
+        public Size MinimumSize
+        {
+            get { return new Size(Convert.ToInt32(_window.MinWidth), Convert.ToInt32(_window.MinHeight)); }
+            set
+            {
+                _window.MinWidth = value.Width;
+                _window.MinHeight = value.Height;
+            }
+        }
+
+        public bool Capture
+        {
+            get { return _window.IsMouseCaptured; }
+            set
+            {
+                IInputElement targetToCapture = value ? _window : null;
+                Mouse.Capture(targetToCapture);
+            }
+        }
+
+        public void Activate()
+        {
+            _window.Activate();
+        }
+
+        public Point PointToScreen(Point pointWin)
+        {
+            System.Windows.Point p = new System.Windows.Point();
+            Point resultWpf = toWinPoint(_window.PointToScreen(p));
+            Point resultScaled = resultWpf + new Size(pointWin);
+            return resultScaled;
+        }
+
+        #endregion
+
+        #region Utility Methods
+
+        private Point getWindowOrigin()
+        {
+            // TODO: alla prima invocazione far andare in cache per migliorare perf ed evitare errori di approx
+            //return new Point(-4, -28);
+            if(!_origin.HasValue)
+            {
+                var currentWinPointConverted = fromRelativeToDevice(-_window.Left, -_window.Top, _window);
+                Point locationFromScreen = this.PointToScreen(toWinPoint(currentWinPointConverted));
+                _origin = new Point(-locationFromScreen.X, -locationFromScreen.Y);
+            }
+
+            return _origin.Value;
+        }
+
+        private static System.Windows.Point fromDeviceToRelative(double x, double y, Visual workingVisual)
+        {
+            Point widthHeightPoint = new Point(Convert.ToInt32(x), Convert.ToInt32(y));
+            PresentationSource source = PresentationSource.FromVisual(workingVisual);
+            return source.CompositionTarget.TransformFromDevice.Transform(toWpfPoint(widthHeightPoint));
+        }
+
+        private static System.Windows.Point fromRelativeToDevice(double x, double y, Visual workingVisual)
+        {
+            Point widthHeightPoint = new Point(Convert.ToInt32(x), Convert.ToInt32(y));
+            PresentationSource source = PresentationSource.FromVisual(workingVisual);
+            return source.CompositionTarget.TransformToDevice.Transform(toWpfPoint(widthHeightPoint));
+        }
+
+        public Point PointFromScreen(Point pointWin)
+        {
+            return toWinPoint(_window.PointFromScreen(toWpfPoint(pointWin)));
+        }
+
+        private static System.Windows.Point toWpfPoint(Point point)
+        {
+            return new System.Windows.Point(point.X, point.Y);
+        }
+
+        private static Point toWinPoint(System.Windows.Point point)
+        {
+            return new Point(Convert.ToInt32(point.X), Convert.ToInt32(point.Y));
+        }
+
+        #endregion
+    }
+}
+using System;
+using System.Drawing;
+using System.Collections;
+using System.ComponentModel;
+using System.Windows.Forms;
+using System.Data;
+using StickyWindowLibrary;
+
+namespace WinTest
+{
+    /// <summary>
+    /// Summary description for Form1.
+    /// </summary>
+    public class Form1 : System.Windows.Forms.Form
+    {
+        private System.Windows.Forms.Button button1;
+        /// <summary>
+        /// Required designer variable.
+        /// </summary>
+        private System.ComponentModel.Container components = null;
+
+        public Form1()
+        {
+            //
+            // Required for Windows Form Designer support
+            //
+            InitializeComponent();
+
+            //
+            // TODO: Add any constructor code after InitializeComponent call
+            //
+
+            Blue.Windows.StickyWindow.RegisterExternalReferenceForm(this);
+        }
+
+        /// <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()
+        {
+            this.button1 = new System.Windows.Forms.Button();
+            this.SuspendLayout();
+            // 
+            // button1
+            // 
+            this.button1.Location = new System.Drawing.Point(10, 16);
+            this.button1.Name = "button1";
+            this.button1.Size = new System.Drawing.Size(102, 23);
+            this.button1.TabIndex = 0;
+            this.button1.Text = "New Test Form";
+            this.button1.Click += new System.EventHandler(this.button1_Click);
+            // 
+            // Form1
+            // 
+            this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
+            this.ClientSize = new System.Drawing.Size(350, 53);
+            this.Controls.Add(this.button1);
+            this.Name = "Form1";
+            this.Text = "Form1";
+            this.ResumeLayout(false);
+
+        }
+        #endregion
+
+        /// <summary>
+        /// The main entry point for the application.
+        /// </summary>
+        [STAThread]
+        static void Main() 
+        {
+            Application.Run(new Form1());
+        }
+
+        private void button1_Click(object sender, System.EventArgs e)
+        {
+            Form2 ff = new Form2();
+            ff.Show();
+        }
+    }
+}

WinTest/Form1.resx

+<?xml version="1.0" encoding="utf-8"?>
+<root>
+  <!-- 
+    Microsoft ResX Schema 
+    
+    Version 1.3
+    
+    The primary goals of this format is to allow a simple XML format 
+    that is mostly human readable. The generation and parsing of the 
+    various data types are done through the TypeConverter classes 
+    associated with the data types.
+    
+    Example:
+    
+    ... ado.net/XML headers & schema ...
+    <resheader name="resmimetype">text/microsoft-resx</resheader>
+    <resheader name="version">1.3</resheader>
+    <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+    <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+    <data name="Name1">this is my long string</data>
+    <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+    <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+        [base64 mime encoded serialized .NET Framework object]
+    </data>
+    <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+        [base64 mime encoded string representing a byte array form of the .NET Framework object]
+    </data>
+                
+    There are any number of "resheader" rows that contain simple 
+    name/value pairs.
+    
+    Each data row contains a name, and value. The row also contains a 
+    type or mimetype. Type corresponds to a .NET class that support 
+    text/value conversion through the TypeConverter architecture. 
+    Classes that don't support this are serialized and stored with the 
+    mimetype set.
+    
+    The mimetype is used forserialized objects, and tells the 
+    ResXResourceReader how to depersist the object. This is currently not 
+    extensible. For a given mimetype the value must be set accordingly:
+    
+    Note - application/x-microsoft.net.object.binary.base64 is the format 
+    that the ResXResourceWriter will generate, however the reader can 
+    read any of the formats listed below.
+    
+    mimetype: application/x-microsoft.net.object.binary.base64
+    value   : The object must be serialized with 
+            : System.Serialization.Formatters.Binary.BinaryFormatter
+            : and then encoded with base64 encoding.
+    
+    mimetype: application/x-microsoft.net.object.soap.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+            : and then encoded with base64 encoding.
+
+    mimetype: application/x-microsoft.net.object.bytearray.base64
+    value   : The object must be serialized into a byte array 
+            : using a System.ComponentModel.TypeConverter
+            : and then encoded with base64 encoding.
+    -->
+  <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+    <xsd:element name="root" msdata:IsDataSet="true">
+      <xsd:complexType>
+        <xsd:choice maxOccurs="unbounded">
+          <xsd:element name="data">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+                <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" msdata:Ordinal="1" />
+              <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+              <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="resheader">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" />
+            </xsd:complexType>
+          </xsd:element>
+        </xsd:choice>
+      </xsd:complexType>
+    </xsd:element>
+  </xsd:schema>
+  <resheader name="resmimetype">
+    <value>text/microsoft-resx</value>
+  </resheader>
+  <resheader name="version">
+    <value>1.3</value>
+  </resheader>
+  <resheader name="reader">
+    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <resheader name="writer">
+    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <data name="button1.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+    <value>False</value>
+  </data>
+  <data name="button1.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+    <value>Private</value>
+  </data>
+  <data name="button1.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+    <value>Private</value>
+  </data>
+  <data name="$this.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+    <value>False</value>
+  </data>
+  <data name="$this.Language" type="System.Globalization.CultureInfo, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+    <value>(Default)</value>
+  </data>
+  <data name="$this.TrayLargeIcon" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+    <value>False</value>
+  </data>
+  <data name="$this.Localizable" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+    <value>False</value>
+  </data>
+  <data name="$this.GridSize" type="System.Drawing.Size, System.Drawing, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
+    <value>2, 2</value>
+  </data>
+  <data name="$this.Name">
+    <value>Form1</value>
+  </data>
+  <data name="$this.DrawGrid" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+    <value>True</value>
+  </data>
+  <data name="$this.TrayHeight" type="System.Int32, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+    <value>80</value>
+  </data>
+  <data name="$this.SnapToGrid" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+    <value>True</value>
+  </data>
+  <data name="$this.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+    <value>Private</value>
+  </data>
+</root>
+using System;
+using System.Drawing;
+using System.Collections;
+using System.ComponentModel;
+using System.Windows.Forms;
+
+using Blue.Windows;
+using StickyWindowLibrary;
+
+namespace WinTest
+{
+    /// <summary>
+    /// Summary description for Form2.
+    /// </summary>
+    public class Form2 : System.Windows.Forms.Form
+    {
+        private StickyWindow	stickyWindow;
+
+        private System.Windows.Forms.CheckBox checkStickToScreen;
+        private System.Windows.Forms.CheckBox checkStickToOthers;
+        private System.Windows.Forms.CheckBox checkStickOnResize;
+        private System.Windows.Forms.CheckBox checkStickOnMove;
+        /// <summary>
+        /// Required designer variable.
+        /// </summary>
+        private System.ComponentModel.Container components = null;
+
+        public Form2()
+        {
+            InitializeComponent();
+            stickyWindow = new StickyWindow( this );
+            checkStickOnMove.Checked	= stickyWindow.StickOnMove;
+            checkStickOnResize.Checked	= stickyWindow.StickOnResize;
+            checkStickToOthers.Checked	= stickyWindow.StickToOther;
+            checkStickToScreen.Checked	= stickyWindow.StickToScreen;
+        }
+
+        /// <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()
+        {
+            this.checkStickToScreen = new System.Windows.Forms.CheckBox();
+            this.checkStickToOthers = new System.Windows.Forms.CheckBox();
+            this.checkStickOnResize = new System.Windows.Forms.CheckBox();
+            this.checkStickOnMove = new System.Windows.Forms.CheckBox();
+            this.SuspendLayout();
+            // 
+            // checkStickToScreen
+            // 
+            this.checkStickToScreen.Location = new System.Drawing.Point(26, 30);
+            this.checkStickToScreen.Name = "checkStickToScreen";
+            this.checkStickToScreen.Size = new System.Drawing.Size(125, 28);
+            this.checkStickToScreen.TabIndex = 0;
+            this.checkStickToScreen.Text = "Stick to Screen";
+            this.checkStickToScreen.CheckedChanged += new System.EventHandler(this.checkStickToScreen_CheckedChanged);
+            // 
+            // checkStickToOthers
+            // 
+            this.checkStickToOthers.Location = new System.Drawing.Point(26, 67);
+            this.checkStickToOthers.Name = "checkStickToOthers";
+            this.checkStickToOthers.Size = new System.Drawing.Size(125, 28);
+            this.checkStickToOthers.TabIndex = 1;
+            this.checkStickToOthers.Text = "Stick to Others";
+            this.checkStickToOthers.CheckedChanged += new System.EventHandler(this.checkStickToOthers_CheckedChanged);
+            // 
+            // checkStickOnResize
+            // 
+            this.checkStickOnResize.Location = new System.Drawing.Point(26, 141);
+            this.checkStickOnResize.Name = "checkStickOnResize";
+            this.checkStickOnResize.Size = new System.Drawing.Size(125, 27);
+            this.checkStickOnResize.TabIndex = 2;
+            this.checkStickOnResize.Text = "Stick on Resize";
+            this.checkStickOnResize.CheckedChanged += new System.EventHandler(this.checkStickOnResize_CheckedChanged);
+            // 
+            // checkStickOnMove
+            // 
+            this.checkStickOnMove.Location = new System.Drawing.Point(26, 178);
+            this.checkStickOnMove.Name = "checkStickOnMove";
+            this.checkStickOnMove.Size = new System.Drawing.Size(125, 27);
+            this.checkStickOnMove.TabIndex = 3;
+            this.checkStickOnMove.Text = "Stick On Move";
+            this.checkStickOnMove.CheckedChanged += new System.EventHandler(this.checkStickOnMove_CheckedChanged);
+            // 
+            // Form2
+            // 
+            this.AutoScaleBaseSize = new System.Drawing.Size(6, 15);
+            this.ClientSize = new System.Drawing.Size(292, 266);
+            this.Controls.Add(this.checkStickOnMove);
+            this.Controls.Add(this.checkStickOnResize);
+            this.Controls.Add(this.checkStickToOthers);
+            this.Controls.Add(this.checkStickToScreen);
+            this.Name = "Form2";
+            this.StartPosition = System.Windows.Forms.FormStartPosition.Manual;
+            this.Text = "Form2";
+            this.Load += new System.EventHandler(this.Form2_Load);
+            this.ResumeLayout(false);
+
+        }
+        #endregion
+
+        private void Form2_Load(object sender, System.EventArgs e)
+        {
+        }
+
+        private void checkStickToScreen_CheckedChanged(object sender, System.EventArgs e)
+        {
+            stickyWindow.StickToScreen = checkStickToScreen.Checked;
+        }
+
+        private void checkStickToOthers_CheckedChanged(object sender, System.EventArgs e)
+        {
+            stickyWindow.StickToOther = checkStickToOthers.Checked;
+        }
+
+        private void checkStickOnResize_CheckedChanged(object sender, System.EventArgs e)
+        {
+            stickyWindow.StickOnResize = checkStickOnResize.Checked;
+        }
+
+        private void checkStickOnMove_CheckedChanged(object sender, System.EventArgs e)
+        {
+            stickyWindow.StickOnMove = checkStickOnMove.Checked;
+        }
+    }
+}

WinTest/Form2.resx

+<?xml version="1.0" encoding="utf-8"?>
+<root>
+  <!-- 
+    Microsoft ResX Schema 
+    
+    Version 2.0
+    
+    The primary goals of this format is to allow a simple XML format 
+    that is mostly human readable. The generation and parsing of the 
+    various data types are done through the TypeConverter classes 
+    associated with the data types.
+    
+    Example:
+    
+    ... ado.net/XML headers & schema ...
+    <resheader name="resmimetype">text/microsoft-resx</resheader>
+    <resheader name="version">2.0</resheader>
+    <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+    <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+    <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+    <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+    <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+        <value>[base64 mime encoded serialized .NET Framework object]</value>
+    </data>
+    <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+        <comment>This is a comment</comment>
+    </data>
+                
+    There are any number of "resheader" rows that contain simple 
+    name/value pairs.
+    
+    Each data row contains a name, and value. The row also contains a 
+    type or mimetype. Type corresponds to a .NET class that support 
+    text/value conversion through the TypeConverter architecture. 
+    Classes that don't support this are serialized and stored with the 
+    mimetype set.
+    
+    The mimetype is used for serialized objects, and tells the 
+    ResXResourceReader how to depersist the object. This is currently not 
+    extensible. For a given mimetype the value must be set accordingly:
+    
+    Note - application/x-microsoft.net.object.binary.base64 is the format 
+    that the ResXResourceWriter will generate, however the reader can 
+    read any of the formats listed below.
+    
+    mimetype: application/x-microsoft.net.object.binary.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
+            : and then encoded with base64 encoding.
+    
+    mimetype: application/x-microsoft.net.object.soap.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+            : and then encoded with base64 encoding.
+
+    mimetype: application/x-microsoft.net.object.bytearray.base64
+    value   : The object must be serialized into a byte array 
+            : using a System.ComponentModel.TypeConverter
+            : and then encoded with base64 encoding.
+    -->
+  <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+    <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
+    <xsd:element name="root" msdata:IsDataSet="true">
+      <xsd:complexType>
+        <xsd:choice maxOccurs="unbounded">
+          <xsd:element name="metadata">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" />
+              </xsd:sequence>
+              <xsd:attribute name="name" use="required" type="xsd:string" />
+              <xsd:attribute name="type" type="xsd:string" />
+              <xsd:attribute name="mimetype" type="xsd:string" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="assembly">
+            <xsd:complexType>
+              <xsd:attribute name="alias" type="xsd:string" />
+              <xsd:attribute name="name" type="xsd:string" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="data">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+                <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
+              <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+              <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="resheader">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" />
+            </xsd:complexType>
+          </xsd:element>
+        </xsd:choice>
+      </xsd:complexType>
+    </xsd:element>
+  </xsd:schema>
+  <resheader name="resmimetype">
+    <value>text/microsoft-resx</value>
+  </resheader>
+  <resheader name="version">
+    <value>2.0</value>
+  </resheader>
+  <resheader name="reader">
+    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <resheader name="writer">
+    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+</root>

WinTest/Properties/AssemblyInfo.cs

+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following 
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("WinTest")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("Reply")]
+[assembly: AssemblyProduct("WinTest")]
+[assembly: AssemblyCopyright("Copyright © Reply 2009")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible 
+// to COM components.  If you need to access a type in this assembly from 
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("b9caf167-a392-493a-a833-85c6653f4a40")]
+
+// Version information for an assembly consists of the following four values:
+//
+//      Major Version
+//      Minor Version 
+//      Build Number
+//      Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers 
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]

WinTest/Properties/Resources.Designer.cs

+//------------------------------------------------------------------------------
+// <auto-generated>
+//     This code was generated by a tool.
+//     Runtime Version:2.0.50727.3053
+//
+//     Changes to this file may cause incorrect behavior and will be lost if
+//     the code is regenerated.
+// </auto-generated>
+//------------------------------------------------------------------------------
+
+namespace WinTest.Properties
+{
+
+
+    /// <summary>
+    ///   A strongly-typed resource class, for looking up localized strings, etc.
+    /// </summary>
+    // This class was auto-generated by the StronglyTypedResourceBuilder
+    // class via a tool like ResGen or Visual Studio.
+    // To add or remove a member, edit your .ResX file then rerun ResGen
+    // with the /str option, or rebuild your VS project.
+    [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "2.0.0.0")]
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+    [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+    internal class Resources
+    {
+
+        private static global::System.Resources.ResourceManager resourceMan;
+
+        private static global::System.Globalization.CultureInfo resourceCulture;
+
+        [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
+        internal Resources()
+        {
+        }
+
+        /// <summary>
+        ///   Returns the cached ResourceManager instance used by this class.
+        /// </summary>
+        [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+        internal static global::System.Resources.ResourceManager ResourceManager
+        {
+            get
+            {
+                if ((resourceMan == null))
+                {
+                    global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("WinTest.Properties.Resources", typeof(Resources).Assembly);
+                    resourceMan = temp;
+                }
+                return resourceMan;
+            }
+        }
+
+        /// <summary>
+        ///   Overrides the current thread's CurrentUICulture property for all
+        ///   resource lookups using this strongly typed resource class.
+        /// </summary>
+        [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+        internal static global::System.Globalization.CultureInfo Culture
+        {
+            get
+            {
+                return resourceCulture;
+            }
+            set
+            {
+                resourceCulture = value;
+            }
+        }
+    }
+}

WinTest/Properties/Resources.resx

+<?xml version="1.0" encoding="utf-8"?>
+<root>
+  <!-- 
+    Microsoft ResX Schema 
+    
+    Version 2.0
+    
+    The primary goals of this format is to allow a simple XML format 
+    that is mostly human readable. The generation and parsing of the 
+    various data types are done through the TypeConverter classes 
+    associated with the data types.
+    
+    Example:
+    
+    ... ado.net/XML headers & schema ...
+    <resheader name="resmimetype">text/microsoft-resx</resheader>
+    <resheader name="version">2.0</resheader>
+    <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+    <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+    <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+    <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+    <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+        <value>[base64 mime encoded serialized .NET Framework object]</value>
+    </data>
+    <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+        <comment>This is a comment</comment>
+    </data>
+                
+    There are any number of "resheader" rows that contain simple 
+    name/value pairs.
+    
+    Each data row contains a name, and value. The row also contains a 
+    type or mimetype. Type corresponds to a .NET class that support 
+    text/value conversion through the TypeConverter architecture. 
+    Classes that don't support this are serialized and stored with the 
+    mimetype set.
+    
+    The mimetype is used for serialized objects, and tells the 
+    ResXResourceReader how to depersist the object. This is currently not 
+    extensible. For a given mimetype the value must be set accordingly:
+    
+    Note - application/x-microsoft.net.object.binary.base64 is the format 
+    that the ResXResourceWriter will generate, however the reader can 
+    read any of the formats listed below.
+    
+    mimetype: application/x-microsoft.net.object.binary.base64
+    value   : The object must be serialized with 
+            : System.Serialization.Formatters.Binary.BinaryFormatter
+            : and then encoded with base64 encoding.
+    
+    mimetype: application/x-microsoft.net.object.soap.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+            : and then encoded with base64 encoding.
+
+    mimetype: application/x-microsoft.net.object.bytearray.base64
+    value   : The object must be serialized into a byte array 
+            : using a System.ComponentModel.TypeConverter
+            : and then encoded with base64 encoding.
+    -->
+  <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+    <xsd:element name="root" msdata:IsDataSet="true">
+      <xsd:complexType>
+        <xsd:choice maxOccurs="unbounded">
+          <xsd:element name="metadata">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" />
+              <xsd:attribute name="type" type="xsd:string" />
+              <xsd:attribute name="mimetype" type="xsd:string" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="assembly">
+            <xsd:complexType>
+              <xsd:attribute name="alias" type="xsd:string" />
+              <xsd:attribute name="name" type="xsd:string" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="data">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+                <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" msdata:Ordinal="1" />
+              <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+              <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="resheader">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" />
+            </xsd:complexType>
+          </xsd:element>
+        </xsd:choice>
+      </xsd:complexType>
+    </xsd:element>
+  </xsd:schema>
+  <resheader name="resmimetype">
+    <value>text/microsoft-resx</value>
+  </resheader>
+  <resheader name="version">
+    <value>2.0</value>
+  </resheader>
+  <resheader name="reader">
+    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <resheader name="writer">
+    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+</root>

WinTest/Properties/Settings.Designer.cs

+//------------------------------------------------------------------------------
+// <auto-generated>
+//     This code was generated by a tool.
+//     Runtime Version:2.0.50727.3053
+//
+//     Changes to this file may cause incorrect behavior and will be lost if
+//     the code is regenerated.
+// </auto-generated>
+//------------------------------------------------------------------------------
+
+namespace WinTest.Properties
+{
+
+
+    [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+    [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "9.0.0.0")]
+    internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase
+    {
+
+        private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
+
+        public static Settings Default
+        {
+            get
+            {
+                return defaultInstance;
+            }
+        }
+    }
+}

WinTest/Properties/Settings.settings

+<?xml version='1.0' encoding='utf-8'?>
+<SettingsFile xmlns="http://schemas.microsoft.com/VisualStudio/2004/01/settings" CurrentProfile="(Default)">
+  <Profiles>
+    <Profile Name="(Default)" />
+  </Profiles>
+  <Settings />
+</SettingsFile>

WinTest/WinTest.csproj

+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="3.5" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <PropertyGroup>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+    <ProductVersion>9.0.30729</ProductVersion>
+    <SchemaVersion>2.0</SchemaVersion>
+    <ProjectGuid>{609227AC-69FB-43D6-8E44-9817D260C2D0}</ProjectGuid>
+    <OutputType>WinExe</OutputType>
+    <AppDesignerFolder>Properties</AppDesignerFolder>
+    <RootNamespace>WinTest</RootNamespace>
+    <AssemblyName>WinTest</AssemblyName>
+    <TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
+    <FileAlignment>512</FileAlignment>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+    <DebugSymbols>true</DebugSymbols>
+    <DebugType>full</DebugType>
+    <Optimize>false</Optimize>
+    <OutputPath>bin\Debug\</OutputPath>
+    <DefineConstants>DEBUG;TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+    <DebugType>pdbonly</DebugType>
+    <Optimize>true</Optimize>
+    <OutputPath>bin\Release\</OutputPath>
+    <DefineConstants>TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+  </PropertyGroup>
+  <ItemGroup>
+    <Reference Include="PresentationCore">
+      <RequiredTargetFramework>3.0</RequiredTargetFramework>
+    </Reference>
+    <Reference Include="PresentationFramework">
+      <RequiredTargetFramework>3.0</RequiredTargetFramework>
+    </Reference>
+    <Reference Include="System" />
+    <Reference Include="System.Core">
+      <RequiredTargetFramework>3.5</RequiredTargetFramework>
+    </Reference>
+    <Reference Include="System.Xml.Linq">
+      <RequiredTargetFramework>3.5</RequiredTargetFramework>
+    </Reference>
+    <Reference Include="System.Data.DataSetExtensions">
+      <RequiredTargetFramework>3.5</RequiredTargetFramework>
+    </Reference>
+    <Reference Include="System.Data" />
+    <Reference Include="System.Deployment" />
+    <Reference Include="System.Drawing" />
+    <Reference Include="System.Windows.Forms" />
+    <Reference Include="System.Xml" />
+    <Reference Include="WindowsBase">
+      <RequiredTargetFramework>3.0</RequiredTargetFramework>
+    </Reference>
+  </ItemGroup>
+  <ItemGroup>
+    <Compile Include="Form1.cs">
+      <SubType>Form</SubType>
+    </Compile>
+    <Compile Include="Form2.cs">
+      <SubType>Form</SubType>
+    </Compile>
+    <Compile Include="Properties\AssemblyInfo.cs" />
+    <EmbeddedResource Include="Form1.resx">
+      <DependentUpon>Form1.cs</DependentUpon>
+    </EmbeddedResource>