Опубликован: 28.04.2009 | Доступ: свободный | Студентов: 1746 / 80 | Оценка: 4.36 / 4.40 | Длительность: 16:40:00
Специальности: Программист
Лекция 3:

Усложненные технологии визуализации

Следующий шаг - создание конструктора формы, принимающего в качестве параметров текущие настройки приложения и объект графического адаптера, используемого приложением (листинг 3.12).

public partial class SettingsForm : Form
{
// Набор ассоциативных сортированных массив с 
информаций о поддерживаемых видеорежимах
SortedDictionary<ResolutionItem, SortedDictionary<ColorDepthItem, 
 SortedDictionary<RefreshRateItem, bool>>> modeCollection;
// Текущие настройки приложения. Класс Properties.Settings 
автоматически генерируется 
// дизайнером настроек приложения (рисунок 3.10). 
Properties.Settings settings;
// Конструктор формы
internal SettingsForm(Properties.Settings settings, 
GraphicsAdapter adapter) 
{
InitializeComponent();
// Сохраняем ссылку на настройки приложения
 this.settings = settings;
// Если файл с конфигурацией приложения не был найден,
 устанавливаем в качестве параметров по 
// умолчанию настройки рабочего стола if (!settings.Init) 
{
settings.Width = adapter.CurrentDisplayMode.Width;
 settings.Height = adapter.CurrentDisplayMode.Height;
 settings.Format = adapter.CurrentDisplayMode.Format;
 settings.RefreshRate = adapter.CurrentDisplayMode.RefreshRate;
 settings.FullScreen = true;
}
modeCollection = new SortedDictionary<ResolutionItem, 
4> SortedDictionary<ColorDepthItem, SortedDictionary<RefreshRateItem,
bool>>>();
// Перебираем все видеорежимы, поддерживаемые видеокартой и
 заполняем ассоциативный массив 
// modeCollection
foreach (DisplayMode mode in adapter.SupportedDisplayModes)
{
ResolutionItem res = new ResolutionItem(mode.Width, mode.Height);
if (!modeCollection.ContainsKey(res))
modeCollection.Add(res, new SortedDictionary<ColorDepthItem,
 SortedDictionary<RefreshRateItem, bool>>());
ColorDepthItem depth = new ColorDepthItem(mode.Format); if
 (!modeCollection[res].ContainsKey(depth))
modeCollection[res].Add(depth, new SortedDictionary<RefreshRateItem,
 bool>());
RefreshRateItem refresh = new RefreshRateItem(mode.RefreshRate); if
 (!modeCollection[res][depth].ContainsKey(refresh))
 modeCollection[res][depth].Add(refresh, true); }
// Задаем состояние флага  "визуализировать в окне "
inWindowCheckBox.Checked = !settings.FullScreen;
// Добавляем в список  "соотношение сторон " типовые фильтры
видеорежимов aspectRatioComboBox.Items.Add(new AspectItem());
 aspectRatioComboBox.Items.Add(new AspectItem(4.0f / 3.0f));
aspectRatioComboBox.Items.Add(new AspectItem(5.0f / 4.0f));
 aspectRatioComboBox.Items.Add(new AspectItem(16.0f / 9.0f));
// Выбираем самый первый элемент списка ( "Любое ") 
aspectRatioComboBox.SelectedIndex = 0; }
}
Листинг 3.12.

Как видно, информация о поддерживаемых видеорежимах хранится в многомерном ассоциативном массиве, упрощающем поиск информации о требуемых видеорежимах. Например, для проверки существования видеорежима с разрешением 1024x768x32bpp:@85Hz приложение должно проверить существование элемента modeCollection[ "1024x768 "][ SurfaceFormat.Brg32][85] . Последний оператор конструктора выбирает нулевой элемент списка, генерируя событие SelectedIndexChanged, обработчик которого приведен в листинге 3.13.

// Обновляет список поддерживаемых разрешений экрана с 
учетом нового фильтра соотношения
// сторон
private void aspectRatioComboBoxSelectedIndexChanged(object 
sender, EventArgs e)
{
// Получаем текущий элемент списка  "соотношение сторон "
AspectItem aspect = (AspectItem)aspectRatioComboBox.SelectedItem;
// Текущее разрешение экрана
ResolutionItem currentResolution; 
// Используем в качестве текущего разрешения экрана элемент
 из списка  "Разрешение ". Если же 
// элемент в списке не выбран, используем разрешение
 экрана из текущих настроек приложения if 
 (resolutionComboBox.SelectedIndex != -1)
currentResolution = (ResolutionItem)resolutionComboBox.
SelectedItem; else
currentResolution = new ResolutionItem(settings.Width,
 settings.Height);
// Очищаем список разрешений экрана
resolutionComboBox.Items.Clear(); 
// Перебираем все разрешения экрана
foreach (ResolutionItem res in modeCollection.Keys) 
// Если разрешение экрана удовлетворяет заданному соотношению сторон
if (aspect.Compare(res.Aspect)) 
// Добавляем его в список разрешений
resolutionComboBox.Items.Add(res);
// Если было найдено хотя бы одно разрешение экрана, 
соответствующее заданному соотношению 
// сторон
if (resolutionComboBox.Items.Count != 0) 
{ 
// В списке разрешений экрана пытаемся выбрать текущее разрешение
resolutionComboBox.SelectedItem = currentResolution; 
// Если это не удалось, выбираем самый первый элемент списка if
 (resolutionComboBox.SelectedIndex == -1)
 resolutionComboBox.SelectedIndex = 0; }
// Вызываем обработчик события изменения состояния 
переключателя  "Визуализировать в окне ",
// который при необходимости активирует/деактивирует 
определенные элементы формы вроде кнопки
// Ok
inWindowCheckBox_CheckedChanged(inWindowCheckBox, null); 
}
// Обработчик события CheckedChange флага  "Визуализировать
 в окне ",
private void inWindowCheckBox_CheckedChanged(object sender, EventArgs e)
{
// Если флаг включен
if (inWindowCheckBox.Checked) 
{ 
// Деактивируем все списки, связанные с параметрами 
полноэкранного режима
 aspectRatioComboBox.Enabled = false; resolutionComboBox.Enabled =
 false; colorDepthComboBox.Enabled = false; refreshRateComboBox.Enabled
 = false; okButton.Enabled = true; 
}
else 
{ 
// Активируем список  "Соотношение сторон "
aspectRatioComboBox.Enabled = true; 
// Если список доступных разрешений экрана не пустой if
(resolutionComboBox.Items.Count > 0) 
{ 
// Активируем оставшиеся три списка и кнопку Ok 
resolutionComboBox.Enabled = true;
colorDepthComboBox.Enabled = true;
refreshRateComboBox.Enabled = true;
okButton.Enabled = true; 
}
else 
{ 
// В противном случае блокируем эти элементы управления
 resolutionComboBox.Enabled = false;
 colorDepthComboBox.Enabled = false;
 refreshRateComboBox.Enabled = false; okButton.Enabled =
 false; 
} 
} 
}
Листинг 3.13.

Так как выбранное разрешение оказывает влияние на доступные форматы пикселей списка "Глубина цвета ", необходимо определить обработчик события SelectedIndexChanged списка разрешений (листинг 3.14).

private void resolutionComboBoxSelectedIndexChanged(object sender, EventArgs e)
{
// Получаем выбранный элемент списка разрешений экрана
ResolutionItem res = (ResolutionItem) resolutionComboBox.SelectedItem; 
// Текущая глубина цвета
ColorDepthItem currentColorDepth; 
// Используем в качестве текущей глубины цвета 
элемент из списка  "Глубина цвета ".
Если же 
// элемент в списке не выбран, используем глубину 
цвета из текущих настроек приложения
if (colorDepthComboBox.SelectedIndex != -1)
currentColorDepth = (ColorDepthItem)colorDepthComboBox.SelectedItem;
else
currentColorDepth = new ColorDepthItem(settings.Format);
// Очищаем список  "Глубина цвета "
colorDepthComboBox.Items.Clear(); 
// Перебираем все форматы пикселей выбранного 
разрешения экрана и добавляем их в список 
//  "Глубина цвета "
foreach (ColorDepthItem colorDepth in modeCollection[res].Keys)
 colorDepthComboBox.Items.Add(colorDepth);
// Пытаемся выбрать глубину цвета, как у текущих настроек приложения
colorDepthComboBox.SelectedItem = currentColorDepth; 
// В случае неудачи выбираем первый элемент списка
if (colorDepthComboBox.SelectedIndex == -1)
 colorDepthComboBox.SelectedIndex = 0; 
}
Листинг 3.14.

Список поддерживаемых частот экрана, разумеется, тоже зависит от выбранной глубины цвета и разрешения экрана, соответственно, необходимо реализовать и обработчик события SelectedIndexChanged списка глубины цвета (листинг 3.15).

private void colorDepthComboBox_SelectedIndex
Changed(object sender, EventArgs e)
{
// Получаем выбранное разрешение и глубину цвета (формат пикселей)
ResolutionItem res = (ResolutionItem)resolutionComboBox.SelectedItem;
ColorDepthItem colorDepth = (ColorDepthItem)
colorDepthComboBox.SelectedItem;
// Текущая частота обновления экрана
RefreshRateItem currentRefreshRate; 
// Используем в качестве текущей частоты обновления 
экрана элемент из списка. Если же элемент 
// в списке не выбран, используем частоту обновления 
экрана из текущих настроек приложения if
 (refreshRateComboBox.SelectedIndex != -1)
currentRefreshRate = (RefreshRateItem)refreshRate
ComboBox.SelectedItem; else
currentRefreshRate = new RefreshRateItem(settings.RefreshRate);
// Очищаем список  "Частота обновления "
refreshRateComboBox.Items.Clear(); 
// Перебираем частоты обновления экрана, поддерживаемые 
выбранным разрешением с указанной
// глубиной цвета
foreach (RefreshRateItem refreshRate in modeCollection[res]
[colorDepth].Keys)
 refreshRateComboBox.Items.Add(refreshRate);
// Выбираем в списке  "Частота обновления " 
текущую частоту обновления экрана
refreshRateComboBox.SelectedItem = currentRefreshRate; 
// Если такого элемента нет, выбираем самый первый элемент списка
if (refreshRateComboBox.SelectedIndex == -1)
 refreshRateComboBox.SelectedIndex = 0; 
}
Листинг 3.15.

Завершая создание диалогового окна, мы должны реализовать обработчик нажатия кнопки Ok:

private void okButton_Click(object sender, EventArgs e)
{
// Обновляем настройки приложения на основе текущего 
состояния элементов управления
// формы окна
settings.FullScreen = !inWindowCheckBox.Checked;
if (!inWindowCheckBox.Checked)
{
settings.Width = ((ResolutionItem)resolutionComboBox.SelectedItem).width; 
settings.Height = ((ResolutionItem)resolutionComboBox.SelectedItem).height;
settings.Format = ((ColorDepthItem)colorDepthComboBox.SelectedItem).value;
settings.RefreshRate = ((RefreshRateItem)refreshRate
ComboBox.SelectedItem).value; 
}
// Настройки были инициализированы. При следующем показа
 диалогового окна все элементы 
// управления будут инициализированы согласно значениями 
сохраненных настроек
settings.Init = true; 
// Пользователь настроил приложение. Показывать диалоговое 
окно больше нет необходимости.
settings.ShowSettingForm = false;
DialogResult = DialogResult.OK; 
}
Листинг 3.16.
Андрей Леонов
Андрей Леонов

Reference = add reference, в висуал студия 2010 не могу найти в вкладке Solution Explorer, Microsoft.Xna.Framework. Его нету.

Олег Корсак
Олег Корсак
Латвия, Рига
Александр Петухов
Александр Петухов
Россия, Екатеринбург