Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Лабораторный_практикум.doc
Скачиваний:
73
Добавлен:
15.11.2019
Размер:
45.35 Mб
Скачать

8. Модификация приложения Windows Forms: вкладка «Огонь!!!»

На этот раз будем имитировать горение огня (стена огня). Для создания эффекта огня будем использовать генерацию случайных чисел каждую миллисекунду. Однако, отображать сам огонь будем не на вкладке TabControl, а в новой форме. Это связано с «некрасивым» обновлением вкладки при рисовании огня (возникает заметное мерцание).

Создаём новую вкладку со свойствами:

TabPage:

Text:

Огонь!!!

Cursor:

No

Добавляем новую форму с именем LWP19Fire и не меняем какие-либо свойства формы (ну, разве что значок). Добавить форму можно так: Проект -> Добавить форму Windows... (а затем переименовать класс формы); либо использовать стандартное добавление: Проект -> Добавить новый элемент... (Ctrl+Shift+A) и далее указать Имя: LWP19Fire).

Редактируем код события Selected для TabControl. Добавляем туда строчки:

if (e.TabPage.Name == tabPage5.Name)

{

tabPage5.BackColor = Color.Black;

LWP19Fire Fire = new LWP19Fire();

Fire.ShowDialog();

}

Выбор данной вкладки («Огонь!!!») вызовет экземпляр модальной формы LWP19Fire.

Теперь редактируем код новой формы. Вначале добавим следующий код (в директивы using):

using System.Drawing.Imaging;

Теперь, найдём в коде формы строчки:

public partial class LWP19Fire : Form

{

Добавим после:

// Начало: вкладка "Огонь!!!"

private Bitmap buf; // Буфер для графики

private Random random = new Random(DateTime.Now.Millisecond); // Истоник данных (Random)

private const int width = 640;

private const int height = 320;

// Конец: вкладка "Огонь!!!"

Метод LWP19Fire() редактируем так:

public LWP19Fire()

{

InitializeComponent();

// Инициализируем источник для последующего использования

random = new Random();

// Устанавливаем начальные параметры вкладки

this.Text = "Расширенная работа с GDI+ (C#) :: форма для вкладки \"Огонь!!!\"";

this.ClientSize = new Size(width, height);

this.MaximizeBox = false;

this.FormBorderStyle = FormBorderStyle.FixedDialog;

this.BackColor = Color.Black;

SetStyle(ControlStyles.Opaque, true);

// Вызываем событие рисования (для метода DoFire)

this.Paint += new PaintEventHandler(this.DoFire);

// Генерируем палитру 640x480 (на основе Bimtap с 256 цветами на пиксель)

buf = new Bitmap(width, height, PixelFormat.Format8bppIndexed);

ColorPalette pal = buf.Palette;

// Заполняем палитру, используя 64-цветные блоки:

// чёрный с красным, красный с желтым, желтый с белым, белый.

// Так как каждый диапазон составляет 64 цветов и RGB охватывает 256 значений,

// использовуем левый сдвиг (<<) по массиву

for (int i = 0; i < 64; i++)

{

pal.Entries[i] = Color.FromArgb(i << 2, 0, 0);

pal.Entries[i + 64] = Color.FromArgb(255, i << 2, 0);

pal.Entries[i + 128] = Color.FromArgb(255, 255, i << 2);

pal.Entries[i + 192] = Color.FromArgb(255, 255, 255);

}

buf.Palette = pal;

}

И добавим метод для переопределённого события Paint формы:

// Метод рисования "огня"

private void DoFire(object src, PaintEventArgs e)

{

// Блокируем растр, чтобы мы смогли записывать в него напрямую

BitmapData buflock = buf.LockBits(

new Rectangle(Point.Empty, buf.Size),

ImageLockMode.ReadWrite, PixelFormat.Format8bppIndexed);

// Записываем "огонь"

// Используем указатели, потому блок "unsafe"

unsafe

{

// Извлекает указатель на верхнюю строку развёртки изображения

Byte* bufdata = (Byte*)buflock.Scan0;

Byte* bufbottom = bufdata + ((height - 1) * width);

Byte* i; int v;

// Используем случайную нижней линию в качестве источника "огня"

for (int x = 0; x < width; x++)

{

*(bufbottom + x) = (Byte)random.Next(100, 255);

}

// Для каждого пикселя в изображении,

// среднее значение пикселей, один справа, один снизу

// и один в левом нижнем углу. Достигаем порог 0,

// и пишем на текущей позиции

for (i = bufdata; i < bufbottom; i++)

{

v = *i + *(i + 1) + *(i + height) + *(i + height - 1);

v /= 4;

if (v < 0) v = 0;

*i = (Byte)v;

}

}

// Разблокируем изображение и рисуем на его на форме

buf.UnlockBits(buflock);

e.Graphics.DrawImageUnscaled(buf, 0, 0);

this.Invalidate();

}

Компилируем (Debug) и запускаем. Переходим на закладку «Огонь!!!», любуемся на огонь (можно любоваться вечно, не правда ли?).