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);
}
}
}