GDI+ - это набор программных средств, которые используются в .NET.
GDI+ позволяют создателям приложений выводить данные на экран или на принтер без необходимости обеспечивать работу с определенными типами устройств отображения. Для отображения информации программисту достаточно вызывать нужные методы классов GDI+. При этом автоматически учитываются типы определенных устройств и выполняются вызовы соответствующих драйверов.
Класс, который ИНКАПСУЛИРУЕТ поверхность рисования GDI+. Для этого класса не определен ни один конструктор. Видимо, успех в деле ручного конструирования инкапсулятора поверхностей рисования (еще вопрос, сколько разновидностей таких поверхностей) представляется проблематичным.
Конкретный объект – представитель класса Graphics предоставляется в виде ссылки методами-обработчиками событий либо создается в ходе выполнения ряда методов применительно к конкретным объектам, обладающим "поверхностями рисования" (клиентская область формы, кнопки, панели, битовая матрица):
Bitmap bmp; Pen greedPen; ::::: greedPen = new Pen(Color.FromArgb(50, 0, 0, 255), 1); // Новая битовая карта под новый размер клиентской области формы. bmp = new Bitmap(this.ClientSize.Width, this.ClientSize.Height); Graphics gr = Graphics.FromImage(bmp); gr.DrawLine(this.greedPen, 0, 0, 100, 100); gr.Dispose();
Ниже представлен список членов класса.
Clip |
Получает или задает объект Region, ограничивающий область рисования данного объекта Graphics |
ClipBounds |
Получает структуру RectangleF, которая заключает в себе вырезанную область данного объекта Graphics |
CompositingMode |
Получает значение, задающее порядок рисования сложных изображений в данном объекте Graphics |
CompositingQuality |
Получает или задает качество отображения сложных изображений, которые выводятся в данном объекте Graphics |
DpiX |
Получает горизонтальное разрешение данного объекта Graphics |
DpiY |
Получает вертикальное разрешение данного объекта Graphics |
InterpolationMode |
Получает или задает Graphics |
IsClipEmpty |
Получает значение, которое указывает, является ли вырезанная область данного объекта Graphics пустой |
IsVisibleClipEmpty |
Получает значение, которое указывает, является ли видимая вырезанная область данного объекта Graphics пустой |
PageScale |
Получает или задает масштабирование между универсальными единицами и единицами страницы для данного объекта Graphics |
PageUnit |
Получает или задает единицу измерения для координат страницы данного объекта Graphics |
PixelOffsetMode |
Получает или задает значение, которое задает порядок смещения точек во время отображения данного объекта Graphics |
RenderingOrigin |
Получает или задает исходное заполнение данного объекта Graphics для сглаживания цветовых переходов и для штриховки |
SmoothingMode |
Получает или задает качество заполнения для данного объекта Graphics |
TextContrast |
Получает или задает значение коррекции яркости для отображения текста |
TextRenderingHint |
Получает или задает режим заполнения для текста, связанного с данным объектом Graphics |
Transform |
Получает или задает универсальное преобразование для данного объекта Graphics |
VisibleClipBounds |
Получает или задает рабочий прямоугольник видимой вырезанной области данного объекта Graphics |
AddMetafileComment |
Добавляет комментарий к текущему объекту |
BeginContainer |
Перегружен. Сохраняет графический контейнер, содержащий текущее состояние данного объекта Graphics, а затем открывает и использует новый графический контейнер |
Clear |
Очищает всю поверхность рисования и выполняет заливку поверхности указанным цветом фона |
CreateObjRef |
Создает объект, который содержит всю необходимую информацию для создания прокси-сервера, используемого для коммуникации с удаленными объектами |
Dispose |
Освобождает все ресурсы, используемые данным объектом Graphics |
DrawArc |
Перегружен. Рисует дугу, которая является частью эллипса, заданного парой координат, шириной и высотой |
DrawBezier |
Перегружен. Строит кривую Безье, определяемую четырьмя структурами Point |
DrawBeziers |
Перегружен. Формирует набор кривых Безье из массива структур Point |
DrawClosedCurve |
Перегружен. Строит замкнутую фундаментальную кривую, определяемую массивом структур Point |
DrawCurve |
Перегружен. Строит замкнутую фундаментальную кривую через точки указанного массива структур Point |
DrawEllipse |
Перегружен. Формирует эллипс, который определяется |
DrawIcon |
Перегружен. Формирует изображение, которое представлено указанным объектом Icon, расположенным по указанным координатам |
DrawIconUnstretched |
Формирует изображение, представленное указанным объектом Icon, не масштабируя его |
DrawImage |
Перегружен. Рисует заданный объект Image в заданном месте, используя исходный размер |
DrawImageUnscaled |
Перегружен. Рисует заданное изображение, используя его исходный фактический размер, в расположении, заданном парой координат |
DrawLine |
Перегружен. Проводит линию, соединяющую две точки, определенные парами координат |
DrawLines |
Перегружен. Формирует набор сегментов линии, которые соединяют массив структур Point |
DrawPath |
Рисует объект GraphicsPath |
DrawPie |
Перегружен. Рисует сектор, определенный эллипсом, который задан парой координат, шириной, высотой и двумя радиальными линиями |
DrawPolygon |
Перегружен. Рисует многоугольник, определяемый массивом структур Point |
DrawRectangle |
Перегружен. Рисует прямоугольник, который определен парой координат, шириной и высотой |
DrawRectangles |
Перегружен. Рисует набор прямоугольников, определяемых структурой Rectangle |
DrawString |
Перегружен. Создает текстовую строку в заданном месте с указанными объектами Brush и Font |
EndContainer |
Закрывает текущий графический контейнер и восстанавливает состояние данного объекта Graphics, которое было сохранено при вызове метода BeginContainer |
EnumerateMetafile |
Перегружен. Отправляет записи указанного объекта по отдельности методу обратного вызова, который отображает их в заданной точке |
Equals |
Перегружен. Определяет, равны ли два экземпляра Object |
ExcludeClip |
Перегружен. Обновляет вырезанную область данного объекта Graphics, чтобы исключить из нее часть, определенную структурой Rectangle |
FillClosedCurve |
Перегружен. Заполняет замкнутую фундаментальную кривую, определяемую массивом структур Point |
FillEllipse |
Перегружен. Заполняет внутреннюю часть эллипса, который определяется |
FillPath |
Заполняет внутреннюю часть объекта GraphicsPath |
FillPie |
Перегружен. Заполняет внутреннюю часть сектора, определенного эллипсом, который задан парой координат, шириной, высотой и двумя радиальными линиями |
FillPolygon |
Перегружен. Заполняет внутреннюю часть многоугольника, определенного массивом точек, заданных структурами Point |
FillRectangle |
Перегружен. Заполняет внутреннюю часть прямоугольника, который определен парой координат, шириной и высотой |
FillRectangles |
Перегружен. Заполняет внутреннюю часть набора прямоугольников, определяемого структурами Rectangle |
FillRegion |
Заполняет внутреннюю часть объекта Region |
Flush |
Перегружен. Вызывает принудительное выполнение всех отложенных графических операций и немедленно возвращается, не дожидаясь их окончания |
FromHdc |
Статический. Перегружен. Создает новый объект Graphics из указанного дескриптора для контекста устройства |
FromHdcInternal |
Статический. Внутренний метод. Не используется |
FromHwnd |
Статический. Создает новый объект Graphics из указанного дескриптора для окна |
FromHwndInternal |
Статический. Внутренний метод. Не используется |
FromImage |
Статический. Создает новый объект Graphics из заданного объекта Image |
GetHalftonePalette |
Статический. Получает дескриптор текущей полутоновой палитры Windows |
GetHashCode |
Служит хэш-функцией для конкретного типа, пригоден для использования в алгоритмах хэширования и структурах данных, например в хэш-таблице |
GetHdc |
Получает дескриптор контекста устройства, связанный с данным объектом Graphics |
GetLifetimeService |
Извлекает служебный объект текущего срока действия, который управляет средствами срока действия данного экземпляра |
GetNearestColor |
Получает цвет, ближайший к указанной структуре Color |
GetType |
Возвращает Type текущего экземпляра |
InitializeLifetimeService |
Получает служебный объект срока действия, для управления средствами срока действия данного экземпляра |
IntersectClip |
Перегружен. Обновляет вырезанную область данного объекта Graphics, включая в нее пересечение текущей вырезанной области и указанной структуры Rectangle |
IsVisible |
Перегружен. Указывает, содержится ли точка, заданная с помощью пары координат, в видимой вырезанной области данного объекта Graphics |
MeasureCharacterRanges |
Получает массив объектов Region, каждый из которых связывает диапазон позиций символов в рамках указанной строки |
MeasureString |
Перегружен. Измеряет указанную строку в процессе ее создания с помощью заданного объекта Font |
MultiplyTransform |
Перегружен. Умножает универсальное преобразование данного объекта Graphics на преобразование указанного объекта Matrix |
ReleaseHdc |
Освобождает дескриптор контекста устройства, полученный в результате предыдущего вызова метода GetHdc данного объекта Graphics |
ReleaseHdcInternal |
Внутренний метод. Не используется |
ResetClip |
Сбрасывает вырезанную область данного объекта Graphics и делает ее бесконечной |
ResetTransform |
Сбрасывает матрицу универсального преобразования данного объекта Graphics и делает ее единичной матрицей |
Restore |
Восстанавливает состояние данного объекта Graphics, возвращая его к состоянию объекта GraphicsState |
RotateTransform |
Перегружен. Применяет заданное вращение к матрице преобразования данного объекта Graphics |
Save |
Сохраняет текущее состояние данного объекта Graphics и связывает сохраненное состояние с объектом GraphicsState |
ScaleTransform |
Перегружен. Применяет указанную операцию масштабирования к матрице преобразования данного объекта Graphics путем ее добавления к матрице преобразования объекта |
SetClip |
Перегружен. Задает в качестве вырезанной области данного объекта Graphics свойство Clip указанного объекта Graphics |
ToString |
Возвращает String, который представляет текущий Object |
TransformPoints |
Перегружен. Преобразует массив точек из одного координатного пространства в другое, используя текущее универсальное преобразование и преобразование страницы данного объекта Graphics |
TranslateClip |
Перегружен. Переводит вырезанную область данного объекта Graphics в указанном объеме в горизонтальном и вертикальном направлениях. |
TranslateTransform |
Перегружен. Добавляет заданный перевод к матрице преобразования данного объекта Graphics |
Finalize |
Переопределен. См. Object.Finalize.В языках C# и C++ для функций финализации используется синтаксис деструктора |
MemberwiseClone |
Создает неполную копию текущего Object |
Приводимое ниже приложение демонстрирует технику рисования на невидимых виртуальных поверхностях – в буквальном смысле в оперативной памяти.
Приложение моделирует случайное блуждание множества однородных частиц. Несмотря на интенсивный вывод графической информации, удается избежать эффекта мигания, который возникает при непосредственной модификации внешнего вида элементов управления.
Демонстрация предварительно нарисованной в памяти картинки происходит при помощи элемента управления типа PictureBox, который благодаря свойству объекта Image обеспечивает быстрое отображение выводимой графической информации.
Итак, данное Windows-приложение включает объявление трех классов:
xPoint, объекты которого периодически изменяют собственное положение в пределах клиентской области окна;cForm, который обладает свойствами сохранения постоянного соотношения собственных размеров и размеров клиентской области, и обеспечивает отображение множества блуждающих объектов – представителей класса xPoint ;Program, который в соответствии с предопределенными алгоритмами обеспечивает создание и выполнение приложения.Создается автоматически. Без комментариев.
using System;
using System.Collections.Generic;
using System.Windows.Forms;
namespace cForm
{
static class Program
{
// The main entry point for the application.
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new cForm());
}
}
}
Объявление класса блуждающих объектов:
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Text;
namespace cForm
{
class xPoint
{
// Собственный статический генератор случайных чисел.
// Используется в конструкторе.
public static Random rnd = new Random();
// Цвет объекта.
public Color xColor;
// Текущая позиция. Относительные значения координат X и Y.
public Point p;
// Обеспечение перемещения. Текущие значения координат могут
// изменяться как по X, так и по Y.
public Point direction;
// Счетчик циклов сохранения выбранного направления.
// Объект на протяжении фиксированного интервала времени может
// сохранять ранее избранное направление движения.
// В течение n.X "тиков" для X в течение n.Y "тиков" для Y.
public Point n;
public xPoint(int X, int Y, int Xn, int Yn)
{
n = new Point(rnd.Next(0, Xn), rnd.Next(0, Yn));
direction = new Point(rnd.Next(-1, 2), rnd.Next(-1, 2));
p = new Point(X, Y);
xColor =
Color.FromArgb(150, rnd.Next(0, 256), rnd.Next(0, 256), rnd.Next(0, 256));
}
// Статический метод. Еще вопрос, где следовало размещать его
// объявление... Определение нового положения амебы.
// Просматривается ВЕСЬ список.
// Ее перемещение ограничивается физическими размерами клиентской области
// окна приложения и определяется по двум координатам (X и Y).
// В каждый момент она может оставаться на месте, либо изменить
// свое положение на один "шаг" по каждой из осей координат
// ("вверх" или "вниз" по оси Y и "вперед" или "назад" по оси X).
public static void setNextPosition(cForm cf, xPoint[] pt)
{
int i;
float xy;
// Итак, определение текущей позиции объекта.
// Просмотр массива...
for (i = 0; i < pt.Length; i++)
{
// Сначала разбираемся со значением координаты X.
// Вычисляем возможную позицию после перемещения объекта.
xy = (float)((pt[i].p.X + pt[i].direction.X) * cf.rPointGet);
// Вполне возможно, что это вполне подходящая позиция.
// И надо всего лишь проверить две вещи:
// 1. не выскочит ли объект за пределы клиентской области окна
// приложения,
// 2. не настало ли время поменять направление движения.
if (
xy < 0 || xy > cf.ClientSize.Width // 1.
||
pt[i].n.X > cf.NX // 2.
)
{
pt[i].n.X = 0; // Обнулили счетчик циклов сохранения выбранного направления.
// Процедура изменения направления перемещения по оси X.
// На ближайшую перспективу объект может переместиться
// вперед: pt[i].direction.X == 1,
// назад: pt[i].direction.X == –1,
// остаться на месте: pt[i].direction.X == 0.
// Главное — это не выйти за пределы клиентской области окна приложения.
pt[i].direction.X = xPoint.rnd.Next(-1, 2);
xy = (float)((pt[i].p.X + pt[i].direction.X) * cf.rPointGet);
if (xy >= 0 xy <= cf.ClientSize.Width)
{
// Направление выбрано, перемещение произведено.
pt[i].p.X += pt[i].direction.X;
}
else
{
// Выбранное направление движения приводит к выходу объекта
// за пределы клиентской области окна приложения.
// На ближайшие cf.NX тактов объект остается неподвижен по оси X.
pt[i].direction.X = 0;
}
}
else
{
// Осуществили очередное перемещение по оси X.
pt[i].p.X += pt[i].direction.X;
pt[i].n.X++;
}
xy = (float)((pt[i].p.Y + pt[i].direction.Y) * cf.rPointGet);
// Вполне возможно, что это вполне подходящая позиция.
// И надо всего лишь проверить две вещи:
// 1. не выскочит ли объект за пределы клиентской области
// окна приложения,
// 2. не настало ли время поменять направление движения.
if (
xy < 0 || xy > cf.ClientSize.Height // 1.
||
pt[i].n.Y > cf.NY // 2.
)
{
pt[i].n.Y = 0; // Обнулили счетчик циклов сохранения выбранного направления.
// Процедура изменения направления перемещения по оси Y.
// На ближайшую перспективу объект может переместиться
// вверх: pt[i].direction.Y == 1,
// вниз: pt[i].direction.Y == -1,
// остаться на месте: pt[i].direction.Y == 0.
// Главное — это не выйти за пределы клиентской области окна приложения.
pt[i].direction.Y = xPoint.rnd.Next(-1, 2);
xy = (float)((pt[i].p.Y + pt[i].direction.Y) * cf.rPointGet);
if (xy >= 0 xy <= cf.ClientSize.Height)
{
// Направление выбрано, перемещение произведено.
pt[i].p.Y += pt[i].direction.Y;
}
else
{
// Выбранное направление движения приводит к выходу объекта
// за пределы клиентской области окна приложения.
// На ближайшие cf.NY тактов объект остается неподвижен по оси Y.
pt[i].direction.Y = 0;
}
}
else
{
// Осуществили очередное перемещение по оси Y.
pt[i].p.Y += pt[i].direction.Y;
pt[i].n.Y++;
}
}
}
}
}
Partial-класс. Содержит объявление класса формы приложения. Первая часть объявления в основном создается автоматически. Следует обратить внимание на настройку событий:
namespace cForm
{
partial class cForm
{
// Required designer variable.
private System.ComponentModel.IContainer components = null;
// Clean up any resources being used.
// <param name="disposing">true if managed resources should be disposed;
// otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#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()
{
this.components = new System.ComponentModel.Container();
this.mainPictureBox = new System.Windows.Forms.PictureBox();
this.mainTimer = new System.Windows.Forms.Timer(this.components);
((System.ComponentModel.ISupportInitialize)(this.mainPictureBox)).
BeginInit();
this.SuspendLayout();
//
// mainPictureBox
//
this.mainPictureBox.BackColor = System.Drawing.Color.White;
this.mainPictureBox.BorderStyle =
System.Windows.Forms.BorderStyle.FixedSingle;
this.mainPictureBox.Dock = System.Windows.Forms.DockStyle.Fill;
this.mainPictureBox.Location = new System.Drawing.Point(0, 0);
this.mainPictureBox.Name = "mainPictureBox";
this.mainPictureBox.Size = new System.Drawing.Size(569, 538);
this.mainPictureBox.TabIndex = 0;
this.mainPictureBox.TabStop = false;
//
// mainTimer
//
this.mainTimer.Interval = 250;
this.mainTimer.Tick += new System.EventHandler(this.mainTimer_Tick);
//
// cForm
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(569, 538);
this.Controls.Add(this.mainPictureBox);
this.Name = "cForm";
this.Text = "cForm";
this.Paint +=
new System.Windows.Forms.PaintEventHandler(this.bForm00_Paint);
this.Layout +=
new System.Windows.Forms.LayoutEventHandler(this.bForm00_Layout);
((System.ComponentModel.ISupportInitialize)(this.mainPictureBox)).EndInit();
this.ResumeLayout(false);
}
#endregion
private System.Windows.Forms.PictureBox mainPictureBox;
// Определение неизменяемых характеристик рамки окна приложения.
private void GetBordersGabarits()
{
this.borderHeight = this.Height - this.ClientSize.Height;
this.borderWidth = this.Width - this.ClientSize.Width;
}
// Определение предельных габаритов окна приложения.
private void SetMinMaxSize()
{
this.MinimumSize =
new System.Drawing.Size(minWidth + borderWidth, minHeight + borderHeight);
this.MaximumSize =
new System.Drawing.Size(maxWidth + borderWidth, maxHeight + borderHeight);
}
}
}
Вторая часть объявления. Здесь сосредоточены методы управления поведением популяции амеб, методы масштабирования внешнего вида приложения и отображения информации.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
namespace cForm
{
public partial class cForm : Form
{
// Средства для отображения объектов на плоскости.
Color backColor;
Pen greedPen;
Pen pen0;
SolidBrush br;
// Действующие лица. Массив объектов xPoint.
xPoint[] pt;
// Количество точек.
const int nPT = 10000;
// Синхронизаторы изменения направления перемещения объектов.
public int NX, NY;
// Предельные характеристики размеров клиентской области.
const int minHeight = 100;
const int minWidth = 100;
const int maxHeight = 950;
const int maxWidth = 950;
// Средство масштабирования. Всеобщая единица измерения.
private double rPoint;
// Абсолютные неизменяемые характеристики рамки окна приложения.
int borderHeight;
int borderWidth;
// Область рисования. Изображение формируется в памяти.
// На "поверхности" битовой карты
// (объект - представитель класса Graphics,
// создается в результате выполнения метода FromImage),
// средствами векторной графики (методы класса Graphics)
// рисуется картинка.
// Изображение проецируется на поверхность элемента управления
// mainPictureBox
// путем модификации свойства Image этого элемента управления.
private Bitmap bmp;
// Таймер. Фактически представляет собой делегат,
// который через фиксированные интервалы
// времени активизирует соответствующее событие
// (передает управление методу mainTimer_Tick).
private System.Windows.Forms.Timer mainTimer;
// Конструктор формы.
public cForm()
{
int i;
// Цвет фона картинки. Используется при перерисовке изображения.
backColor = Color.FromArgb(255,0,0,0);
// Средства для рисования.
greedPen = new Pen(Color.FromArgb(50, 0, 0, 255), 1);
pen0 = new Pen(Color.FromArgb(255,0,0,0),1);
br = new SolidBrush(Color.FromArgb(0, 0, 0, 0));
// Обязательно смотреть код начальной инициализации элементов формы!
InitializeComponent();
// Определение неизменяемых характеристик окна приложения (формы).
GetBordersGabarits();
// Начальная коррекция размеров клиентской области окна приложения.
// "Прямой" вызов метода - обработчика события изменения размеров
// окна приложения.
bForm00_Layout(null, null);
// Определение предельных габаритов окна приложения.
SetMinMaxSize();
// Значения синхронизаторов.
// Неплохо приспособить специальные элементы управления,
// которые позволяли бы изменять эти значения в интерактивном режиме!
NX = 50;
NY = 50;
// Инициализация популяции.
// Все располагаются в одном месте – в центре клиентской области окна.
// Одинаковые значения двух последних параметров приводят к тому, что
// члены популяции синхронно изменяют направление движения.
pt = new xPoint[nPT];
for (i = 0; i < pt.Length; i++)
{
pt[i] = new xPoint(
(int)(this.ClientSize.Width / (2*rPoint)),
(int)(this.ClientSize.Height / (2*rPoint)),
0, //NX, // xPoint.rnd.Next(0, NX+1), // А такие значения нарушают
0 //NY // xPoint.rnd.Next(0, NY+1) // синхронность поведения объектов.
);
}
// Процесс пошел!
mainTimer.Start();
}
// Определение относительной величины rPoint реализовано как свойство.
// Замечательная особенность свойства!
// Оно имеет явную спецификацию возвращаемого значения.
// И точно такого же типа должен быть единственный параметр value!
private Size rPointSet
{
set
{
Size s = value;
rPoint = Math.Sqrt(2.0*s.Width*s.Height) * 0.002;
}
}
// А вот перегрузить свойство нельзя! Невидимый параметр value
// и возвращаемое значение свойства должны быть одного типа.
// Именно поэтому МНЕ пришлось вводить пару свойств.
public double rPointGet
{
get
{
return rPoint;
}
}
// Обработчик события перерисовки формы.
// В списке параметров ссылка на объект - инициализатор события,
// а также ссылка на объект – носитель информации об инкапсуляторе
// данной поверхности рисования.
// Способ получения этой информации простой – через свойство Graphics:
// Graphics gr = e.Graphics;
// И знай рисуй себе!
// Однако эта ссылка нам не понадобится, поскольку мы рисуем
// не на ПОВЕРХНОСТИ ЭЛЕМЕНТА УПРАВЛЕНИЯ,
// а в памяти, на ПОВЕРХНОСТИ БИТОВОЙ КАРТЫ.
private void bForm00_Paint(object sender, PaintEventArgs e)
{
xRedraw();
}
// Событие Layout возникает при удалении или добавлении дочерних
// элементов управления,
// изменении границ элемента управления и других изменениях,
// в том числе и изменении размеров формы, которые могут повлиять
// на макет элемента.
// Рекомендуется использовать именно это событие,
// а не события ..._Resize или ..._SizeChanged. Как сказано
// в руководстве, событие Layout возникает в ответ на события
// ..._Resize и ..._SizeChanged,
// а также в других ситуациях, когда может понадобиться применение макета.
private void bForm00_Layout(object sender, LayoutEventArgs e)
{
// Использование сразу ДВУХ величин – длины и ширины клиентской
// области окна!
// Вот оптимальное решение проблемы поддержки ПОСТОЯННОГО соотношения
// характеристик клиентской области
// (среднее арифметическое для поддержки равенства сторон).
// ПЛЮС поправка на размеры рамки окна приложения.
Size = new System.Drawing.Size
(
(ClientSize.Width + ClientSize.Height)/2 + borderWidth,
(ClientSize.Width + ClientSize.Height)/2 + borderHeight
);
// После коррекции размеров окна – устанавливаем значение величины
// rPoint, которое производится через обращение к свойству rPointSet.
rPointSet = this.ClientSize;
// Новая битовая карта под новый размер клиентской области.
bmp = new Bitmap(this.ClientSize.Width, this.ClientSize.Height);
// Объявляется недопустимой конкретная область элемента управления
// (здесь форма) и происходит отправка соответствующего сообщения
// (Paint) элементу управления (форме). При этом значение
// параметра (true)
// объявляет недопустимыми назначенные элементу управления
// дочерние элементы.
// Для каждого элемента автоматически формируется
// объект-представитель
// класса Graphics, инкапсулирующий поверхность для рисования.
// Для активизации процесса перерисовки соответствующего
// элемента управления требуется объявить метод – обработчик события
// (в нашем случае это bForm00_Paint).
this.Invalidate(false);
}
// Обработчик события таймера:
// всем амебам надлежит переопределить собственные координаты и
// перерисовать картинку! Здесь также можно было бы объявить
// недействительной и требующей перерисовки поверхность формы.
// Это просто: this.Invalidate(false);
// Однако никто не помешает нам сделать все напрямую, через метод xRedraw.
private void mainTimer_Tick(object sender, EventArgs e)
{
xPoint.setNextPosition(this, pt);
xRedraw();
}
// Перерисовка.
private void xRedraw()
{
// Поверхность для рисования на битовой карте!
Graphics gr = Graphics.FromImage(bmp);
// Очистить поверхность и закрасить ее в ненавязчивый черный цвет!
gr.Clear(backColor);
// Нарисовать решетку!
DrawGreed(gr);
// Нарисовать объекты!
foreach (xPoint xp in pt)
{
// Сообщили кисти цвет объекта...
br.Color = xp.xColor;
// Закрасили объект.
gr.FillEllipse(br,
(float)((xp.p.X * rPoint) - rPoint),
(float)((xp.p.Y * rPoint) - rPoint),
(float)(2 * rPoint),
(float)(2 * rPoint));
// Сообщили перу цвет объекта...
pen0.Color = xp.xColor;
// Нарисовали контур амебы...
gr.DrawEllipse(pen0,
(float)((xp.p.X * rPoint) - rPoint),
(float)((xp.p.Y * rPoint) - rPoint),
(float)(2 * rPoint),
(float)(2 * rPoint));
}
// Рисование закончено. Подготовить объект-поверхность к удалению.
gr.Dispose();
// Отобразить картинку!
// Это всего лишь модификация свойства Image элемента управления PictureBox.
this.mainPictureBox.Image = bmp;
}
// На поверхности битовой карты (параметр gr) рисуется координатная сетка.
private void DrawGreed(Graphics gr)
{
float i;
float w = (float)(this.ClientSize.Width/25.0F);
float h = (float)(this.ClientSize.Height/25.0F);
float W = this.ClientSize.Width;
float H = this.ClientSize.Height;
for (i = h; i < H; i += h)
{
gr.DrawLine(this.greedPen, 0, i, W, i);
}
for (i = w; i < W; i += w)
{
gr.DrawLine(this.greedPen, i, 0, i, H);
}
}
}
}
Запустили приложение, порадовались отсутствию утомляющего глаза мигания, характерного для непосредственного рисования на поверхности элемента управления... подумали над созданием элементов управления для изменения синхронности перемещения членов амебной популяции.
GraphicsPath – класс, представляющий последовательность соединенных линий и кривых. Приложения используют контуры для отображения очертаний фигур, заполнения внутренних областей фигур, создания областей отсечения.
Контур может состоять из любого числа фигур (контуров). Каждая фигура либо составлена из последовательности линий и кривых, либо является геометрическим примитивом. Начальная точка фигуры – первая точка в последовательности соединенных линий и кривых. Конечная точка – последняя точка в последовательности.
Фигура, состоящая из последовательности соединенных линий и кривых (чьи начальная и конечная точки могут совпадать), является разомкнутой фигурой, если она не замкнута явно. Фигура может быть замкнута явно с помощью метода CloseFigure, который замыкает фигуру путем соединения конечной и начальной точек линией. Фигура, состоящая из геометрического примитива, является замкнутой.
Для целей заполнения и отсечения (например, если контур визуализируется с помощью метода Graphics.FillPath ) все разомкнутые фигуры замыкаются путем добавления линии от первой точки фигуры к последней.
Новая фигура начинается неявно, когда создается контур или фигура замыкается. Новая фигура создается явно, когда вызывается метод StartFigure.
Когда к контуру добавляется геометрический примитив, то он добавляет фигуру, содержащую геометрический примитив, а также неявно начинает новую фигуру. Следовательно, в контуре всегда существует текущая фигура. Когда линии и кривые добавляются к контуру, то добавляется неявная линия, соединяющая конечную точку текущей фигуры с начальной точкой новых линий и кривых, чтобы сформировать последовательность соединенных линий и кривых.
У фигуры есть направление, определяющее, как отрезки прямых и кривых следуют от начальной точки к конечной. Направление задается либо порядком добавления линий и кривых к фигуре, либо геометрическим примитивом. Направление используется для определения внутренних областей контура для целей отсечения и заполнения. О структуре и назначении классов можно судить по списку членов класса, который представлен ниже.
GraphicsPath -конструктор |
Инициализирует новый экземпляр класса GraphicsPath с перечислением FillMode из Alternate |
FillMode |
Получает или задает перечисление FillMode, определяющее, как заполняются внутренние области фигур в объекте GraphicsPath |
PathPoints |
Получает точки в контуре |
PathTypes |
Получает типы соответствующих точек в массиве PathPoints |
PointCount |
Получает PathPoints или PathTypes |
AddArc |
Присоединяет дугу эллипса к текущей фигуре |
AddBezier |
Добавляет в текущую фигуру кривую Безье третьего порядка |
AddBeziers |
Добавляет в текущую фигуру последовательность соединенных кривых Безье третьего порядка |
AddClosedCurve |
Добавляет замкнутую кривую к данному контуру. Используется кривая фундаментального сплайна, поскольку кривая проходит через все точки массива |
AddCurve |
Добавляет в текущую фигуру кривую сплайна. Используется кривая фундаментального сплайна, поскольку кривая проходит через все точки массива |
AddEllipse |
Добавляет эллипс к текущему пути |
AddLine |
Добавляет отрезок прямой к объекту GraphicsPath |
AddLines |
Добавляет последовательность соединенных отрезков прямых в конец объекта GraphicsPath |
AddPath |
Добавляет указанный объект GraphicsPath к данному контуру |
AddPie |
Добавляет контур сектора к данному контуру |
AddPolygon |
Добавляет многоугольник к данному контуру |
AddRectangle |
Добавляет прямоугольник к данному контуру |
AddRectangles |
Добавляет последовательность прямоугольников к данному контуру |
AddString |
Добавляет строку текста в данный путь |
ClearMarkers |
Удаляет все маркеры из данного контура |
Clone |
Создает точную копию данного контура |
CloseAllFigures |
Замыкает все незамкнутые фигуры в данном контуре и открывает новую фигуру. Каждая незамкнутая фигура замыкается путем соединения ее начальной и конечной точек линией |
CloseFigure |
Замыкает текущую фигуру и открывает новую. Если текущая фигура содержит последовательность соединенных линий и кривых, то метод замыкает ее путем соединения начальной и конечной точек линией |
CreateObjRef (унаследовано от ) |
Создает объект, который содержит всю необходимую информацию для конструирования прокси-сервера, используемого для коммуникации с удаленными объектами |
Dispose |
Освобождает все ресурсы, используемые объектом GraphicsPath |
Equals (унаследовано от Object ) |
Определяет, равны ли два экземпляра Object |
Flatten |
Преобразует каждую кривую в данном контуре в последовательность соединенных отрезков прямых |
GetBounds |
Возвращает прямоугольник, ограничивающий объект GraphicsPath |
GetHashCode (унаследовано от Object) |
Служит хэш-функцией для конкретного типа, пригоден для использования в алгоритмах хэширования и структурах данных, например, в хэш-таблице |
GetLastPoint |
Получает последнюю точку массива PathPoints объекта GraphicsPath |
GetLifetimeService (унаследовано от MarshalByRefObject ) |
Извлекает служебный объект текущего срока действия, который управляет средствами срока действия данного экземпляра |
GetType (унаследовано от Object ) |
Возвращает Type текущего экземпляра |
InitializeLifetimeService (унаследовано от MarshalByRefObject ) |
Получает служебный объект срока действия, для управления средствами срока действия данного экземпляра |
IsOutlineVisible |
Указывает, содержится ли определенная точка внутри (под) контура объекта GraphicsPath при отображении его с помощью указанного объекта Pen |
IsVisible |
Определяет, содержится ли указанная точка в объекте GraphicsPath |
Reset |
Очищает массивы PathPoints и PathTypes и устанавливает FillMode в Alternate |
Reverse |
Изменяет порядок точек в массиве PathPoints объекта GraphicsPath на противоположный |
SetMarkers |
Устанавливает маркер на объекте GraphicsPath |
StartFigure |
Открывает новую фигуру, не замыкая при этом текущую. Все последующие точки, добавляемые к контуру, добавляются к новой фигуре |
ToString (унаследовано от Object ) |
Возвращает String, который представляет текущий Object |
Transform |
Применяет матрицу преобразования к объекту GraphicsPath |
|
Применяет преобразование перекоса, определяемое прямоугольником и параллелограммом, к объекту GraphicsPath |
Widen |
Заменяет данный контур кривыми, которые окружают область, заполняемую при отображении контура указанным пером |
Finalize |
Переопределен. См. Object.Finalize.В языках C# и C++ для функций финализации используется синтаксис деструктора |
MemberwiseClone (унаследовано от Object ) |
Создает неполную копию текущего Object |
Класс Region (Область) предназначается для создания объектов, которые описывают внутреннюю часть графической формы из прямоугольников и фигур, составленных из замкнутых линий. Этот класс не наследуется.
Область является масштабируемой. Приложение может использовать области для фиксации выходных данных операций рисования. Brush.
Множество пикселей, входящих в состав региона, может состоять из нескольких несмежных участков.
Список членов класса представляется ниже.
Region -конструктор |
Инициализирует новый объект Region |
Clone |
Создает точную копию объекта Region |
|
Обновляет объект Region, чтобы включить часть указанной структуры RectangleF, не пересекающуюся с объектом Region |
CreateObjRef (унаследовано от MarshalByRefObject ) |
Создает объект, который содержит всю необходимую информацию для создания прокси-сервера, используемого для коммуникации с удаленными объектами |
DisposeEquals |
Освобождает все ресурсы, используемые объектом Region |
Exclude |
Обновляет объект Region, чтобы включить часть его внутренней части, не пересекающуюся с указанной структурой Rectangle |
FromHrgn |
Инициализирует новый объект Region из дескриптора указанной существующей области GDI |
GetBounds |
Возвращает структуру RectangleF, которая представляет прямоугольник, ограничивающий объект Region на поверхности рисунка объекта Graphics |
GetHashCode (унаследовано от Object ) |
Служит хэш-функцией для конкретного типа, пригоден для использования в алгоритмах хэширования и структурах данных, например в хэш-таблице |
GetHrgn |
Возвращает дескриптор Windows для объекта Region в указанном графическом контексте |
GetLifetimeService (унаследовано от MarshalByRefObject ) |
Извлекает служебный объект текущего срока действия, который управляет средствами срока действия данного экземпляра |
GetRegionData |
Возвращает объект RegionData, который представляет данные, описывающие объект Region |
GetRegionScans |
Возвращает массив структур RectangleF, аппроксимирующих объект Region |
GetType (унаследовано от Object ) |
Возвращает Type текущего экземпляра |
InitializeLifetimeService (унаследовано от MarshalByRefObject ) |
Получает служебный объект срока действия для управления средствами срока действия данного экземпляра |
Intersect |
Заменяет объект Region на его пересечение с указанным объектом Region |
IsEmpty |
Проверяет, имеет ли объект Region пустую внутреннюю часть на указанной поверхности рисунка |
IsInfinite |
Проверяет, имеет ли объект Region пустую внутреннюю часть на указанной поверхности рисунка |
IsVisible |
Проверяет, содержится ли указанный прямоугольник в объекте Region |
MakeEmpty |
Инициализирует объект Region для пустой внутренней части |
MakeInfinite |
Инициализирует объект Region для бесконечной внутренней части |
ToString (унаследовано от Object ) |
Возвращает String, который представляет текущий Object |
Transform |
Преобразует этот объект Region с помощью указанного объекта Matrix |
Translate |
Смещает координаты объекта Region на указанную величину |
Union |
Заменяет объект Region на его объединение с указанным объектом GraphicsPath |
Xor |
Заменяет объект Region на разность объединения и его пересечения с указанным объектом GraphicsPath |
Finalize |
Переопределен. См. Object.Finalize.В языках C# и C++ для функций финализации используется синтаксис деструктора |
MemberwiseClone (унаследовано от Object ) |
Создает неполную копию текущего Object |
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();
}
}
}
В этом разделе обсуждаются некоторые аспекты проблемы построения собственных элементов управления.
Известно по крайней мере три возможных подхода к разработке новых элементов управления:
Разработка составных элементов управления предполагает объявление класса, производного от класса UserControl и использование Мастера UserControl, для добавления вложенных элементов управления с последующей настройкой образующих элементов.
Новый элемент управления может быть построен на основе класса – наследника какого-либо из существующих элементов управления. В этом случае в новом классе удается частично использовать функциональности ранее объявленного класса, возможно, сохраняя при этом внешний вид элемента. Например, можно объявить собственный вариант класса кнопки, который будет наследовать классу Button.
Написание нового элемента "с нуля" отличается от предыдущего варианта разработки выбором базового класса. В этом случае основываются на классе Control, который не предоставляет потомкам даже элементарного графического интерфейса. Процесс визуализации в этом случае обеспечивается переопределяемым обработчиком события Paint. При этом переопределяется виртуальный метод базового класса OnPaint с единственным аргументом типа PaintEventArgs, который содержит информацию о клиентской области элемента управления. Член этого класса объект типа Graphics – обеспечивает формирование представления элемента управления. Второй член класса – объект типа ClipRectangle – описывает доступную клентскую область элемента управления.
Следует отметить, что между двумя последними способами определения элементов управления не существует четких границ. В обоих случаях основанием для классификации оказывается объем работы по доопределению и переопределению методов и свойств вновь создаваемого класса элементов управления.
В рассматриваемом ниже примере определения собственного элемента управления используется объект – представитель класса ImageList. Объекты этого класса предназначаются для сохранения рисунков, которые могут отображаться другими элементами управления. В общем случае этот компонент позволяет написать код для унифицированного каталога рисунков. В нашем варианте он используется для изменения внешнего вида элемента управления. К каждому рисунку можно получить доступ с помощью значения индекса этого рисунка. Отображаемые рисунки имеют один и тот же формат и размер, устанавливаемый в свойстве ImageSize. Таким образом, на основе данного свойства может быть реализован эффект масштабирования элемента управления в смысле изменения его видимых размеров в случае изменения клиентских размеров формы:
using System;
using System.Collections;
using System.ComponentModel;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Data;
using System.Windows.Forms;
namespace StrangeControls
{
// Summary description for RoundButton.
// Хотя класс RoundButton и объявляется на основе базового
// класса Button, внешнее представление его
// объектов-представителей реализуется в переопределяемом
// методе OnPaint с использованием класса ImageList.
public class RoundButton : Button
{
ImageList imgList;
// Внешнее представление элемента управления меняется
// в зависимости от состояния элемента. Это состояние
// зависит от конкретных событий, происходящих с элементом
// управления.
// Индекс, который используется при изменении внешнего
// представления элемента управления.
// Внешний вид элемента управления определяется значением
// переменной indexB, которая меняет значение в рамках
// переопределяемых обработчиков событий.
// Функциональность данного элемента управления задана
// в классе формы, в виде стандартных (непереопределяемых) обработчиков.
int indexB;
public RoundButton():base()
{
indexB = 0;
imgList = new ImageList();
imgList.Images.Add(Image.FromFile(@"jpg0.jpg"));
imgList.Images.Add(Image.FromFile(@"jpg1.jpg"));
imgList.Images.Add(Image.FromFile(@"jpg2.jpg"));
imgList.Images.Add(Image.FromFile(@"jpg3.jpg"));
this.ImageList=imgList;
}
// Код, управляющий изменением внешнего вида элемента.
// Сюда передается управление в результате выполнения метода
// Refresh().
protected override void OnPaint(PaintEventArgs e)
{
GraphicsPath gp = new GraphicsPath();
gp.AddEllipse(10,10,50,50);
Region reg = new Region(gp);
// Свойству Region присваивается новое значение – новый регион!
this.Region = reg;
e.Graphics.DrawImage(ImageList.Images[indexB],10,10,50,50);
}
protected override void OnClick(EventArgs e)
{
indexB = 0;
this.Refresh();
base.OnClick (e);
}
protected override void OnMouseDown(MouseEventArgs e)
{
indexB = 1;
this.Refresh();
base.OnMouseDown (e);
}
protected override void OnGotFocus(EventArgs e)
{
indexB = 0;
this.Refresh();
base.OnGotFocus (e);
}
protected override void OnLostFocus(EventArgs e)
{
indexB = 0;
this.Refresh();
base.OnLostFocus(e);
}
protected override void OnMouseEnter(EventArgs e)
{
indexB = 2;
this.Refresh();
base.OnMouseEnter (e);
}
protected override void OnMouseLeave(EventArgs e)
{
indexB = 3;
this.Refresh();
base.OnMouseLeave (e);
}
private void InitializeComponent()
{
//
// RoundButton
//
}
}
}
Ниже приводится фрагмент кода формы (включая назначение и определение метода – обработчика события), использующей данный элемент управления:
private void InitializeComponent()
{
::::::::::::::::::::
//
// roundButton1
//
this.roundButton1.Cursor = System.Windows.Forms.Cursors.Cross;
this.roundButton1.Location = new System.Drawing.Point(136, 8);
this.roundButton1.Name = "roundButton1";
this.roundButton1.Size = new System.Drawing.Size(72, 72);
this.roundButton1.TabIndex = 2;
this.roundButton1.Text = "roundButton1";
this.roundButton1.Click += new System.EventHandler(this.roundButton_Click);
::::::::::::::::::::
}
Сам обработчик события в форме объявлен следующим образом:
private void roundButton_Click(object sender, System.EventArgs e)
{
if (imgListindex < imgList.Images.Count–1) imgListindex++;
else imgListindex = 0;
pictureBox1.Image = imgList.Images[imgListindex];
}
Следующий фрагмент кода посвящен разработке составного элемента управления, который представляет собой "батарею" из 16 одинаковых кнопочек, располагаемых на одной панели. Несмотря на внушительное количество составляющих элементов, перед нами один элемент управления с общим единым обработчиком события, связанным с нажатием на одну из 16 кнопочек. Естественно, что реализация единого обработчика требует дополнительных усилий: каждой кнопке назначается один и тот же стандартный обработчик с двумя параметрами. Один из параметров используется для идентификации нажатой кнопки. При нажатии на кнопку происходит изменение состояния этой кнопки, которое кодируется посредством текстового значения (свойства Text ), отображаемого на поверхности кнопки.
using System;
using System.Collections;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Windows.Forms;
namespace By2
{
// Summary description for ButtonsControl.
public class ButtonsControl : System.Windows.Forms.UserControl
{
// Required designer variable.
private Form1 f1;
private ArrayList bArrList;
private System.Windows.Forms.Panel panel1;
private System.Windows.Forms.Button button16;
private System.Windows.Forms.Button button15;
private System.Windows.Forms.Button button14;
private System.Windows.Forms.Button button13;
private System.Windows.Forms.Button button12;
private System.Windows.Forms.Button button11;
private System.Windows.Forms.Button button10;
private System.Windows.Forms.Button button9;
private System.Windows.Forms.Button button8;
private System.Windows.Forms.Button button7;
private System.Windows.Forms.Button button6;
private System.Windows.Forms.Button button5;
private System.Windows.Forms.Button button4;
private System.Windows.Forms.Button button3;
private System.Windows.Forms.Button button2;
private System.Windows.Forms.Button button1;
public ArrayList parameterList;
public void SetParent(Form1 fKey)
{
f1 = fKey;
}
private System.ComponentModel.Container components = null;
public ButtonsControl()
{
InitializeComponent();
bArrList = new ArrayList();
bArrList.Add(button16);
bArrList.Add(button15);
bArrList.Add(button14);
bArrList.Add(button13);
bArrList.Add(button12);
bArrList.Add(button11);
bArrList.Add(button10);
bArrList.Add(button9);
bArrList.Add(button8);
bArrList.Add(button7);
bArrList.Add(button6);
bArrList.Add(button5);
bArrList.Add(button4);
bArrList.Add(button3);
bArrList.Add(button2);
bArrList.Add(button1);
parameterList = new ArrayList();
}
private void SetParameterList()
{
int i, I = bArrList.Count ;
parameterList.Clear();
for (i = 0; i < I; i++)
{
parameterList.Add(int.Parse(((Button)bArrList[i]).Text));
}
f1.formDecimalValue(parameterList);
}
public void SetButtons(ArrayList lst)
{
int i, I = lst.Count, J = bArrList.Count;
for (i = 0; i < J; i++)
{
((Button)bArrList[i]).Text = "0";
}
for (i = 0; i < I; i++)
{
((Button)bArrList[i]).Text = ((int)lst[i]).ToString();
}
}
// Clean up any resources being used.
protected override void Dispose( bool disposing )
{
if( disposing )
{
if(components != null)
{
components.Dispose();
}
}
base.Dispose( disposing );
}
#region Component Designer generated code
// Required method for Designer support – do not modify
// the contents of this method with the code editor.
private void InitializeComponent()
{
this.panel1 = new System.Windows.Forms.Panel();
this.button16 = new System.Windows.Forms.Button();
this.button15 = new System.Windows.Forms.Button();
this.button14 = new System.Windows.Forms.Button();
this.button13 = new System.Windows.Forms.Button();
this.button12 = new System.Windows.Forms.Button();
this.button11 = new System.Windows.Forms.Button();
this.button10 = new System.Windows.Forms.Button();
this.button9 = new System.Windows.Forms.Button();
this.button8 = new System.Windows.Forms.Button();
this.button7 = new System.Windows.Forms.Button();
this.button6 = new System.Windows.Forms.Button();
this.button5 = new System.Windows.Forms.Button();
this.button4 = new System.Windows.Forms.Button();
this.button3 = new System.Windows.Forms.Button();
this.button2 = new System.Windows.Forms.Button();
this.button1 = new System.Windows.Forms.Button();
this.panel1.SuspendLayout();
this.SuspendLayout();
//
// panel1
//
this.panel1.BorderStyle = System.Windows.Forms.BorderStyle.Fixed3D;
this.panel1.Controls.Add(this.button16);
this.panel1.Controls.Add(this.button15);
this.panel1.Controls.Add(this.button14);
this.panel1.Controls.Add(this.button13);
this.panel1.Controls.Add(this.button12);
this.panel1.Controls.Add(this.button11);
this.panel1.Controls.Add(this.button10);
this.panel1.Controls.Add(this.button9);
this.panel1.Controls.Add(this.button8);
this.panel1.Controls.Add(this.button7);
this.panel1.Controls.Add(this.button6);
this.panel1.Controls.Add(this.button5);
this.panel1.Controls.Add(this.button4);
this.panel1.Controls.Add(this.button3);
this.panel1.Controls.Add(this.button2);
this.panel1.Controls.Add(this.button1);
this.panel1.Location = new System.Drawing.Point(8, 8);
this.panel1.Name = "panel1";
this.panel1.Size = new System.Drawing.Size(648, 48);
this.panel1.TabIndex = 0;
//
// button16
//
this.button16.Location = new System.Drawing.Point(605, 12);
this.button16.Name = "button16";
this.button16.Size = new System.Drawing.Size(32, 23);
this.button16.TabIndex = 146;
this.button16.Text = "0";
this.button16.Click += new System.EventHandler(this.buttonX_Click);
//
// button15
//
this.button15.Location = new System.Drawing.Point(565, 12);
this.button15.Name = "button15";
this.button15.Size = new System.Drawing.Size(32, 23);
this.button15.TabIndex = 145;
this.button15.Text = "0";
this.button15.Click += new System.EventHandler(this.buttonX_Click);
//
// button14
//
this.button14.Location = new System.Drawing.Point(525, 12);
this.button14.Name = "button14";
this.button14.Size = new System.Drawing.Size(32, 23);
this.button14.TabIndex = 144;
this.button14.Text = "0";
this.button14.Click += new System.EventHandler (this.buttonX_Click);
//
// button13
//
this.button13.Location = new System.Drawing.Point(485, 12);
this.button13.Name = "button13";
this.button13.Size = new System.Drawing.Size(32, 23);
this.button13.TabIndex = 143;
this.button13.Text = "0";
this.button13.Click += new System.EventHandler (this.buttonX_Click);
//
// button12
//
this.button12.Location = new System.Drawing.Point(445, 12);
this.button12.Name = "button12";
this.button12.Size = new System.Drawing.Size(32, 23);
this.button12.TabIndex = 142;
this.button12.Text = "0";
this.button12.Click += new System.EventHandler (this.buttonX_Click);
//
// button11
//
this.button11.Location = new System.Drawing.Point(405, 12);
this.button11.Name = "button11";
this.button11.Size = new System.Drawing.Size(32, 23);
this.button11.TabIndex = 141;
this.button11.Text = "0";
this.button11.Click += new System.EventHandler (this.buttonX_Click);
//
// button10
//
this.button10.Location = new System.Drawing.Point(365, 12);
this.button10.Name = "button10";
this.button10.Size = new System.Drawing.Size(32, 23);
this.button10.TabIndex = 140;
this.button10.Text = "0";
this.button10.Click += new System.EventHandler (this.buttonX_Click);
//
// button9
//
this.button9.Location = new System.Drawing.Point(325, 12);
this.button9.Name = "button9";
this.button9.Size = new System.Drawing.Size(32, 23);
this.button9.TabIndex = 139;
this.button9.Text = "0";
this.button9.Click += new System.EventHandler (this.buttonX_Click);
//
// button8
//
this.button8.Location = new System.Drawing.Point(285, 12);
this.button8.Name = "button8";
this.button8.Size = new System.Drawing.Size(32, 23);
this.button8.TabIndex = 138;
this.button8.Text = "0";
this.button8.Click += new System.EventHandler(this.buttonX_Click);
//
// button7
//
this.button7.Location = new System.Drawing.Point(245, 12);
this.button7.Name = "button7";
this.button7.Size = new System.Drawing.Size(32, 23);
this.button7.TabIndex = 137;
this.button7.Text = "0";
this.button7.Click += new System.EventHandler(this.buttonX_Click);
//
// button6
//
this.button6.Location = new System.Drawing.Point(205, 12);
this.button6.Name = "button6";
this.button6.Size = new System.Drawing.Size(32, 23);
this.button6.TabIndex = 136;
this.button6.Text = "0";
this.button6.Click += new System.EventHandler(this.buttonX_Click);
//
// button5
//
this.button5.Location = new System.Drawing.Point(165, 12);
this.button5.Name = "button5";
this.button5.Size = new System.Drawing.Size(32, 23);
this.button5.TabIndex = 135;
this.button5.Text = "0";
this.button5.Click += new System.EventHandler(this.buttonX_Click);
//
// button4
//
this.button4.Location = new System.Drawing.Point(125, 12);
this.button4.Name = "button4";
this.button4.Size = new System.Drawing.Size(32, 23);
this.button4.TabIndex = 134;
this.button4.Text = "0";
this.button4.Click += new System.EventHandler (this.buttonX_Click);
//
// button3
//
this.button3.Location = new System.Drawing.Point(85, 12);
this.button3.Name = "button3";
this.button3.Size = new System.Drawing.Size(32, 23);
this.button3.TabIndex = 133;
this.button3.Text = "0";
this.button3.Click += new System.EventHandler (this.buttonX_Click);
//
// button2
//
this.button2.Location = new System.Drawing.Point(45, 12);
this.button2.Name = "button2";
this.button2.Size = new System.Drawing.Size(32, 23);
this.button2.TabIndex = 132;
this.button2.Text = "0";
this.button2.Click += new System.EventHandler (this.buttonX_Click);
//
// button1
//
this.button1.Location = new System.Drawing.Point(5, 12);
this.button1.Name = "button1";
this.button1.Size = new System.Drawing.Size(32, 23);
this.button1.TabIndex = 131;
this.button1.Text = "0";
this.button1.Click += new System.EventHandler(this.buttonX_Click);
//
// ButtonsControl
//
this.Controls.Add(this.panel1);
this.Name = "ButtonsControl";
this.Size = new System.Drawing.Size(664, 64);
this.panel1.ResumeLayout(false);
this.ResumeLayout(false);
}
#endregion
private void buttonX_Click(object sender, System.EventArgs e)
{
if (((Button)sender).Text.Equals("0")) ((Button)sender).Text = "1";
else ((Button)sender).Text = "0";
SetParameterList();
}
}
}
GDI+ - это набор программных средств, которые используются в .NET.
GDI+ позволяют создателям приложений выводить данные на экран или на принтер без необходимости обеспечивать работу с определенными типами устройств отображения. Для отображения информации программисту достаточно вызывать нужные методы классов GDI+. При этом автоматически учитываются типы определенных устройств и выполняются вызовы соответствующих драйверов.
Класс, который ИНКАПСУЛИРУЕТ поверхность рисования GDI+. Для этого класса не определен ни один конструктор. Видимо, успех в деле ручного конструирования инкапсулятора поверхностей рисования (еще вопрос, сколько разновидностей таких поверхностей) представляется проблематичным.
Конкретный объект – представитель класса Graphics предоставляется в виде ссылки методами-обработчиками событий либо создается в ходе выполнения ряда методов применительно к конкретным объектам, обладающим "поверхностями рисования" (клиентская область формы, кнопки, панели, битовая матрица):
Bitmap bmp; Pen greedPen; ::::: greedPen = new Pen(Color.FromArgb(50, 0, 0, 255), 1); // Новая битовая карта под новый размер клиентской области формы. bmp = new Bitmap(this.ClientSize.Width, this.ClientSize.Height); Graphics gr = Graphics.FromImage(bmp); gr.DrawLine(this.greedPen, 0, 0, 100, 100); gr.Dispose();
Ниже представлен список членов класса.
Clip |
Получает или задает объект Region, ограничивающий область рисования данного объекта Graphics |
ClipBounds |
Получает структуру RectangleF, которая заключает в себе вырезанную область данного объекта Graphics |
CompositingMode |
Получает значение, задающее порядок рисования сложных изображений в данном объекте Graphics |
CompositingQuality |
Получает или задает качество отображения сложных изображений, которые выводятся в данном объекте Graphics |
DpiX |
Получает горизонтальное разрешение данного объекта Graphics |
DpiY |
Получает вертикальное разрешение данного объекта Graphics |
InterpolationMode |
Получает или задает Graphics |
IsClipEmpty |
Получает значение, которое указывает, является ли вырезанная область данного объекта Graphics пустой |
IsVisibleClipEmpty |
Получает значение, которое указывает, является ли видимая вырезанная область данного объекта Graphics пустой |
PageScale |
Получает или задает масштабирование между универсальными единицами и единицами страницы для данного объекта Graphics |
PageUnit |
Получает или задает единицу измерения для координат страницы данного объекта Graphics |
PixelOffsetMode |
Получает или задает значение, которое задает порядок смещения точек во время отображения данного объекта Graphics |
RenderingOrigin |
Получает или задает исходное заполнение данного объекта Graphics для сглаживания цветовых переходов и для штриховки |
SmoothingMode |
Получает или задает качество заполнения для данного объекта Graphics |
TextContrast |
Получает или задает значение коррекции яркости для отображения текста |
TextRenderingHint |
Получает или задает режим заполнения для текста, связанного с данным объектом Graphics |
Transform |
Получает или задает универсальное преобразование для данного объекта Graphics |
VisibleClipBounds |
Получает или задает рабочий прямоугольник видимой вырезанной области данного объекта Graphics |
AddMetafileComment |
Добавляет комментарий к текущему объекту |
BeginContainer |
Перегружен. Сохраняет графический контейнер, содержащий текущее состояние данного объекта Graphics, а затем открывает и использует новый графический контейнер |
Clear |
Очищает всю поверхность рисования и выполняет заливку поверхности указанным цветом фона |
CreateObjRef |
Создает объект, который содержит всю необходимую информацию для создания прокси-сервера, используемого для коммуникации с удаленными объектами |
Dispose |
Освобождает все ресурсы, используемые данным объектом Graphics |
DrawArc |
Перегружен. Рисует дугу, которая является частью эллипса, заданного парой координат, шириной и высотой |
DrawBezier |
Перегружен. Строит кривую Безье, определяемую четырьмя структурами Point |
DrawBeziers |
Перегружен. Формирует набор кривых Безье из массива структур Point |
DrawClosedCurve |
Перегружен. Строит замкнутую фундаментальную кривую, определяемую массивом структур Point |
DrawCurve |
Перегружен. Строит замкнутую фундаментальную кривую через точки указанного массива структур Point |
DrawEllipse |
Перегружен. Формирует эллипс, который определяется |
DrawIcon |
Перегружен. Формирует изображение, которое представлено указанным объектом Icon, расположенным по указанным координатам |
DrawIconUnstretched |
Формирует изображение, представленное указанным объектом Icon, не масштабируя его |
DrawImage |
Перегружен. Рисует заданный объект Image в заданном месте, используя исходный размер |
DrawImageUnscaled |
Перегружен. Рисует заданное изображение, используя его исходный фактический размер, в расположении, заданном парой координат |
DrawLine |
Перегружен. Проводит линию, соединяющую две точки, определенные парами координат |
DrawLines |
Перегружен. Формирует набор сегментов линии, которые соединяют массив структур Point |
DrawPath |
Рисует объект GraphicsPath |
DrawPie |
Перегружен. Рисует сектор, определенный эллипсом, который задан парой координат, шириной, высотой и двумя радиальными линиями |
DrawPolygon |
Перегружен. Рисует многоугольник, определяемый массивом структур Point |
DrawRectangle |
Перегружен. Рисует прямоугольник, который определен парой координат, шириной и высотой |
DrawRectangles |
Перегружен. Рисует набор прямоугольников, определяемых структурой Rectangle |
DrawString |
Перегружен. Создает текстовую строку в заданном месте с указанными объектами Brush и Font |
EndContainer |
Закрывает текущий графический контейнер и восстанавливает состояние данного объекта Graphics, которое было сохранено при вызове метода BeginContainer |
EnumerateMetafile |
Перегружен. Отправляет записи указанного объекта по отдельности методу обратного вызова, который отображает их в заданной точке |
Equals |
Перегружен. Определяет, равны ли два экземпляра Object |
ExcludeClip |
Перегружен. Обновляет вырезанную область данного объекта Graphics, чтобы исключить из нее часть, определенную структурой Rectangle |
FillClosedCurve |
Перегружен. Заполняет замкнутую фундаментальную кривую, определяемую массивом структур Point |
FillEllipse |
Перегружен. Заполняет внутреннюю часть эллипса, который определяется |
FillPath |
Заполняет внутреннюю часть объекта GraphicsPath |
FillPie |
Перегружен. Заполняет внутреннюю часть сектора, определенного эллипсом, который задан парой координат, шириной, высотой и двумя радиальными линиями |
FillPolygon |
Перегружен. Заполняет внутреннюю часть многоугольника, определенного массивом точек, заданных структурами Point |
FillRectangle |
Перегружен. Заполняет внутреннюю часть прямоугольника, который определен парой координат, шириной и высотой |
FillRectangles |
Перегружен. Заполняет внутреннюю часть набора прямоугольников, определяемого структурами Rectangle |
FillRegion |
Заполняет внутреннюю часть объекта Region |
Flush |
Перегружен. Вызывает принудительное выполнение всех отложенных графических операций и немедленно возвращается, не дожидаясь их окончания |
FromHdc |
Статический. Перегружен. Создает новый объект Graphics из указанного дескриптора для контекста устройства |
FromHdcInternal |
Статический. Внутренний метод. Не используется |
FromHwnd |
Статический. Создает новый объект Graphics из указанного дескриптора для окна |
FromHwndInternal |
Статический. Внутренний метод. Не используется |
FromImage |
Статический. Создает новый объект Graphics из заданного объекта Image |
GetHalftonePalette |
Статический. Получает дескриптор текущей полутоновой палитры Windows |
GetHashCode |
Служит хэш-функцией для конкретного типа, пригоден для использования в алгоритмах хэширования и структурах данных, например в хэш-таблице |
GetHdc |
Получает дескриптор контекста устройства, связанный с данным объектом Graphics |
GetLifetimeService |
Извлекает служебный объект текущего срока действия, который управляет средствами срока действия данного экземпляра |
GetNearestColor |
Получает цвет, ближайший к указанной структуре Color |
GetType |
Возвращает Type текущего экземпляра |
InitializeLifetimeService |
Получает служебный объект срока действия, для управления средствами срока действия данного экземпляра |
IntersectClip |
Перегружен. Обновляет вырезанную область данного объекта Graphics, включая в нее пересечение текущей вырезанной области и указанной структуры Rectangle |
IsVisible |
Перегружен. Указывает, содержится ли точка, заданная с помощью пары координат, в видимой вырезанной области данного объекта Graphics |
MeasureCharacterRanges |
Получает массив объектов Region, каждый из которых связывает диапазон позиций символов в рамках указанной строки |
MeasureString |
Перегружен. Измеряет указанную строку в процессе ее создания с помощью заданного объекта Font |
MultiplyTransform |
Перегружен. Умножает универсальное преобразование данного объекта Graphics на преобразование указанного объекта Matrix |
ReleaseHdc |
Освобождает дескриптор контекста устройства, полученный в результате предыдущего вызова метода GetHdc данного объекта Graphics |
ReleaseHdcInternal |
Внутренний метод. Не используется |
ResetClip |
Сбрасывает вырезанную область данного объекта Graphics и делает ее бесконечной |
ResetTransform |
Сбрасывает матрицу универсального преобразования данного объекта Graphics и делает ее единичной матрицей |
Restore |
Восстанавливает состояние данного объекта Graphics, возвращая его к состоянию объекта GraphicsState |
RotateTransform |
Перегружен. Применяет заданное вращение к матрице преобразования данного объекта Graphics |
Save |
Сохраняет текущее состояние данного объекта Graphics и связывает сохраненное состояние с объектом GraphicsState |
ScaleTransform |
Перегружен. Применяет указанную операцию масштабирования к матрице преобразования данного объекта Graphics путем ее добавления к матрице преобразования объекта |
SetClip |
Перегружен. Задает в качестве вырезанной области данного объекта Graphics свойство Clip указанного объекта Graphics |
ToString |
Возвращает String, который представляет текущий Object |
TransformPoints |
Перегружен. Преобразует массив точек из одного координатного пространства в другое, используя текущее универсальное преобразование и преобразование страницы данного объекта Graphics |
TranslateClip |
Перегружен. Переводит вырезанную область данного объекта Graphics в указанном объеме в горизонтальном и вертикальном направлениях. |
TranslateTransform |
Перегружен. Добавляет заданный перевод к матрице преобразования данного объекта Graphics |
Finalize |
Переопределен. См. Object.Finalize.В языках C# и C++ для функций финализации используется синтаксис деструктора |
MemberwiseClone |
Создает неполную копию текущего Object |
Приводимое ниже приложение демонстрирует технику рисования на невидимых виртуальных поверхностях – в буквальном смысле в оперативной памяти.
Приложение моделирует случайное блуждание множества однородных частиц. Несмотря на интенсивный вывод графической информации, удается избежать эффекта мигания, который возникает при непосредственной модификации внешнего вида элементов управления.
Демонстрация предварительно нарисованной в памяти картинки происходит при помощи элемента управления типа PictureBox, который благодаря свойству объекта Image обеспечивает быстрое отображение выводимой графической информации.
Итак, данное Windows-приложение включает объявление трех классов:
xPoint, объекты которого периодически изменяют собственное положение в пределах клиентской области окна;cForm, который обладает свойствами сохранения постоянного соотношения собственных размеров и размеров клиентской области, и обеспечивает отображение множества блуждающих объектов – представителей класса xPoint ;Program, который в соответствии с предопределенными алгоритмами обеспечивает создание и выполнение приложения.Создается автоматически. Без комментариев.
using System;
using System.Collections.Generic;
using System.Windows.Forms;
namespace cForm
{
static class Program
{
// The main entry point for the application.
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new cForm());
}
}
}
Объявление класса блуждающих объектов:
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Text;
namespace cForm
{
class xPoint
{
// Собственный статический генератор случайных чисел.
// Используется в конструкторе.
public static Random rnd = new Random();
// Цвет объекта.
public Color xColor;
// Текущая позиция. Относительные значения координат X и Y.
public Point p;
// Обеспечение перемещения. Текущие значения координат могут
// изменяться как по X, так и по Y.
public Point direction;
// Счетчик циклов сохранения выбранного направления.
// Объект на протяжении фиксированного интервала времени может
// сохранять ранее избранное направление движения.
// В течение n.X "тиков" для X в течение n.Y "тиков" для Y.
public Point n;
public xPoint(int X, int Y, int Xn, int Yn)
{
n = new Point(rnd.Next(0, Xn), rnd.Next(0, Yn));
direction = new Point(rnd.Next(-1, 2), rnd.Next(-1, 2));
p = new Point(X, Y);
xColor =
Color.FromArgb(150, rnd.Next(0, 256), rnd.Next(0, 256), rnd.Next(0, 256));
}
// Статический метод. Еще вопрос, где следовало размещать его
// объявление... Определение нового положения амебы.
// Просматривается ВЕСЬ список.
// Ее перемещение ограничивается физическими размерами клиентской области
// окна приложения и определяется по двум координатам (X и Y).
// В каждый момент она может оставаться на месте, либо изменить
// свое положение на один "шаг" по каждой из осей координат
// ("вверх" или "вниз" по оси Y и "вперед" или "назад" по оси X).
public static void setNextPosition(cForm cf, xPoint[] pt)
{
int i;
float xy;
// Итак, определение текущей позиции объекта.
// Просмотр массива...
for (i = 0; i < pt.Length; i++)
{
// Сначала разбираемся со значением координаты X.
// Вычисляем возможную позицию после перемещения объекта.
xy = (float)((pt[i].p.X + pt[i].direction.X) * cf.rPointGet);
// Вполне возможно, что это вполне подходящая позиция.
// И надо всего лишь проверить две вещи:
// 1. не выскочит ли объект за пределы клиентской области окна
// приложения,
// 2. не настало ли время поменять направление движения.
if (
xy < 0 || xy > cf.ClientSize.Width // 1.
||
pt[i].n.X > cf.NX // 2.
)
{
pt[i].n.X = 0; // Обнулили счетчик циклов сохранения выбранного направления.
// Процедура изменения направления перемещения по оси X.
// На ближайшую перспективу объект может переместиться
// вперед: pt[i].direction.X == 1,
// назад: pt[i].direction.X == –1,
// остаться на месте: pt[i].direction.X == 0.
// Главное — это не выйти за пределы клиентской области окна приложения.
pt[i].direction.X = xPoint.rnd.Next(-1, 2);
xy = (float)((pt[i].p.X + pt[i].direction.X) * cf.rPointGet);
if (xy >= 0 xy <= cf.ClientSize.Width)
{
// Направление выбрано, перемещение произведено.
pt[i].p.X += pt[i].direction.X;
}
else
{
// Выбранное направление движения приводит к выходу объекта
// за пределы клиентской области окна приложения.
// На ближайшие cf.NX тактов объект остается неподвижен по оси X.
pt[i].direction.X = 0;
}
}
else
{
// Осуществили очередное перемещение по оси X.
pt[i].p.X += pt[i].direction.X;
pt[i].n.X++;
}
xy = (float)((pt[i].p.Y + pt[i].direction.Y) * cf.rPointGet);
// Вполне возможно, что это вполне подходящая позиция.
// И надо всего лишь проверить две вещи:
// 1. не выскочит ли объект за пределы клиентской области
// окна приложения,
// 2. не настало ли время поменять направление движения.
if (
xy < 0 || xy > cf.ClientSize.Height // 1.
||
pt[i].n.Y > cf.NY // 2.
)
{
pt[i].n.Y = 0; // Обнулили счетчик циклов сохранения выбранного направления.
// Процедура изменения направления перемещения по оси Y.
// На ближайшую перспективу объект может переместиться
// вверх: pt[i].direction.Y == 1,
// вниз: pt[i].direction.Y == -1,
// остаться на месте: pt[i].direction.Y == 0.
// Главное — это не выйти за пределы клиентской области окна приложения.
pt[i].direction.Y = xPoint.rnd.Next(-1, 2);
xy = (float)((pt[i].p.Y + pt[i].direction.Y) * cf.rPointGet);
if (xy >= 0 xy <= cf.ClientSize.Height)
{
// Направление выбрано, перемещение произведено.
pt[i].p.Y += pt[i].direction.Y;
}
else
{
// Выбранное направление движения приводит к выходу объекта
// за пределы клиентской области окна приложения.
// На ближайшие cf.NY тактов объект остается неподвижен по оси Y.
pt[i].direction.Y = 0;
}
}
else
{
// Осуществили очередное перемещение по оси Y.
pt[i].p.Y += pt[i].direction.Y;
pt[i].n.Y++;
}
}
}
}
}
Partial-класс. Содержит объявление класса формы приложения. Первая часть объявления в основном создается автоматически. Следует обратить внимание на настройку событий:
namespace cForm
{
partial class cForm
{
// Required designer variable.
private System.ComponentModel.IContainer components = null;
// Clean up any resources being used.
// <param name="disposing">true if managed resources should be disposed;
// otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#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()
{
this.components = new System.ComponentModel.Container();
this.mainPictureBox = new System.Windows.Forms.PictureBox();
this.mainTimer = new System.Windows.Forms.Timer(this.components);
((System.ComponentModel.ISupportInitialize)(this.mainPictureBox)).
BeginInit();
this.SuspendLayout();
//
// mainPictureBox
//
this.mainPictureBox.BackColor = System.Drawing.Color.White;
this.mainPictureBox.BorderStyle =
System.Windows.Forms.BorderStyle.FixedSingle;
this.mainPictureBox.Dock = System.Windows.Forms.DockStyle.Fill;
this.mainPictureBox.Location = new System.Drawing.Point(0, 0);
this.mainPictureBox.Name = "mainPictureBox";
this.mainPictureBox.Size = new System.Drawing.Size(569, 538);
this.mainPictureBox.TabIndex = 0;
this.mainPictureBox.TabStop = false;
//
// mainTimer
//
this.mainTimer.Interval = 250;
this.mainTimer.Tick += new System.EventHandler(this.mainTimer_Tick);
//
// cForm
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(569, 538);
this.Controls.Add(this.mainPictureBox);
this.Name = "cForm";
this.Text = "cForm";
this.Paint +=
new System.Windows.Forms.PaintEventHandler(this.bForm00_Paint);
this.Layout +=
new System.Windows.Forms.LayoutEventHandler(this.bForm00_Layout);
((System.ComponentModel.ISupportInitialize)(this.mainPictureBox)).EndInit();
this.ResumeLayout(false);
}
#endregion
private System.Windows.Forms.PictureBox mainPictureBox;
// Определение неизменяемых характеристик рамки окна приложения.
private void GetBordersGabarits()
{
this.borderHeight = this.Height - this.ClientSize.Height;
this.borderWidth = this.Width - this.ClientSize.Width;
}
// Определение предельных габаритов окна приложения.
private void SetMinMaxSize()
{
this.MinimumSize =
new System.Drawing.Size(minWidth + borderWidth, minHeight + borderHeight);
this.MaximumSize =
new System.Drawing.Size(maxWidth + borderWidth, maxHeight + borderHeight);
}
}
}
Вторая часть объявления. Здесь сосредоточены методы управления поведением популяции амеб, методы масштабирования внешнего вида приложения и отображения информации.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
namespace cForm
{
public partial class cForm : Form
{
// Средства для отображения объектов на плоскости.
Color backColor;
Pen greedPen;
Pen pen0;
SolidBrush br;
// Действующие лица. Массив объектов xPoint.
xPoint[] pt;
// Количество точек.
const int nPT = 10000;
// Синхронизаторы изменения направления перемещения объектов.
public int NX, NY;
// Предельные характеристики размеров клиентской области.
const int minHeight = 100;
const int minWidth = 100;
const int maxHeight = 950;
const int maxWidth = 950;
// Средство масштабирования. Всеобщая единица измерения.
private double rPoint;
// Абсолютные неизменяемые характеристики рамки окна приложения.
int borderHeight;
int borderWidth;
// Область рисования. Изображение формируется в памяти.
// На "поверхности" битовой карты
// (объект - представитель класса Graphics,
// создается в результате выполнения метода FromImage),
// средствами векторной графики (методы класса Graphics)
// рисуется картинка.
// Изображение проецируется на поверхность элемента управления
// mainPictureBox
// путем модификации свойства Image этого элемента управления.
private Bitmap bmp;
// Таймер. Фактически представляет собой делегат,
// который через фиксированные интервалы
// времени активизирует соответствующее событие
// (передает управление методу mainTimer_Tick).
private System.Windows.Forms.Timer mainTimer;
// Конструктор формы.
public cForm()
{
int i;
// Цвет фона картинки. Используется при перерисовке изображения.
backColor = Color.FromArgb(255,0,0,0);
// Средства для рисования.
greedPen = new Pen(Color.FromArgb(50, 0, 0, 255), 1);
pen0 = new Pen(Color.FromArgb(255,0,0,0),1);
br = new SolidBrush(Color.FromArgb(0, 0, 0, 0));
// Обязательно смотреть код начальной инициализации элементов формы!
InitializeComponent();
// Определение неизменяемых характеристик окна приложения (формы).
GetBordersGabarits();
// Начальная коррекция размеров клиентской области окна приложения.
// "Прямой" вызов метода - обработчика события изменения размеров
// окна приложения.
bForm00_Layout(null, null);
// Определение предельных габаритов окна приложения.
SetMinMaxSize();
// Значения синхронизаторов.
// Неплохо приспособить специальные элементы управления,
// которые позволяли бы изменять эти значения в интерактивном режиме!
NX = 50;
NY = 50;
// Инициализация популяции.
// Все располагаются в одном месте – в центре клиентской области окна.
// Одинаковые значения двух последних параметров приводят к тому, что
// члены популяции синхронно изменяют направление движения.
pt = new xPoint[nPT];
for (i = 0; i < pt.Length; i++)
{
pt[i] = new xPoint(
(int)(this.ClientSize.Width / (2*rPoint)),
(int)(this.ClientSize.Height / (2*rPoint)),
0, //NX, // xPoint.rnd.Next(0, NX+1), // А такие значения нарушают
0 //NY // xPoint.rnd.Next(0, NY+1) // синхронность поведения объектов.
);
}
// Процесс пошел!
mainTimer.Start();
}
// Определение относительной величины rPoint реализовано как свойство.
// Замечательная особенность свойства!
// Оно имеет явную спецификацию возвращаемого значения.
// И точно такого же типа должен быть единственный параметр value!
private Size rPointSet
{
set
{
Size s = value;
rPoint = Math.Sqrt(2.0*s.Width*s.Height) * 0.002;
}
}
// А вот перегрузить свойство нельзя! Невидимый параметр value
// и возвращаемое значение свойства должны быть одного типа.
// Именно поэтому МНЕ пришлось вводить пару свойств.
public double rPointGet
{
get
{
return rPoint;
}
}
// Обработчик события перерисовки формы.
// В списке параметров ссылка на объект - инициализатор события,
// а также ссылка на объект – носитель информации об инкапсуляторе
// данной поверхности рисования.
// Способ получения этой информации простой – через свойство Graphics:
// Graphics gr = e.Graphics;
// И знай рисуй себе!
// Однако эта ссылка нам не понадобится, поскольку мы рисуем
// не на ПОВЕРХНОСТИ ЭЛЕМЕНТА УПРАВЛЕНИЯ,
// а в памяти, на ПОВЕРХНОСТИ БИТОВОЙ КАРТЫ.
private void bForm00_Paint(object sender, PaintEventArgs e)
{
xRedraw();
}
// Событие Layout возникает при удалении или добавлении дочерних
// элементов управления,
// изменении границ элемента управления и других изменениях,
// в том числе и изменении размеров формы, которые могут повлиять
// на макет элемента.
// Рекомендуется использовать именно это событие,
// а не события ..._Resize или ..._SizeChanged. Как сказано
// в руководстве, событие Layout возникает в ответ на события
// ..._Resize и ..._SizeChanged,
// а также в других ситуациях, когда может понадобиться применение макета.
private void bForm00_Layout(object sender, LayoutEventArgs e)
{
// Использование сразу ДВУХ величин – длины и ширины клиентской
// области окна!
// Вот оптимальное решение проблемы поддержки ПОСТОЯННОГО соотношения
// характеристик клиентской области
// (среднее арифметическое для поддержки равенства сторон).
// ПЛЮС поправка на размеры рамки окна приложения.
Size = new System.Drawing.Size
(
(ClientSize.Width + ClientSize.Height)/2 + borderWidth,
(ClientSize.Width + ClientSize.Height)/2 + borderHeight
);
// После коррекции размеров окна – устанавливаем значение величины
// rPoint, которое производится через обращение к свойству rPointSet.
rPointSet = this.ClientSize;
// Новая битовая карта под новый размер клиентской области.
bmp = new Bitmap(this.ClientSize.Width, this.ClientSize.Height);
// Объявляется недопустимой конкретная область элемента управления
// (здесь форма) и происходит отправка соответствующего сообщения
// (Paint) элементу управления (форме). При этом значение
// параметра (true)
// объявляет недопустимыми назначенные элементу управления
// дочерние элементы.
// Для каждого элемента автоматически формируется
// объект-представитель
// класса Graphics, инкапсулирующий поверхность для рисования.
// Для активизации процесса перерисовки соответствующего
// элемента управления требуется объявить метод – обработчик события
// (в нашем случае это bForm00_Paint).
this.Invalidate(false);
}
// Обработчик события таймера:
// всем амебам надлежит переопределить собственные координаты и
// перерисовать картинку! Здесь также можно было бы объявить
// недействительной и требующей перерисовки поверхность формы.
// Это просто: this.Invalidate(false);
// Однако никто не помешает нам сделать все напрямую, через метод xRedraw.
private void mainTimer_Tick(object sender, EventArgs e)
{
xPoint.setNextPosition(this, pt);
xRedraw();
}
// Перерисовка.
private void xRedraw()
{
// Поверхность для рисования на битовой карте!
Graphics gr = Graphics.FromImage(bmp);
// Очистить поверхность и закрасить ее в ненавязчивый черный цвет!
gr.Clear(backColor);
// Нарисовать решетку!
DrawGreed(gr);
// Нарисовать объекты!
foreach (xPoint xp in pt)
{
// Сообщили кисти цвет объекта...
br.Color = xp.xColor;
// Закрасили объект.
gr.FillEllipse(br,
(float)((xp.p.X * rPoint) - rPoint),
(float)((xp.p.Y * rPoint) - rPoint),
(float)(2 * rPoint),
(float)(2 * rPoint));
// Сообщили перу цвет объекта...
pen0.Color = xp.xColor;
// Нарисовали контур амебы...
gr.DrawEllipse(pen0,
(float)((xp.p.X * rPoint) - rPoint),
(float)((xp.p.Y * rPoint) - rPoint),
(float)(2 * rPoint),
(float)(2 * rPoint));
}
// Рисование закончено. Подготовить объект-поверхность к удалению.
gr.Dispose();
// Отобразить картинку!
// Это всего лишь модификация свойства Image элемента управления PictureBox.
this.mainPictureBox.Image = bmp;
}
// На поверхности битовой карты (параметр gr) рисуется координатная сетка.
private void DrawGreed(Graphics gr)
{
float i;
float w = (float)(this.ClientSize.Width/25.0F);
float h = (float)(this.ClientSize.Height/25.0F);
float W = this.ClientSize.Width;
float H = this.ClientSize.Height;
for (i = h; i < H; i += h)
{
gr.DrawLine(this.greedPen, 0, i, W, i);
}
for (i = w; i < W; i += w)
{
gr.DrawLine(this.greedPen, i, 0, i, H);
}
}
}
}
Запустили приложение, порадовались отсутствию утомляющего глаза мигания, характерного для непосредственного рисования на поверхности элемента управления... подумали над созданием элементов управления для изменения синхронности перемещения членов амебной популяции.
GraphicsPath – класс, представляющий последовательность соединенных линий и кривых. Приложения используют контуры для отображения очертаний фигур, заполнения внутренних областей фигур, создания областей отсечения.
Контур может состоять из любого числа фигур (контуров). Каждая фигура либо составлена из последовательности линий и кривых, либо является геометрическим примитивом. Начальная точка фигуры – первая точка в последовательности соединенных линий и кривых. Конечная точка – последняя точка в последовательности.
Фигура, состоящая из последовательности соединенных линий и кривых (чьи начальная и конечная точки могут совпадать), является разомкнутой фигурой, если она не замкнута явно. Фигура может быть замкнута явно с помощью метода CloseFigure, который замыкает фигуру путем соединения конечной и начальной точек линией. Фигура, состоящая из геометрического примитива, является замкнутой.
Для целей заполнения и отсечения (например, если контур визуализируется с помощью метода Graphics.FillPath ) все разомкнутые фигуры замыкаются путем добавления линии от первой точки фигуры к последней.
Новая фигура начинается неявно, когда создается контур или фигура замыкается. Новая фигура создается явно, когда вызывается метод StartFigure.
Когда к контуру добавляется геометрический примитив, то он добавляет фигуру, содержащую геометрический примитив, а также неявно начинает новую фигуру. Следовательно, в контуре всегда существует текущая фигура. Когда линии и кривые добавляются к контуру, то добавляется неявная линия, соединяющая конечную точку текущей фигуры с начальной точкой новых линий и кривых, чтобы сформировать последовательность соединенных линий и кривых.
У фигуры есть направление, определяющее, как отрезки прямых и кривых следуют от начальной точки к конечной. Направление задается либо порядком добавления линий и кривых к фигуре, либо геометрическим примитивом. Направление используется для определения внутренних областей контура для целей отсечения и заполнения. О структуре и назначении классов можно судить по списку членов класса, который представлен ниже.
GraphicsPath -конструктор |
Инициализирует новый экземпляр класса GraphicsPath с перечислением FillMode из Alternate |
FillMode |
Получает или задает перечисление FillMode, определяющее, как заполняются внутренние области фигур в объекте GraphicsPath |
PathPoints |
Получает точки в контуре |
PathTypes |
Получает типы соответствующих точек в массиве PathPoints |
PointCount |
Получает PathPoints или PathTypes |
AddArc |
Присоединяет дугу эллипса к текущей фигуре |
AddBezier |
Добавляет в текущую фигуру кривую Безье третьего порядка |
AddBeziers |
Добавляет в текущую фигуру последовательность соединенных кривых Безье третьего порядка |
AddClosedCurve |
Добавляет замкнутую кривую к данному контуру. Используется кривая фундаментального сплайна, поскольку кривая проходит через все точки массива |
AddCurve |
Добавляет в текущую фигуру кривую сплайна. Используется кривая фундаментального сплайна, поскольку кривая проходит через все точки массива |
AddEllipse |
Добавляет эллипс к текущему пути |
AddLine |
Добавляет отрезок прямой к объекту GraphicsPath |
AddLines |
Добавляет последовательность соединенных отрезков прямых в конец объекта GraphicsPath |
AddPath |
Добавляет указанный объект GraphicsPath к данному контуру |
AddPie |
Добавляет контур сектора к данному контуру |
AddPolygon |
Добавляет многоугольник к данному контуру |
AddRectangle |
Добавляет прямоугольник к данному контуру |
AddRectangles |
Добавляет последовательность прямоугольников к данному контуру |
AddString |
Добавляет строку текста в данный путь |
ClearMarkers |
Удаляет все маркеры из данного контура |
Clone |
Создает точную копию данного контура |
CloseAllFigures |
Замыкает все незамкнутые фигуры в данном контуре и открывает новую фигуру. Каждая незамкнутая фигура замыкается путем соединения ее начальной и конечной точек линией |
CloseFigure |
Замыкает текущую фигуру и открывает новую. Если текущая фигура содержит последовательность соединенных линий и кривых, то метод замыкает ее путем соединения начальной и конечной точек линией |
CreateObjRef (унаследовано от ) |
Создает объект, который содержит всю необходимую информацию для конструирования прокси-сервера, используемого для коммуникации с удаленными объектами |
Dispose |
Освобождает все ресурсы, используемые объектом GraphicsPath |
Equals (унаследовано от Object ) |
Определяет, равны ли два экземпляра Object |
Flatten |
Преобразует каждую кривую в данном контуре в последовательность соединенных отрезков прямых |
GetBounds |
Возвращает прямоугольник, ограничивающий объект GraphicsPath |
GetHashCode (унаследовано от Object) |
Служит хэш-функцией для конкретного типа, пригоден для использования в алгоритмах хэширования и структурах данных, например, в хэш-таблице |
GetLastPoint |
Получает последнюю точку массива PathPoints объекта GraphicsPath |
GetLifetimeService (унаследовано от MarshalByRefObject ) |
Извлекает служебный объект текущего срока действия, который управляет средствами срока действия данного экземпляра |
GetType (унаследовано от Object ) |
Возвращает Type текущего экземпляра |
InitializeLifetimeService (унаследовано от MarshalByRefObject ) |
Получает служебный объект срока действия, для управления средствами срока действия данного экземпляра |
IsOutlineVisible |
Указывает, содержится ли определенная точка внутри (под) контура объекта GraphicsPath при отображении его с помощью указанного объекта Pen |
IsVisible |
Определяет, содержится ли указанная точка в объекте GraphicsPath |
Reset |
Очищает массивы PathPoints и PathTypes и устанавливает FillMode в Alternate |
Reverse |
Изменяет порядок точек в массиве PathPoints объекта GraphicsPath на противоположный |
SetMarkers |
Устанавливает маркер на объекте GraphicsPath |
StartFigure |
Открывает новую фигуру, не замыкая при этом текущую. Все последующие точки, добавляемые к контуру, добавляются к новой фигуре |
ToString (унаследовано от Object ) |
Возвращает String, который представляет текущий Object |
Transform |
Применяет матрицу преобразования к объекту GraphicsPath |
|
Применяет преобразование перекоса, определяемое прямоугольником и параллелограммом, к объекту GraphicsPath |
Widen |
Заменяет данный контур кривыми, которые окружают область, заполняемую при отображении контура указанным пером |
Finalize |
Переопределен. См. Object.Finalize.В языках C# и C++ для функций финализации используется синтаксис деструктора |
MemberwiseClone (унаследовано от Object ) |
Создает неполную копию текущего Object |
Класс Region (Область) предназначается для создания объектов, которые описывают внутреннюю часть графической формы из прямоугольников и фигур, составленных из замкнутых линий. Этот класс не наследуется.
Область является масштабируемой. Приложение может использовать области для фиксации выходных данных операций рисования. Brush.
Множество пикселей, входящих в состав региона, может состоять из нескольких несмежных участков.
Список членов класса представляется ниже.
Region -конструктор |
Инициализирует новый объект Region |
Clone |
Создает точную копию объекта Region |
|
Обновляет объект Region, чтобы включить часть указанной структуры RectangleF, не пересекающуюся с объектом Region |
CreateObjRef (унаследовано от MarshalByRefObject ) |
Создает объект, который содержит всю необходимую информацию для создания прокси-сервера, используемого для коммуникации с удаленными объектами |
DisposeEquals |
Освобождает все ресурсы, используемые объектом Region |
Exclude |
Обновляет объект Region, чтобы включить часть его внутренней части, не пересекающуюся с указанной структурой Rectangle |
FromHrgn |
Инициализирует новый объект Region из дескриптора указанной существующей области GDI |
GetBounds |
Возвращает структуру RectangleF, которая представляет прямоугольник, ограничивающий объект Region на поверхности рисунка объекта Graphics |
GetHashCode (унаследовано от Object ) |
Служит хэш-функцией для конкретного типа, пригоден для использования в алгоритмах хэширования и структурах данных, например в хэш-таблице |
GetHrgn |
Возвращает дескриптор Windows для объекта Region в указанном графическом контексте |
GetLifetimeService (унаследовано от MarshalByRefObject ) |
Извлекает служебный объект текущего срока действия, который управляет средствами срока действия данного экземпляра |
GetRegionData |
Возвращает объект RegionData, который представляет данные, описывающие объект Region |
GetRegionScans |
Возвращает массив структур RectangleF, аппроксимирующих объект Region |
GetType (унаследовано от Object ) |
Возвращает Type текущего экземпляра |
InitializeLifetimeService (унаследовано от MarshalByRefObject ) |
Получает служебный объект срока действия для управления средствами срока действия данного экземпляра |
Intersect |
Заменяет объект Region на его пересечение с указанным объектом Region |
IsEmpty |
Проверяет, имеет ли объект Region пустую внутреннюю часть на указанной поверхности рисунка |
IsInfinite |
Проверяет, имеет ли объект Region пустую внутреннюю часть на указанной поверхности рисунка |
IsVisible |
Проверяет, содержится ли указанный прямоугольник в объекте Region |
MakeEmpty |
Инициализирует объект Region для пустой внутренней части |
MakeInfinite |
Инициализирует объект Region для бесконечной внутренней части |
ToString (унаследовано от Object ) |
Возвращает String, который представляет текущий Object |
Transform |
Преобразует этот объект Region с помощью указанного объекта Matrix |
Translate |
Смещает координаты объекта Region на указанную величину |
Union |
Заменяет объект Region на его объединение с указанным объектом GraphicsPath |
Xor |
Заменяет объект Region на разность объединения и его пересечения с указанным объектом GraphicsPath |
Finalize |
Переопределен. См. Object.Finalize.В языках C# и C++ для функций финализации используется синтаксис деструктора |
MemberwiseClone (унаследовано от Object ) |
Создает неполную копию текущего Object |
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();
}
}
}
В этом разделе обсуждаются некоторые аспекты проблемы построения собственных элементов управления.
Известно по крайней мере три возможных подхода к разработке новых элементов управления:
Разработка составных элементов управления предполагает объявление класса, производного от класса UserControl и использование Мастера UserControl, для добавления вложенных элементов управления с последующей настройкой образующих элементов.
Новый элемент управления может быть построен на основе класса – наследника какого-либо из существующих элементов управления. В этом случае в новом классе удается частично использовать функциональности ранее объявленного класса, возможно, сохраняя при этом внешний вид элемента. Например, можно объявить собственный вариант класса кнопки, который будет наследовать классу Button.
Написание нового элемента "с нуля" отличается от предыдущего варианта разработки выбором базового класса. В этом случае основываются на классе Control, который не предоставляет потомкам даже элементарного графического интерфейса. Процесс визуализации в этом случае обеспечивается переопределяемым обработчиком события Paint. При этом переопределяется виртуальный метод базового класса OnPaint с единственным аргументом типа PaintEventArgs, который содержит информацию о клиентской области элемента управления. Член этого класса объект типа Graphics – обеспечивает формирование представления элемента управления. Второй член класса – объект типа ClipRectangle – описывает доступную клентскую область элемента управления.
Следует отметить, что между двумя последними способами определения элементов управления не существует четких границ. В обоих случаях основанием для классификации оказывается объем работы по доопределению и переопределению методов и свойств вновь создаваемого класса элементов управления.
В рассматриваемом ниже примере определения собственного элемента управления используется объект – представитель класса ImageList. Объекты этого класса предназначаются для сохранения рисунков, которые могут отображаться другими элементами управления. В общем случае этот компонент позволяет написать код для унифицированного каталога рисунков. В нашем варианте он используется для изменения внешнего вида элемента управления. К каждому рисунку можно получить доступ с помощью значения индекса этого рисунка. Отображаемые рисунки имеют один и тот же формат и размер, устанавливаемый в свойстве ImageSize. Таким образом, на основе данного свойства может быть реализован эффект масштабирования элемента управления в смысле изменения его видимых размеров в случае изменения клиентских размеров формы:
using System;
using System.Collections;
using System.ComponentModel;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Data;
using System.Windows.Forms;
namespace StrangeControls
{
// Summary description for RoundButton.
// Хотя класс RoundButton и объявляется на основе базового
// класса Button, внешнее представление его
// объектов-представителей реализуется в переопределяемом
// методе OnPaint с использованием класса ImageList.
public class RoundButton : Button
{
ImageList imgList;
// Внешнее представление элемента управления меняется
// в зависимости от состояния элемента. Это состояние
// зависит от конкретных событий, происходящих с элементом
// управления.
// Индекс, который используется при изменении внешнего
// представления элемента управления.
// Внешний вид элемента управления определяется значением
// переменной indexB, которая меняет значение в рамках
// переопределяемых обработчиков событий.
// Функциональность данного элемента управления задана
// в классе формы, в виде стандартных (непереопределяемых) обработчиков.
int indexB;
public RoundButton():base()
{
indexB = 0;
imgList = new ImageList();
imgList.Images.Add(Image.FromFile(@"jpg0.jpg"));
imgList.Images.Add(Image.FromFile(@"jpg1.jpg"));
imgList.Images.Add(Image.FromFile(@"jpg2.jpg"));
imgList.Images.Add(Image.FromFile(@"jpg3.jpg"));
this.ImageList=imgList;
}
// Код, управляющий изменением внешнего вида элемента.
// Сюда передается управление в результате выполнения метода
// Refresh().
protected override void OnPaint(PaintEventArgs e)
{
GraphicsPath gp = new GraphicsPath();
gp.AddEllipse(10,10,50,50);
Region reg = new Region(gp);
// Свойству Region присваивается новое значение – новый регион!
this.Region = reg;
e.Graphics.DrawImage(ImageList.Images[indexB],10,10,50,50);
}
protected override void OnClick(EventArgs e)
{
indexB = 0;
this.Refresh();
base.OnClick (e);
}
protected override void OnMouseDown(MouseEventArgs e)
{
indexB = 1;
this.Refresh();
base.OnMouseDown (e);
}
protected override void OnGotFocus(EventArgs e)
{
indexB = 0;
this.Refresh();
base.OnGotFocus (e);
}
protected override void OnLostFocus(EventArgs e)
{
indexB = 0;
this.Refresh();
base.OnLostFocus(e);
}
protected override void OnMouseEnter(EventArgs e)
{
indexB = 2;
this.Refresh();
base.OnMouseEnter (e);
}
protected override void OnMouseLeave(EventArgs e)
{
indexB = 3;
this.Refresh();
base.OnMouseLeave (e);
}
private void InitializeComponent()
{
//
// RoundButton
//
}
}
}
Ниже приводится фрагмент кода формы (включая назначение и определение метода – обработчика события), использующей данный элемент управления:
private void InitializeComponent()
{
::::::::::::::::::::
//
// roundButton1
//
this.roundButton1.Cursor = System.Windows.Forms.Cursors.Cross;
this.roundButton1.Location = new System.Drawing.Point(136, 8);
this.roundButton1.Name = "roundButton1";
this.roundButton1.Size = new System.Drawing.Size(72, 72);
this.roundButton1.TabIndex = 2;
this.roundButton1.Text = "roundButton1";
this.roundButton1.Click += new System.EventHandler(this.roundButton_Click);
::::::::::::::::::::
}
Сам обработчик события в форме объявлен следующим образом:
private void roundButton_Click(object sender, System.EventArgs e)
{
if (imgListindex < imgList.Images.Count–1) imgListindex++;
else imgListindex = 0;
pictureBox1.Image = imgList.Images[imgListindex];
}
Следующий фрагмент кода посвящен разработке составного элемента управления, который представляет собой "батарею" из 16 одинаковых кнопочек, располагаемых на одной панели. Несмотря на внушительное количество составляющих элементов, перед нами один элемент управления с общим единым обработчиком события, связанным с нажатием на одну из 16 кнопочек. Естественно, что реализация единого обработчика требует дополнительных усилий: каждой кнопке назначается один и тот же стандартный обработчик с двумя параметрами. Один из параметров используется для идентификации нажатой кнопки. При нажатии на кнопку происходит изменение состояния этой кнопки, которое кодируется посредством текстового значения (свойства Text ), отображаемого на поверхности кнопки.
using System;
using System.Collections;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Windows.Forms;
namespace By2
{
// Summary description for ButtonsControl.
public class ButtonsControl : System.Windows.Forms.UserControl
{
// Required designer variable.
private Form1 f1;
private ArrayList bArrList;
private System.Windows.Forms.Panel panel1;
private System.Windows.Forms.Button button16;
private System.Windows.Forms.Button button15;
private System.Windows.Forms.Button button14;
private System.Windows.Forms.Button button13;
private System.Windows.Forms.Button button12;
private System.Windows.Forms.Button button11;
private System.Windows.Forms.Button button10;
private System.Windows.Forms.Button button9;
private System.Windows.Forms.Button button8;
private System.Windows.Forms.Button button7;
private System.Windows.Forms.Button button6;
private System.Windows.Forms.Button button5;
private System.Windows.Forms.Button button4;
private System.Windows.Forms.Button button3;
private System.Windows.Forms.Button button2;
private System.Windows.Forms.Button button1;
public ArrayList parameterList;
public void SetParent(Form1 fKey)
{
f1 = fKey;
}
private System.ComponentModel.Container components = null;
public ButtonsControl()
{
InitializeComponent();
bArrList = new ArrayList();
bArrList.Add(button16);
bArrList.Add(button15);
bArrList.Add(button14);
bArrList.Add(button13);
bArrList.Add(button12);
bArrList.Add(button11);
bArrList.Add(button10);
bArrList.Add(button9);
bArrList.Add(button8);
bArrList.Add(button7);
bArrList.Add(button6);
bArrList.Add(button5);
bArrList.Add(button4);
bArrList.Add(button3);
bArrList.Add(button2);
bArrList.Add(button1);
parameterList = new ArrayList();
}
private void SetParameterList()
{
int i, I = bArrList.Count ;
parameterList.Clear();
for (i = 0; i < I; i++)
{
parameterList.Add(int.Parse(((Button)bArrList[i]).Text));
}
f1.formDecimalValue(parameterList);
}
public void SetButtons(ArrayList lst)
{
int i, I = lst.Count, J = bArrList.Count;
for (i = 0; i < J; i++)
{
((Button)bArrList[i]).Text = "0";
}
for (i = 0; i < I; i++)
{
((Button)bArrList[i]).Text = ((int)lst[i]).ToString();
}
}
// Clean up any resources being used.
protected override void Dispose( bool disposing )
{
if( disposing )
{
if(components != null)
{
components.Dispose();
}
}
base.Dispose( disposing );
}
#region Component Designer generated code
// Required method for Designer support – do not modify
// the contents of this method with the code editor.
private void InitializeComponent()
{
this.panel1 = new System.Windows.Forms.Panel();
this.button16 = new System.Windows.Forms.Button();
this.button15 = new System.Windows.Forms.Button();
this.button14 = new System.Windows.Forms.Button();
this.button13 = new System.Windows.Forms.Button();
this.button12 = new System.Windows.Forms.Button();
this.button11 = new System.Windows.Forms.Button();
this.button10 = new System.Windows.Forms.Button();
this.button9 = new System.Windows.Forms.Button();
this.button8 = new System.Windows.Forms.Button();
this.button7 = new System.Windows.Forms.Button();
this.button6 = new System.Windows.Forms.Button();
this.button5 = new System.Windows.Forms.Button();
this.button4 = new System.Windows.Forms.Button();
this.button3 = new System.Windows.Forms.Button();
this.button2 = new System.Windows.Forms.Button();
this.button1 = new System.Windows.Forms.Button();
this.panel1.SuspendLayout();
this.SuspendLayout();
//
// panel1
//
this.panel1.BorderStyle = System.Windows.Forms.BorderStyle.Fixed3D;
this.panel1.Controls.Add(this.button16);
this.panel1.Controls.Add(this.button15);
this.panel1.Controls.Add(this.button14);
this.panel1.Controls.Add(this.button13);
this.panel1.Controls.Add(this.button12);
this.panel1.Controls.Add(this.button11);
this.panel1.Controls.Add(this.button10);
this.panel1.Controls.Add(this.button9);
this.panel1.Controls.Add(this.button8);
this.panel1.Controls.Add(this.button7);
this.panel1.Controls.Add(this.button6);
this.panel1.Controls.Add(this.button5);
this.panel1.Controls.Add(this.button4);
this.panel1.Controls.Add(this.button3);
this.panel1.Controls.Add(this.button2);
this.panel1.Controls.Add(this.button1);
this.panel1.Location = new System.Drawing.Point(8, 8);
this.panel1.Name = "panel1";
this.panel1.Size = new System.Drawing.Size(648, 48);
this.panel1.TabIndex = 0;
//
// button16
//
this.button16.Location = new System.Drawing.Point(605, 12);
this.button16.Name = "button16";
this.button16.Size = new System.Drawing.Size(32, 23);
this.button16.TabIndex = 146;
this.button16.Text = "0";
this.button16.Click += new System.EventHandler(this.buttonX_Click);
//
// button15
//
this.button15.Location = new System.Drawing.Point(565, 12);
this.button15.Name = "button15";
this.button15.Size = new System.Drawing.Size(32, 23);
this.button15.TabIndex = 145;
this.button15.Text = "0";
this.button15.Click += new System.EventHandler(this.buttonX_Click);
//
// button14
//
this.button14.Location = new System.Drawing.Point(525, 12);
this.button14.Name = "button14";
this.button14.Size = new System.Drawing.Size(32, 23);
this.button14.TabIndex = 144;
this.button14.Text = "0";
this.button14.Click += new System.EventHandler (this.buttonX_Click);
//
// button13
//
this.button13.Location = new System.Drawing.Point(485, 12);
this.button13.Name = "button13";
this.button13.Size = new System.Drawing.Size(32, 23);
this.button13.TabIndex = 143;
this.button13.Text = "0";
this.button13.Click += new System.EventHandler (this.buttonX_Click);
//
// button12
//
this.button12.Location = new System.Drawing.Point(445, 12);
this.button12.Name = "button12";
this.button12.Size = new System.Drawing.Size(32, 23);
this.button12.TabIndex = 142;
this.button12.Text = "0";
this.button12.Click += new System.EventHandler (this.buttonX_Click);
//
// button11
//
this.button11.Location = new System.Drawing.Point(405, 12);
this.button11.Name = "button11";
this.button11.Size = new System.Drawing.Size(32, 23);
this.button11.TabIndex = 141;
this.button11.Text = "0";
this.button11.Click += new System.EventHandler (this.buttonX_Click);
//
// button10
//
this.button10.Location = new System.Drawing.Point(365, 12);
this.button10.Name = "button10";
this.button10.Size = new System.Drawing.Size(32, 23);
this.button10.TabIndex = 140;
this.button10.Text = "0";
this.button10.Click += new System.EventHandler (this.buttonX_Click);
//
// button9
//
this.button9.Location = new System.Drawing.Point(325, 12);
this.button9.Name = "button9";
this.button9.Size = new System.Drawing.Size(32, 23);
this.button9.TabIndex = 139;
this.button9.Text = "0";
this.button9.Click += new System.EventHandler (this.buttonX_Click);
//
// button8
//
this.button8.Location = new System.Drawing.Point(285, 12);
this.button8.Name = "button8";
this.button8.Size = new System.Drawing.Size(32, 23);
this.button8.TabIndex = 138;
this.button8.Text = "0";
this.button8.Click += new System.EventHandler(this.buttonX_Click);
//
// button7
//
this.button7.Location = new System.Drawing.Point(245, 12);
this.button7.Name = "button7";
this.button7.Size = new System.Drawing.Size(32, 23);
this.button7.TabIndex = 137;
this.button7.Text = "0";
this.button7.Click += new System.EventHandler(this.buttonX_Click);
//
// button6
//
this.button6.Location = new System.Drawing.Point(205, 12);
this.button6.Name = "button6";
this.button6.Size = new System.Drawing.Size(32, 23);
this.button6.TabIndex = 136;
this.button6.Text = "0";
this.button6.Click += new System.EventHandler(this.buttonX_Click);
//
// button5
//
this.button5.Location = new System.Drawing.Point(165, 12);
this.button5.Name = "button5";
this.button5.Size = new System.Drawing.Size(32, 23);
this.button5.TabIndex = 135;
this.button5.Text = "0";
this.button5.Click += new System.EventHandler(this.buttonX_Click);
//
// button4
//
this.button4.Location = new System.Drawing.Point(125, 12);
this.button4.Name = "button4";
this.button4.Size = new System.Drawing.Size(32, 23);
this.button4.TabIndex = 134;
this.button4.Text = "0";
this.button4.Click += new System.EventHandler (this.buttonX_Click);
//
// button3
//
this.button3.Location = new System.Drawing.Point(85, 12);
this.button3.Name = "button3";
this.button3.Size = new System.Drawing.Size(32, 23);
this.button3.TabIndex = 133;
this.button3.Text = "0";
this.button3.Click += new System.EventHandler (this.buttonX_Click);
//
// button2
//
this.button2.Location = new System.Drawing.Point(45, 12);
this.button2.Name = "button2";
this.button2.Size = new System.Drawing.Size(32, 23);
this.button2.TabIndex = 132;
this.button2.Text = "0";
this.button2.Click += new System.EventHandler (this.buttonX_Click);
//
// button1
//
this.button1.Location = new System.Drawing.Point(5, 12);
this.button1.Name = "button1";
this.button1.Size = new System.Drawing.Size(32, 23);
this.button1.TabIndex = 131;
this.button1.Text = "0";
this.button1.Click += new System.EventHandler(this.buttonX_Click);
//
// ButtonsControl
//
this.Controls.Add(this.panel1);
this.Name = "ButtonsControl";
this.Size = new System.Drawing.Size(664, 64);
this.panel1.ResumeLayout(false);
this.ResumeLayout(false);
}
#endregion
private void buttonX_Click(object sender, System.EventArgs e)
{
if (((Button)sender).Text.Equals("0")) ((Button)sender).Text = "1";
else ((Button)sender).Text = "0";
SetParameterList();
}
}
}
Для получения официальных документов о завершении программы дополнительного профессионального образования (удостоверения о повышении квалификации, дипломов о профессиональной переподготовке и MBA) необходимо предоставить:
Внимание! Вы можете не заказывать доставку бумажной версии официального документы, а скачать его в электронном виде и распечатать самостоятельно. Информация о выданном документе в течение 1 месяца загружается в Федеральную информационную систему «Федеральный реестр сведений о документах об образовании и (или) о квалификации, документах об обучении» - ФИС ФРДО.
Доступ на новый сайт осуществляется с использованием адреса электронной почты, который был указан вами при регистрации на "старом". Мы постарались перенести все ваши данные с прежнего ресурса, однако не исключена вероятность потери части информации.
При возникновении проблемы со входом, воспользуйтесь функцией сброса пароля
Если вы обнаружите несоответствия, пожалуйста, сообщите нам.