using System;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
namespace StrangeControls
{
/// <summary>
/// Объявляется класс-наследник базового класса Form.
/// Наша форма, конечно же, основывается на обычной классической
/// прямоугольной, масштабируемой форме.
/// Прежде всего, это означает,что у неё имеется свойство Size,
/// значения которого используются для определения размеров
/// составляющих нашу форму элементов.
/// Наша форма состоит из двух элементов:
/// Прямоугольника-заголовка (здесь должны размещаться основные элементы управления формы).
/// Эллипсовидной клиентской области с голубой каёмочкой.
/// </summary>
public class RoundForm : System.Windows.Forms.Form
{
private System.ComponentModel.Container components = null;
// Объект headSize используется для управления размерами формы.
private Size headSize;
// bw - (border width) это переменная,
// сохраняющая метрические характеристики рамки.
// В дальнейшем это значение используется для определения
// размеров нашей формы.
int bw;
// Ничем не примечательный конструктор...
public RoundForm()
{
InitializeComponent();
}
#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()
{
//
// RoundForm
//
this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
this.ClientSize = new System.Drawing.Size(292, 273);
this.Cursor = System.Windows.Forms.Cursors.Cross;
this.MinimumSize = new System.Drawing.Size(100, 100);
this.Name = "RoundForm";
this.Text = "RoundForm";
this.Resize += new System.EventHandler(this.RoundForm_Resize);
}
#endregion
/// <summary>
/// Clean up any resources being used.
/// </summary>
protected override void Dispose( bool disposing )
{
if( disposing )
{
if(components != null)
{
components.Dispose();
}
}
base.Dispose( disposing );
}
// Обработчик события, связанного с изменением формы окна обеспечивает
// вызов метода, в котором определяются основные характеристики
// составляющих формы.
private void RoundForm_Resize(object sender, System.EventArgs e)
{
SetSize();
}
// Код, определяюший габариты ФОРМЫ - весь здесь...
// Это определение метрических характеристик ФОРМЫ.
protected void SetSize()
{
// Всего ничего...
// На основе соответствующей "классической" формы
// определяются размеры прямоугольной составляющей (заголовка формы).
int w = this.Size.Width;
bw = (int)((w - this.ClientSize.Width)/2);
int h = this.Size.Height;
int bh = h - this.ClientSize.Height - bw;
headSize = new Size(w,bh);
}
// В рамках переопределённой виртуальной функции...
protected override void OnPaint(PaintEventArgs e)
{
// Определяем габариты формы.
SetSize();
// Получаем ссылку на графический контекст.
Graphics gr = this.CreateGraphics();
// Карандаш для отрисовки каёмочки.
Pen pen = new Pen(SystemColors.Desktop,bw);
// Объект, поддерживающий контуры формы.
GraphicsPath gp = new GraphicsPath();
// Контуры формы образуются прямоугольником
//(его характеристики совпадают с заголовком формы).
// класс GraphicsPath не имеет метода, который позволял
// бы непосредственно подсоединять прямоугольные области.
// Поэтому структура Rectangle предварительно определяется.
// С эллипсом проще. Он подсоединяется "на лету",
// без предварительного опредедления.
Rectangle rect = new Rectangle(0,0,headSize.Width,headSize.Height);
gp.AddRectangle(rect);
gp.AddEllipse(bw,headSize.Height,this.ClientSize.Width,this.ClientSize.Height);
// Сформировали объект, поддерживающий контуры формы.
// И на его основе создаём объект, который описывает внутреннюю часть
// графической формы.
// В нашем случае она состоит из прямоугольника и эллипса.
Region reg = new Region(gp);
// У любой формы имеется свойство Region.
// У нашей формы - он прекрасен.
this.Region = reg;
// Рисуем каёмочку...
gr.DrawEllipse(pen,0,0,this.ClientSize.Width,this.ClientSize.Height);
// Освобождаем занятые ресурсы.
gr.Dispose();
}
}
}