Опубликован: 05.08.2010 | Уровень: специалист | Доступ: платный
Самостоятельная работа 3:

Windows Forms и XNA 3.0

Визуализация объекта, использующего эффект

Визуализация примитивов, использующих эффект, начинается с вызова метода effect.Begin() объекта эффекта. Далее приложение должно перебрать все проходы текущей техники (коллекция effect.CurrentTechnique.Passes ) и вызвать метод pass.Begin() для каждого прохода. Внутри прохода нужно визуализировать примитивы с использованием метода device.DrawUserPrimitives(). Визуализацию прохода нужно закончить вызовом метода pass.End(). По окончанию визуализации всего эффекта приложение должно вызвать метод effect.End().

  • Через контекстное меню перейдите в режим View Designer формы, выделите на ней объект xnaPanel1 и откройте панель Properties в режиме Events
  • Найдите событие Paint объекта xnaPanel1 и двойным щелчком на его поле справа создайте обработчик, который заполните так
private void xnaPanel1_Paint(object sender, PaintEventArgs e)
        {
            if (closing)
                return;
    
            try
            {
                if (device.GraphicsDeviceStatus == GraphicsDeviceStatus.Lost)
                    throw new DeviceLostException();
    
                if (device.GraphicsDeviceStatus == GraphicsDeviceStatus.NotReset)
                    device.Reset(presentParams);
    
                // Очищаем область экрана
                device.Clear(XNAGraphics.Color.CornflowerBlue);
    
                device.RenderState.CullMode = CullMode.None;
                device.VertexDeclaration = decl;
    
                // Задаем координаты вершин из установленного в группе панелей цвета
                vertices[0] = new VertexPositionColor(new Vector3(0.0f, 0.8f, 0.0f), new XNAGraphics.Color(
                    vertex1Color.BackColor.R, vertex1Color.BackColor.G, vertex1Color.BackColor.B));
                vertices[1] = new VertexPositionColor(new Vector3(0.8f, -0.8f, 0.0f), new XNAGraphics.Color(
                    vertex2Color.BackColor.R, vertex2Color.BackColor.G, vertex2Color.BackColor.B));
                vertices[2] = new VertexPositionColor(new Vector3(-0.8f, -0.8f, 0.0f), new XNAGraphics.Color(
                    vertex3Color.BackColor.R, vertex3Color.BackColor.G, vertex3Color.BackColor.B));
    
                effect.Begin();
                foreach(EffectPass pass in effect.CurrentTechnique.Passes)
                {
                    pass.Begin();
                    device.DrawUserPrimitives(PrimitiveType.TriangleList, vertices, 0, vertices.Length / 3);
                    pass.End();
                }
                effect.End();
    
                device.Present();
            }
            catch (DeviceNotResetException)
            {
                Invalidate();
            }
            catch (DeviceLostException)
            {
                closing = true;     // Больше не выполнять OnPaint()
                string title = "Сбой графического устройства";
                string message = "Работа программы будет завершена.\n"
                               + "Закройте все ненужные программы\n"
                               + "и повторите запуск этого приложения";
                MessageBox.Show(message, title, MessageBoxButtons.OK, MessageBoxIcon.Stop);
                Application.Idle += new EventHandler(Application_Idle);
                return;
            }
            catch (Exception ext)           // Все другие исключения
            {
                closing = true;
                MessageBox.Show(ext.Message);
                Application.Idle += Application_Idle;
            }
        }
  • Выделите на форме объект xnaPanel1 и через панель Properties в режиме Events создайте обработчик события Resize, который заполните так
private void xnaPanel1_Resize(object sender, EventArgs e)
        {
            // Устанавливаем размеры заднего буфера по клиентской области панели
            presentParams.BackBufferWidth = xnaPanel1.ClientSize.Width;
            presentParams.BackBufferHeight = xnaPanel1.ClientSize.Height;
            // Сбрасываем устройство и применяем к нему новые параметры  
            // Если окно не минимизировано
            if (this.WindowState != FormWindowState.Minimized)
                device.Reset(presentParams); 
        }
  • Выделите саму форму щелчком на ее заголовке и через панель Properties в режиме Events создайте обработчик события FormClosed, который заполните так
private void MainForm_FormClosed(object sender, FormClosedEventArgs e)
        {
            //  Удаляем (освобождаем) устройство
            device.Dispose();
            // На всякий случай присваиваем ссылке на устройство значение null 
            device = null;
        }
  • Осторожно (чтобы не создать обработчик) выделите все три кнопки на форме (удерживая клавишу Ctrl ) и через панель Properties в режиме Events создайте обработчик события Click с именем vertexColor_Click, который заполните так
private void vertexColor_Click(object sender, EventArgs e)
        {
            Button button = (Button)sender;
            colorDialog1.Color = button.BackColor;
            if (colorDialog1.ShowDialog() == DialogResult.OK)
            {
                button.BackColor = colorDialog1.Color;
                xnaPanel1.Invalidate();
            }
        }
  • В панели Solution Explorer выделите узел проекта Application2 и через контекстное меню сделайте проект стартовым. Запустите приложение - должен получиться такой результат


Замечание. Если приложение выдаст сообщение "Ошибка при компиляции эффекта...", то добавьте к проекту файл с эффектом ColorFill.fx из прилагаемой к работе папки Source, не редактируя его. Незабудьте в этом случае изменить свойство файла Copy to Output Directory на значение Copy if newer.

Запускающее приложение

Если вы все делали так как описано, то исполнимые сборки для упражнений 1 и 2 должны находиться относительно папки решений FormsXNA в подпапках:

FormsXNA\Application1\bin\Debug\Application1.exe  
  FormsXNA\Application2\bin\Debug\Application2.exe

В этом разделе, для тренировки, мы добавим к проекту простое приложение, запускающее сборки с выполненными упражнениями, чтобы легче было их демонстрировать.

  • Добавьте к решению новый проект с именем StartForm и сделайте его стартовым
  • Переименуйте файл формы Form1.cs в StartForm.cs и откройте его в режиме View Designer и поместите на форму два экземпляра компонента LinkLabel


  • Создайте для них обработчики события LinkClicked и заполните их следующим кодом
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
    
using System.IO;
    
namespace StartApp
{
    public partial class StartForm : Form
    {
        System.Diagnostics.Process exe = new System.Diagnostics.Process();
        String path; // Путь к папке с решением
    
        public StartForm()
        {
            InitializeComponent();
    
            path = Directory.GetCurrentDirectory();// Получаем путь к сборке StartForm 
            int pos = path.LastIndexOf(@"\bin\");
            path = path.Substring(0, pos);// Убираем 2 последних секции пути
            pos = path.LastIndexOf(@"\");
            path = path.Substring(0, pos);// Убираем еще одну секцию
        }
    
        private void linkLabel1_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
        {
            Directory.SetCurrentDirectory(path + @"\Application1\bin\Debug");// Путь к сборке
            exe.StartInfo.FileName = "Application1.exe";
            System.Diagnostics.Debug.WriteLine(path); // Для отладки в окно Output
            exe.Start();
        }
    
        private void linkLabel2_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
        {
            Directory.SetCurrentDirectory(path + @"\Application2\bin\Debug");// Путь к сборке
            exe.StartInfo.FileName = "Application2.exe";
            System.Diagnostics.Debug.WriteLine(path); // Для отладки в окно Output
            exe.Start();
        }
    }
}

Код будет работать при условии, что сборка стартовой формы находится в своем каталоге bin дерева решения.


Алексей Бабушкин
Алексей Бабушкин

При выполнении в лабораторной работе упражнения №1 , а именно при выполнении нижеследующего кода:

using System;

using System.Collections.Generic;

using System.ComponentModel;

using System.Data;

using System.Drawing;

using System.Text;

using System.Windows.Forms;

using Microsoft.Xna.Framework.Graphics;

   

namespace Application1

{

    public partial class MainForm : Form

    {

        // Объявим поле графического устройства для видимости в методах

        GraphicsDevice device;

   

        public MainForm()

        {

            InitializeComponent();

   

            // Подпишемся на событие Load формы

            this.Load += new EventHandler(MainForm_Load);

   

            // Попишемся на событие FormClosed формы

            this.FormClosed += new FormClosedEventHandler(MainForm_FormClosed);

        }

   

        void MainForm_FormClosed(object sender, FormClosedEventArgs e)

        {

            //  Удаляем (освобождаем) устройство

            device.Dispose();

            // На всякий случай присваиваем ссылке на устройство значение null

            device = null;       

        }

   

        void MainForm_Load(object sender, EventArgs e)

        {

            // Создаем объект представления для настройки графического устройства

            PresentationParameters presentParams = new PresentationParameters();

            // Настраиваем объект представления через его свойства

            presentParams.IsFullScreen = false; // Включаем оконный режим

            presentParams.BackBufferCount = 1;  // Включаем задний буфер

                                                // для двойной буферизации

            // Переключение переднего и заднего буферов

            // должно осуществляться с максимальной эффективностью

            presentParams.SwapEffect = SwapEffect.Discard;

            // Устанавливаем размеры заднего буфера по клиентской области окна формы

            presentParams.BackBufferWidth = this.ClientSize.Width;

            presentParams.BackBufferHeight = this.ClientSize.Height;

   

            // Создадим графическое устройство с заданными настройками

            device = new GraphicsDevice(GraphicsAdapter.DefaultAdapter, DeviceType.Hardware,

                this.Handle, presentParams);

        }

   

        protected override void OnPaint(PaintEventArgs e)

        {

            device.Clear(Microsoft.Xna.Framework.Graphics.Color.CornflowerBlue);

   

            base.OnPaint(e);

        }

    }

}

Выбрасывается исключение:

Невозможно загрузить файл или сборку "Microsoft.Xna.Framework, Version=3.0.0.0, Culture=neutral, PublicKeyToken=6d5c3888ef60e27d" или один из зависимых от них компонентов. Не удается найти указанный файл.

Делаю все пунктуально. В чем может быть проблема?

Dmitriy Ivanchenko
Dmitriy Ivanchenko
Украина, Кировоград, Виктория-П, 2011
Татьяна Ковалюк
Татьяна Ковалюк
Украина, Киев, Киевский политехнический институт, 1974