Некоторые методы и свойства
public MainMenu(); - конструктор для создания меню без элементов
public MainMenu(MenuItem[] items); - конструктор для создания меню с набором элементов.
public Menu.MenuItemCollection MenuItems {get;} - получение коллекции элементов, ассоциированных с меню.
public virtual MainMenu CloneMenu(); - создание копии текущего меню
public Form GetForm(); - получение формы, содержащей меню (null - в случае отсутствия таковой).
public virtual void MergeMenu(Menu menuSrc); - слияние меню
public MenuItem(string text, EventHandler onClick, Shortcut shortcut); - конструктор для создания пункта меню.
text - заголовок пункта
onClick - обработчик выбора пункта меню
shortcut - акселератор (горячая клавиша для выбора пункта меню).
Практический пример. Игра "Пятнашки".
Данная программа создана для демонстрации работы с Windows Forms.
<исходники> ..\Program\Applications\Game
using System;
using System.Drawing;
using System.Windows.Forms;
namespace CSharpApplication.WindowsApplicationExample
{
// Игра "Пятнашки"
class Game : Form
{
// Размер стороны поля, если изменить игра станет более веселой :)
const int Side = 4;
// Номер "пустышки"
const int Void = Side * Side;
// Начальные координаты пустышки
int Voidx = Side - 1, Voidy = Side - 1;
// Массив кнопок
Button [,] Field;
// Массив значений кнопок
int [,] Numbers;
// Количество проделанных ходов
int Moves;
// Индикатор запуска игры
bool IsGameRun;
// Надпись для отображения прошедшего времени
Label clock = new Label();
// Объект таймера
Timer timer = new Timer();
// Инициализация генератора случайных чисел
Random Randomize = new Random();
// Время игры
TimeSpan time;
static void Main()
{
// Запуск приложения
Application.Run(new Game());
}
// Конструктор - инициализация игры
Game()
{
// Заголовок формы
Text = "Пятнашки";
// Стиль рамки для формы
FormBorderStyle = FormBorderStyle.Fixed3D;
// Выключение кнопки для развертывания окна
MaximizeBox = false;
// Вычисление размера клиентской области окна
ClientSize = new Size(Side * 50 + 20, Side * 50 + 50);
// Цвет фона
BackColor = Color.Silver;
// Массив кнопок
Field = new Button[Side, Side];
// Массив чисел
Numbers = new int[Side, Side];
/*************************************************************/
/* Добавление пунктов меню
/*************************************************************/
MenuItem miNewGame = new MenuItem("Новая игра",
new EventHandler(OnMenuStart), Shortcut.F2);
MenuItem miSeparator = new MenuItem("-");
MenuItem miExit = new MenuItem("Выход",
new EventHandler(OnMenuExit), Shortcut.CtrlX);
MenuItem miGame = new MenuItem("&Игра",
new MenuItem[] {miNewGame, miSeparator, miExit});
// Создание меню и его привязка к форме
Menu = new MainMenu(new MenuItem[] {miGame});
// Игра не запущена
IsGameRun = false;
// Таймер будет срабатывать каждую секунду
timer.Interval = 1000;
// Подключение обработчика таймера
timer.Tick += new EventHandler(OnTimer);
// Размещение надписи
clock.Location = new Point(10, 10);
// Ширина надписи
clock.Width = Side * 50;
// Высота надписи
clock.Height = 20;
// Родитель надписи (форма)
clock.Parent = this;
// Тонкая рамка
clock.BorderStyle = BorderStyle.FixedSingle;
// Цвет фона
clock.BackColor = Color.DarkGray;
// Текст выравнивается по центру надписи
clock.TextAlign = ContentAlignment.MiddleCenter;
// Шифт надписи
clock.Font = new Font("Century", 14, FontStyle.Bold);
// Текст надписи
clock.Text = "00:00:00";
int i, j;
// Инициализация поля
for(i = 0; i < Side; i++)
{
for(j = 0; j < Side; j++)
{
// Создание новой кнопки
Field[i, j] = new Button();
// Указываем родителя для кнопки (форма)
Field[i, j].Parent = this;
// Задаем очередное число
Numbers[i, j] = i * Side + j + 1;
// Если не "пустышка"
if(Numbers[i, j] != Void)
// Отображаем число на кнопке
Field[i, j].Text = Convert.ToString(Numbers[i, j]);
// Вычисляем координаты очередной кнопки
Field[i, j].Left = 10 + j * 50;
Field[i, j].Top = 40 + i * 50;
Field[i, j].Width = 50;
Field[i, j].Height = 50;
// Шрифт кнопки
Field[i, j].Font = new Font("Century", 12, FontStyle.Bold);
// Ассоциируем с кнопкой ее координаты в массиве
Field[i, j].Tag = new Point(i, j);
// Добавляем обработчик нажатия на кнопку
Field[i, j].Click += new EventHandler(OnCellClick);
// Цвет текста
Field[i, j].ForeColor = Color.Yellow;
// Цвет фона
Field[i, j].BackColor = Color.Gray;
}
}
// Отображаем форму по центру экрана
CenterToScreen();
}
// Обработчик пункта меню "Выход"
void OnMenuExit(object obj, EventArgs ea)
{
// Закрываем форму
Close();
}
// Обработчик пункта меню "Новая игра"
void OnMenuStart(object obj, EventArgs ea)
{
int i, j, k;
int direction;
/************************/
/* Перемешивание поля
/************************/
int Times = Side * 100;
for(k = 0; k < Times; k++)
{
// Направление движения
direction = Randomize.Next(4);
if(direction == 0) // Вверх
{
// Кнопка сверху существует
if(Voidx - 1 >= 0)
{
Numbers[Voidx, Voidy] = Numbers[Voidx - 1, Voidy];
Voidx--;
}
else
{
for(i = 0; i < Side - 1; i++)
{
Numbers[i, Voidy] = Numbers[i + 1, Voidy];
}
Voidx = Side - 1;
}
}
else if(direction == 1) // Вниз
{
// Кнопка снизу существует
if(Voidx + 1 < Side)
{
Numbers[Voidx, Voidy] = Numbers[Voidx + 1, Voidy];
Voidx++;
}
else
{
for(i = Side - 1; i > 0; i--)
{
Numbers[i, Voidy] = Numbers[i - 1, Voidy];
}
Voidx = 0;
}
}
else if(direction == 2) // Влево
{
// Кнопка слева существует
if(Voidy - 1 >= 0)
{
Numbers[Voidx, Voidy] = Numbers[Voidx, Voidy - 1];
Voidy--;
}
else
{
for(j = 0; j < Side - 1; j++)
{
Numbers[Voidx, j] = Numbers[Voidx, j + 1];
}
Voidy = Side - 1;
}
}
else // Вправо
{
// Кнопка справа существует
if(Voidy + 1 < Side)
{
Numbers[Voidx, Voidy] = Numbers[Voidx, Voidy + 1];
Voidy++;
}
else
{
for(j = Side - 1; j > 0; j--)
{
Numbers[Voidx, j] = Numbers[Voidx, j - 1];
}
Voidy = 0;
}
}
// Новая позиция "пустышки"
Numbers[Voidx, Voidy] = Void;
}
// Отображение перемешанных чисел на кнопках
for(i = 0; i < Side; i++)
{
for(j = 0; j < Side; j++)
{
if(Numbers[i, j] != Void)
{
Field[i, j].Text = Convert.ToString(Numbers[i, j]);
}
else
{
Field[i, j].Text = "";
}
}
}
Moves = 0;
// Игра запущена
IsGameRun = true;
// Начальное время
time = new TimeSpan(0, 0, 0);
clock.Text = "00:00:00";
// Запуск таймера
timer.Start();
}
// Обработчик нажатия кнопки (ход)
void OnCellClick(object obj, EventArgs ea)
{
// Если игра не запущена
if(IsGameRun == false)
return;
// Вынимаем "нажатый" объект
Button btn = (Button)obj;
// Определяем его месторасположение в массиве
// по ассоциированным координатам
int i = ((Point)btn.Tag).X;
int j = ((Point)btn.Tag).Y;
// Если нажатая кнопка расположена
// слева, или снизу, или справа, или сверху от "пустышки"
if(Math.Abs(i - Voidx) + Math.Abs(j - Voidy) == 1)
{
// Ход
Numbers[Voidx, Voidy] = Numbers[i, j];
Field[Voidx, Voidy].Text = Field[i, j].Text;
// Новые координаты "пустышки"
Voidx = i;
Voidy = j;
Numbers[Voidx, Voidy] = Void;
Field[Voidx, Voidy].Text = "";
// Ход сделан
Moves++;
}
// Если "пустышка" в нижнем правом углу
if(Voidx == Side - 1 && Voidy == Side - 1)
{
// Если победа
if(IsWinner() == true)
{
// Остановка таймера
timer.Stop();
string msg = "Поздравляем!!!\nВы достигли успеха за ";
msg += Moves;
if(Moves % 10 > 1 && Moves % 10 < 5 && Moves % 100 / 10 != 1)
msg += " хода.";
else if(Moves % 10 == 1 && Moves % 100 / 10 != 1)
msg += " ход.";
else
msg += " ходов.";
// Остановка игры
IsGameRun = false;
// Отображение информационного окна
MessageBox.Show(msg, "Победа!!!",
MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
}
}
}
// Определение выигрышной позиции
bool IsWinner()
{
int i, j, k = 1;
for(i = 0; i < Side; i++)
{
for(j = 0; j < Side; j++)
{
// Если очередное число не совпадает с порядковым
if(Numbers[i, j] != k)
return false;
k++;
}
}
// Выигрыш
return true;
}
// Обработчик событий таймера
void OnTimer(object obj, EventArgs ea)
{
// Увеличиваем время на секунду
time += new TimeSpan(0, 0, 1);
// Отображаем полученное время
clock.Text = time.ToString();
}
// Обработчик активизации формы (получение фокуса приложением)
protected override void OnActivated(EventArgs ea)
{
// Вызов базового обработчика
base.OnActivated(ea);
// Если игра запущена
if(IsGameRun == true)
// Запуск таймера
timer.Start();
}
// Обработчик деактивизации формы (потеря фокуса приложением)
protected override void OnDeactivate(EventArgs ea)
{
// Вызов базового обработчика
base.OnDeactivate(ea);
// Если игра запущена
if(IsGameRun == true)
// Остановка таймера
timer.Stop();
}
}
}