www.pudn.com > sudoku.rar > ScalingPanel.cs


//-------------------------------------------------------------------------- 
//  
//  Copyright (c) Microsoft Corporation.  All rights reserved.  
//  
//  File: ScalingPanel.cs 
// 
//  Description: A panel that maintains the relative size and position of its children. 
//  
//-------------------------------------------------------------------------- 
 
using System; 
using System.Drawing; 
using System.Collections; 
using System.ComponentModel; 
using System.Windows.Forms; 
 
namespace Microsoft.Sudoku.Controls 
{ 
	/// Resizes contained controls based on maintaining original aspect ratios. 
	internal class ScalingPanel : NoFlickerPanel 
	{ 
		/// Initializes the panel. 
		public ScalingPanel(){} 
 
		/// The initial bounds of the panel. 
		private Rectangle _initialBounds; 
 
		/// Table of controls and their respective original bounds. 
		private Hashtable _controlBounds; 
 
		/// Whether the panel has been initialized. 
		private bool _initialized; 
 
		/// Initializes the panel based on the current controls in it. 
		public void ConfigureByContainedControls() 
		{ 
			_initialBounds = Bounds; 
			_controlBounds = new Hashtable(); 
			foreach(Control c in this.Controls) 
			{ 
				_controlBounds.Add(c, c.Bounds); 
			} 
			_initialized = true; 
		} 
 
		/// Rescales all contained controls. 
		/// Event arguments. 
		protected override void OnLayout(LayoutEventArgs levent) 
		{ 
			if (_initialized && Width > 0 && Height > 0 && levent.AffectedControl == this) 
			{ 
				// Maintain original aspect ratio 
				int newWidth = Width; 
				int tmp = (int)(_initialBounds.Width / (double)_initialBounds.Height * Height); 
				if (tmp < newWidth) newWidth = tmp; 
 
				int newHeight = Height; 
				tmp = (int)(_initialBounds.Height / (double)_initialBounds.Width * newWidth); 
				if (tmp < newHeight) newHeight = tmp; 
 
				// Keep track of max and min boundaries 
				int minX=int.MaxValue, minY=int.MaxValue, maxX=-1, maxY=-1; 
 
				// Move and resize all controls 
				foreach(Control c in this.Controls) 
				{ 
					Rectangle rect = (Rectangle)_controlBounds[c]; 
 
					// Determine initial best guess at size 
					int x = (int)(rect.X / (double)_initialBounds.Width * newWidth); 
					int y = (int)(rect.Y / (double)_initialBounds.Height * newHeight); 
					int width = (int)(rect.Width / (double)_initialBounds.Width * newWidth); 
					int height = (int)(rect.Height / (double)_initialBounds.Height * newHeight); 
 
					// Set the new bounds 
					Rectangle newBounds = new Rectangle(x, y, width, height); 
					if (newBounds != c.Bounds) c.Bounds = newBounds; 
 
					// Keep track of max and min boundaries 
					if (c.Left < minX) minX = c.Left; 
					if (c.Top < minY) minY = c.Top; 
					if (c.Right  > maxX) maxX = c.Right; 
					if (c.Bottom > maxY) maxY = c.Bottom; 
				} 
 
				// Center all controls 
				int moveX = (Width - (maxX - minX + 1)) / 2; 
				int moveY = (Height - (maxY - minY + 1)) / 2; 
 
				if (moveX > 0 || moveY > 0) 
				{ 
					foreach(Control c in this.Controls)  
					{ 
						c.Location = c.Location + new Size(moveX - minX, moveY - minY); 
					} 
				} 
			} 
 
			// Do base layout 
			base.OnLayout (levent); 
		} 
	} 
}