using System; using System.Drawing; using System.Drawing.Drawing2D; using System.Collections; using System.ComponentModel; using System.Windows.Forms; namespace StrangeControls { // Объявляется класс – наследник базового класса Form. // Наша форма, конечно же, основывается на обычной классической // прямоугольной, масштабируемой форме. // Прежде всего это означает, что у нее имеется свойство Size, // значения которого используются для определения размеров // составляющих нашу форму элементов. // Наша форма состоит из двух элементов: // прямоугольника-заголовка // (здесь должны размещаться основные элементы управления формы); // эллипсовидной клиентской области с голубой каемочкой. 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 // Required method for Designer support – do not modify // the contents of this method with the code editor. 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 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(); } } }