Партнерка на США и Канаду по недвижимости, выплаты в крипто
- 30% recurring commission
- Выплаты в USDT
- Вывод каждую неделю
- Комиссия до 5 лет за каждого referral
Теперь приступим к написанию самой программы.
Вначале в теле метода-обработчика ( //add code here 3) нажатия на кнопку Button1 напишите код, который циклически меняет текст, отображаемый на кнопке. Начальный текст «Remove outer layer», затем «Remove middle layer», затем «Restore Layers», при последующих нажатиях на кнопку надписи опять повторяются сначала в этом же порядке.
Используйте конструкцию switch – case и свойство Text объекта Button1.
Ее синтаксис:
switch(KEY) { case 0: //some code break; case 1: //some code break; default: //some code break; } |
Запустите программу и проверьте, правильно ли меняется текст кнопок.
Далее, при нажатии кнопки “Remove Outer Layer” или “Remove Middle Layer” необходимо менять картинку. Для этого нужно запустить таймер и по каждому тику таймера менять прозрачность «внешней» и «внутренней» картинок. Поэтому добавьте код для запуска таймера при нажатии этих кнопок: timer1.Enabled = true;
После смены текста с “Remove Outer Layer” на “Remove Middle Layer” мы делаем прозрачность средней картинки равной 1. Ставим флаги
removeouter = true; removemiddle = false; |
и запускаем таймер.
В результате получается следующее:
removeouter = true; middleTransparency = 1.0f; removemiddle = false; timer1.Enabled = true; button1.Text = "Remove middle Layer"; |
По аналогии добавьте такой же код, который будет выполняться при нажатии кнопки и смены ее текста с “Remove Middle Layer” до “Restore Layers”.
После нажатия кнопки «Restore Layers» мы возвращаемся в исходное состояние. В этом случае код будет таким:
removeouter = false; removemiddle = false; outerTransparency = 1.0f; middleTransparency = 1.0f; button1.Text = "Remove outer Layer"; Refresh(); |
При смене картинок мы запускаем таймер и по тику таймера меняем значения переменной masterTransparency. Затем, присваиваем ее значение переменной outerTransparency или middleTransparency в зависимости от того, какую картинку мы убираем. Код, который работает по тику таймера, такой (добавьте его под //add code here 4):
masterTransparency = Count; if(Count > 0.05) Count -= 0.05f; else { Count = 1.0f; timer1.Enabled = false; masterTransparency = 0.0f; } if(removeouter) { outerTransparency = masterTransparency; } if(removemiddle) { middleTransparency = masterTransparency; } |
В конце метода timer1_Tick вызывается метод Invalidate(), который посылает событие OnPaint всем дочерним компонентам формы. Сейчас мы напишем обработчик этого события для самой формы.
Мы должны нарисовать на форме все 3 картинки, но с учетом значений прозрачности, вычисленных на данном тике таймера. Картинки при плавном переходе их одна в другую перерисовываются на форме каждый тик таймера (примерно 50 раз в секунду). Вставьте код для рисования первой картинки в тело метода OnPaint, а остальные добавьте по аналогии (замените лишь параметр, отвечающий за то, какая картинка рисуется)
// Draw the base image e. Graphics. DrawImage(btmInner, rect, 0,0, 600, 300, GraphicsUnit. Pixel); //Set alpha in the ColorMatrix middleColorMatrix. Matrix33 = middleTransparency; // Set color matrix of imageAttributes middleImageAttributes. SetColorMatrix(middleColorMatrix, ColorMatrixFlag. Default, ColorAdjustType. Bitmap); |
После этого запустите программу – она должна работать так же, как и демоверсия! Повторите все перечисленные траектории в количестве конкретных задач, поставленных перед вами преподавателем.
Лабораторная работа №4.
Создание и гармонизация динамического оконного приложения
Шаг 1. Создание оконного приложения.
1.1. Запустите интегрированную среду разработки Microsoft Visual 2003. Выберите пункт меню File/New/New Project.

1.2. В появившемся диалоговом окне в списке Project Types выберите пункт Visual C# Projects, в обновившемся списке Templates выберите пункт Windows Application. В поле ввода Name введите название проекта (например, DXApp), в поле ввода Location укажите путь к каталогу проекта (например, С:\).

После нажатия кнопки OK будет создан проект для оконного приложения. Для сборки проекта выберите пункт главного меню Build/Build Solution или нажмите Ctrl+Shift+B.

Сборка должна пройти без ошибок. Для выполнения программы выберите пункт меню Debug/Start Without Debugging или нажмите Ctrl+F5.

На экране появится окно вашего приложения.

Шаг 2. Настройка свойств окна.
В окне Solution Explorer отображается список файлов проекта. Исходный текст на языке C#, относящийся к главному окну приложения находится в файле Form1.cs. Нажатие над этим файлом правой кнопки мыши приводит к появлению контекстного меню, в котором присутствуют пункты View Code и View Designer, определяющие отображение в окне редактора или исходного текста или внешнего вида окна.

Нажмите правую кнопку мыши в свободной области редактора внешнего вида окна и в появившемся контекстном меню выберите пункт Properties.

На экране появится окно редактора свойств формы. Убедитесь, что третья слева кнопка, отображающая список свойств, нажата.

В свойствах окна (формы) измените свойство Text, задающее заголовок окна, (например, на “Приложение Direct3D”). В свойстве Icon укажите путь к файлу пиктограммы. Теперь окно приложения должно выглядеть следующим образом.

Шаг 3. Создание устройства Direct3D для работы с трехмерной графикой.
3.1. Для начала необходимо подключить к проекту сборки DirectX. dll, Direct3D. dll и Direct3DX. dll, содержащие managed классы для работы с DirectX 9.0. Для этого в окне Solution Explorer нажмите правую кнопку мыши над элементом References и выберите в появившемся меню пункт Add Reference.

В появившемся окне при помощи кнопки Browse на закладке. NET добавьте в проект перечисленные выше сборки.

3.2. Устройство Direct3D удобно создавать при первом показе окна на экране. Создайте обработчик события Load. Для этого в окне свойств окна (формы) выберите список событий. Для этого нажмите кнопку с изображением молнии. В списке событий дважды нажмите левую кнопку мыши на событие Load.

Будет создан метод с именем Form1_Load, код которого сразу же отобразится в редакторе.
До этого момента весь код создавала за нас Visual Studio, теперь код придется писать самим J. Значительную помощь в наборе длинных идентификаторов оказывает технология Intellisense, предлагающая выбор методов, свойств или полей данных объекта после набора символа “точка”
3.3. В самом начале исходного текста добавьте две директивы using. Это позволит обращаться к классам DirectX не указывая каждый раз длинных префиксов пространств имен. Здесь и далее жирным шрифтом выделен добавляемый исходный текст.
… using System. Data; using Microsoft. DirectX; using Microsoft. DirectX. Direct3D; … |
3.4. В классе Form1 добавьте поле данных типа Microsoft. Direct3D. Device для хранения ссылки на устройство Direct3D.
public class Form1 : System. Windows. Forms. Form { … Device d3d = null; // Устройство для отображения 3D-графики … } |
3.5. В метод Form1_Load добавьте код для инициализации устройства Direct3D. Для обработки возможных ошибок код инициализации поместим в блок try/catch.
private void Form1_Load(object sender, System. EventArgs e) { try { // Устанавливаем режим отображения трехмерной графики PresentParameters d3dpp = new PresentParameters(); d3dpp. BackBufferCount = 1; d3dpp. SwapEffect = SwapEffect. Discard; d3dpp. Windowed = true; // Выводим графику в окно d3dpp. MultiSample = MultiSampleType. None; // Выключаем антиалиасинг d3dpp. EnableAutoDepthStencil = true; // Разрешаем создание z-буфера d3dpp. AutoDepthStencilFormat = DepthFormat. D16; // Z-буфер в 16 бит d3d = new Device(0, // D3D_ADAPTER_DEFAULT - видеоадаптер по умолчанию DeviceType. Hardware, // Тип устройства - аппаратный ускоритель this, // Окно для вывода графики CreateFlags.SoftwareVertexProcessing, // Геометрию обрабатывает CPU d3dpp); } catch(Exception exc) { MessageBox.Show(this,exc.Message,"Ошибка инициализации"); Close(); // Закрываем окно } } |
3.6. Хорошим тоном в программировании считается своевременное освобождение всех ранее полученных ресурсов. Освобождение памяти берет на себя автоматический сборщик мусора, а освобождение ресурсов Direct3D надо указать явно. Для этого добавьте следующий код в уже существующий виртуальный метод Dispose(bool disposing) класса Form1:
protected override void Dispose( bool disposing ) { if(disposing) { if(components!= null) { components. Dispose(); } // Освобождаем занятые ранее ресурсы if(d3d!= null) d3d. Dispose(); } base. Dispose(disposing); } |
Теперь проект можно собрать и запустить. Внешний вид окна не изменится, но рисование трехмерных объектов в окне можно будет выполнять, вызывая методы объекта d3d.
Шаг 4. Добавление кода для рисования.
4.1. В окне свойств выберите список событий класса Form1 и добавьте обработчик события Paint точно таким же образом, как и обработчик события Load.

4.2. В метод Form1_Paint добавьте код, очищающий буфер глубины, заполняющий дублирующий буфер темно зеленым цветом и показывающий его на экран.
private void Form1_Paint(object sender, System. Windows. Forms. PaintEventArgs e) { // Очищаем буфер глубины и дублирующий буфер d3d. Clear(ClearFlags. Target|ClearFlags. ZBuffer, Color. Green,1.0f,0); //.Показываем содержимое дублирующего буфера d3d.Present(); } |
После выполнения шага 4 окно приложение должно выглядеть следующим образом.

Шаг 5. Рисование трехмерного объекта.
5.1. В конструкторе класса Form1 установите режим перерисовки содержимого окна при любом изменении размера
public Form1() { … InitializeComponent(); SetStyle(ControlStyles. ResizeRedraw, true); … } |
5.2. В класс Form1 добавьте поле данных teapot типа Mesh для хранения ссылки на полигональный объект.
сlass Form1 { … Mesh teapot = null; // Модель чайника … } |
5.3. В метод Form1_Load добавьте код, создающий полигональную модель чайника.
private void Form1_Load(object sender, System. EventArgs e) … d3d = new Device(…); // Создаем модель чайника и задаем ее свойства teapot = Mesh. Teapot(d3d); … } |
5.4. В метод Dispose добавьте код, освобождающий занятые для полигональной модели ресурсы Direct3D.
protected override void Dispose(bool disposing) { … if(teapot!= null) teapot. Dispose(); if(d3d!= null) d3d. Dispose(); … } |
5.5. В метод Form1_Paint добавьте код, отображающий чайник на экране. Для этого необходимо задать преобразование для перспективного проецирования координат из системы координат наблюдателя на экран, задать преобразование из системы координат объекта (чайника) в систему координат наблюдателя и вызвать метод для отрисовки полигональной модели на экране.
private void Form1_Paint(object sender, System. Windows. Forms. PaintEventArgs e) { d3d. Clear(ClearFlags. Target|ClearFlags. ZBuffer, Color. Green,1.0f,0); … // Начинаем отрисовку кадра d3d. BeginScene(); // Задаем матрицу проецирования d3d.Transform.Projection = Matrix.PerspectiveFovLH( (float)Math. PI/3, // Угол зрения Width/(float)Height, // Отношение высоты и ширины окна 0.5f,25.0f); // Диапазон изменения координаты z // Задаем матрицу преобразования мировых координат для чайника: // сдвиг на 3.5 условные единицы :) по оси z от наблюдателя d3d. Transform. World = Matrix. Translation(0,0,3.5f); // Рисуем чайник teapot.DrawSubset(0); // Завершаем отрисовку кадра d3d.EndScene(); d3d. Present(); } |
После выполнения этих действий в окне должен появится силуэт чайника.

Шаг 6. Добавляем освещение.
6.1. Для подчеркивания трехмерности объекта можно включить источник освещения. В класс Form1 добавьте поле данных teapotMaterial типа Material для хранения свойств поверхности чайника.
сlass Form1 { … Mesh teapot = null; // Модель чайника Material teapotMaterial; // Материал из которого изготовлен чайник … } |
6.2. В метод Form1_Load добавьте код, задающий цвет диффузного (рассеянного) и зеркального отражения для материала чайника.
private void Form1_Load(object sender, System. EventArgs e) { … // Создаем модель чайника и задаем ее свойства teapot = Mesh. Teapot(d3d); teapotMaterial = new Material(); teapotMaterial. Diffuse = Color. Blue; teapotMaterial. Specular = Color. White; … } |
Класс, а точнее, структура Material не содержит ссылок на объекты Direct3D, поэтому освобождение материалов в методе Dispose не требуется.
6.3. В методе Form1_Paint задайте положение и свойства одного источника освещения. Перед рисованием чайника установите материал для расчета освещения полигональной модели.
private void Form1_Paint(object sender, System. Windows. Forms. PaintEventArgs e) { … d3d. BeginScene(); // Устанавливаем параметры источника освещения d3d.Lights[0].Enabled = true; // Включаем нулевой источник освещения d3d.Lights[0].Diffuse = Color.White; // Цвет источника освещения d3d. Lights[0].Position = new Vector3(0,0,0); // Задаем координаты … d3d.Material = teapotMaterial; // Устанавливаем материал для чайника teapot. DrawSubset(0); … } |
После выполнения шага 6 модель чайника приобретает объемный вид.

Шаг 7. Рассматриваем чайник со всех сторон.
7.1. На этом шаге к трехмерной сцене будет добавлена анимация. Для начала необходимо организовать постоянную перерисовку окна. Для этого можно воспользоваться механизмом фоновой обработки (idle processing). Как только приложение обработало все сообщения, и очередь сообщений оказалась пуста, вызывается событие Application. Idle. Если обработчик этого события пометит главное окно как требующее обновление, то в очередь событий приложения почти сразу будет помещен запрос на перерисовку окна (сообщение WM_PAINT), который приведет к перерисовке окна и, в частности, к вызову метода Form1_Paint. После обработки запроса на перерисовку окна очередь сообщений вновь окажется пуста и будет вызвано событие Idle, обработчик которого вновь пометит главное окно приложения как требующее обновления и т. д. Для реализации этой схемы добавьте к классу Form1 следующий метод OnIdle.
class Form1 { … private void OnIdle(object sender, EventArgs e) { Invalidate(); // Помечаем главное окно (this) как требующее перерисовки } … } |
Для того чтобы связать метод OnIdle с событием Application. Idle необходимо изменить код метода Main, с которого начинается выполнение программы.
static void Main() { // Создаем объект-окно Form1 mainForm = new Form1(); // Cвязываем метод OnIdle с событием Application. Idle Application. Idle += new EventHandler(mainForm. OnIdle); // Показываем окно и запускаем цикл обработки сообщений *****n(mainForm); } |
7.2. Если теперь собрать и запустить проект, то в главном окне будет наблюдаться неприятное мерцание. Это связано с взаимодействием двойной буферизации Direct3D и отрисовки фона окна. Чтобы избавиться от этого неприятного эффекта добавьте в конструктор класса Form1 код для установки соответствующего режима перерисовки окна.
public Form1() { … SetStyle(ControlStyles. ResizeRedraw, true); // Устанавливаем режим обновления окна SetStyle(ControlStyles. Opaque, true); SetStyle(ControlStyles. UserPaint, true); SetStyle(ControlStyles. AllPaintingInWmPaint, true); } |
7.3. Для того чтобы скорость анимации не зависела от производительности компьютера, запомним время начала анимации в поле данных класса Form1. Тогда при каждой перерисовке окна можно определить сколько времени прошло от начала перерисовки и изменить положение и состояние объектов соответствующим образом.
Добавьте поле данных с именем startTime типа DateTime в класс Form1 для хранения времени начала анимации.
сlass Form1 { … DateTime startTime; // Время начала анимации … } |
Инициализируйте эту переменную в конце блока try/catch в методе Form1_Load.
private void Form1_Load(object sender, System. EventArgs e) { try { … startTime = DateTime. Now; // Засекаем время начала анимации } catch(Exception exc) { … } } |
В начало метода Form1_Paint добавьте код для вычисления времени в секундах, прошедшего с момента начала анимации до начала отрисовки текущего кадра.
private void Form1_Paint(object sender, System. Windows. Forms. PaintEventArgs e) { // Замеряем интервал времени между отрисовкой этого кадра и началом анимации DateTime currTime = DateTime. Now; TimeSpan totalTime = currTime - startTime; double totalSeconds = totalTime. TotalSeconds; … } |
7.3. Для вращения чайника достаточно задавать матрицу преобразования мировых координат в зависимости от значения переменной totalSeconds. Заведите в классе Form1 две константы типа double, определяющие частоту вращения (оборотов/c) чайника вокруг осей OX и OY.
сlass Form1 { … const double TeapotRotationX = 0.2; const double TeapotRotationY = 0.3; … } |
Измените в методе Form1_Paint код для вычисления матрицы преобразования мировых координат, как произведения преобразований вращения и переноса. Перед рисованием чайника можно отключить отсечение нелицевых граней, установив свойство d3d. RenderState. CullMode равным Сull. None.
private void Form1_Paint(object sender, System. Windows. Forms. PaintEventArgs e) { … // Отключаем отсечение нелицевых граней d3d. RenderState. CullMode = Cull. None; // Задаем матрицу преобразования для чайника d3d.Transform.World = Matrix. RotationX((float)(totalSeconds*TeapotRotationX*2*Math. PI))* Matrix. RotationY((float)(totalSeconds*TeapotRotationY*2*Math. PI))* Matrix. Translation(0,0,3.5f); … } |
После выполнения шага 7 чайник должен начать плавно вращаться вокруг двух осей.

Шаг 8. Усложняем сцену.
8.1. На этом шаге в сцену будут добавлены простые объекты, вращающиеся вокруг чайника. Добавьте в класс Form1 поля данных для хранения этих объектов и параметров их движения.
сlass Form1 { … Mesh[] objects = new Mesh[10]; // Модели вращающихся объектов Material[] objectMaterials = new Material[3]; // Материал объектов const double OrbitRadius = 1.5; // Радиус орбиты вращения вокруг чайника const double RotationFreq = 0.4; // Частота вращения по орбите… … } |
8.2. В метод Form1_Load добавьте код, создающий модели объектов, а именно полигональные аппроксимации сфер радиусом 0.05, и задающий свойства материалов.
private void Form1_Load(object sender, System. EventArgs e) { … // Создаем модели объектов, вращающихся вокруг чайника // и задаем свойства материалов for(int i = 0;i<objects.Length;i++) objects[i] = Mesh. Sphere(d3d, 0.05f, // Радиус сферы 10, // Количество параллелей 10); // Количество меридианов objectMaterials[0].Diffuse = Color. Red; objectMaterials[1].Diffuse = Color. LightGreen; objectMaterials[2].Diffuse = Color. LightBlue; … } |
8.3. Класс Microsoft. Direct3D. Mesh содержит ссылку на ресурсы Direct3D, требующие явного освобождения. Поэтому в метод Dispose класса Form1 добавьте код для освобождения всех ресурсов полигональных моделей их массива objects. Для более удобного и независимого от длины массива перечисления его элементов примените оператор foreach.
protected override void Dispose(bool disposing) { … foreach(Mesh m in objects) if(m!= null) m. Dispose(); … if(d3d!= null) d3d. Dispose(); … } |
8.4. В методе Form1_Paint отобразите созданные объекты на экран. Для каждого объекта из массива objects будет задана своя матрица преобразования мировых координат, осуществляющая вращение объектов вокруг чайника. При этом каждый объект вращается в своей плоскости. Сферы являются выпуклыми объектам, поэтому для уменьшения объема вычислений отсечение нелицевых граней можно включить.
private void Form1_Paint(object sender, System. Windows. Forms. PaintEventArgs e) { … d3d. Transform. Projection = Matrix. PerspectiveFovLH(…) // Включаем отсечение нелицевых граней d3d. RenderState. CullMode = Cull. CounterClockwise; // В цикле рисуем все объекты int numObjects = objects. Length; for(int i = 0;i<numObjects;i++) { // Задаем следующее преобразование координат: // Сдвигаем объект на радиус орбиты, // вращаем объект на зависящий от времени угол, // поворачиваем плоскость вращения на угол, зависящий от номера // объекта и совмещаем центр орбит объектов с центром чайника double a = i/(double)numObjects; d3d. Transform. World = Matrix. Translation(0,0,(float)OrbitRadius)* Matrix. RotationY((float)(2*Math. PI*(a + totalSeconds*RotationFreq)))* Matrix. RotationZ((float)(Math. PI*a)* Matrix.Translation(0,0,3.5f); // Задаем материал и рисуем i-й объект d3d. Material = objectMaterials[i % objectMaterials. Length]; objects[i].DrawSubset(0); } … } |
Теперь вокруг чайника вращаются несколько разноцветных сфер.

Шаг 9. Текстурирование.
9.1.Создайте в классе Form1 переменную с именем teapotTexture типа Texture для хранения ссылки на текстуру чайника.
сlass Form1 { … Mesh teapot = null; // Модель чайника Material teapotMaterial; // Материал из которого изготовлен чайник Texture teapotTexture = null; // Текстура для чайника … } |
9.2. Текстура будет загружена из файла. Классы для работы с потоками данных (в том числе и с файлами) находятся в пространстве имен System. IO. Для того, чтобы не указывать этот префикс при каждом обращении к соответствующим классам, добавьте в начало исходного текста директиву using System. IO.
… using System. Data; using System. IO; … |
9.3. Как и многие другие объекты Direct3D, текстуры удобно создавать при первом показе окна на экран и необходимо явно освобождать, когда они больше не нужны. Код для загрузки текстуры из файла добавьте в метод Form1_Load. Обратите внимание, что для гарантированного закрытия файла с текстурой (даже в случае возникновения исключения) применяется оператор using (не путать с одноименной директивой!).
private void Form1_Load(object sender, System. EventArgs e) { … // Загружаем текстуру для чайника из файла с именем spheremap. bmp using(FileStream textureFile = new FileStream("spheremap. bmp",FileMode. Open)) { teapotTexture = Texture. FromStream(d3d, textureFile, // Поток данных с текстурой 0, // Будем использовать как обычную текстуру Pool.Managed); // Область памяти для размещения текстуры textureFile.Close(); } … } |
Код для освобождения текстуры разместите в методе Dispose класса Form1.
|
Из за большого объема этот материал размещен на нескольких страницах:
1 2 3 |


