Опубликован: 25.03.2010 | Доступ: свободный | Студентов: 1447 / 158 | Оценка: 4.31 / 4.00 | Длительность: 25:42:00
Лекция 12:

Классы Application и Form

Наследование форм

До сих пор мы делали все неправильно, потому, что создавали в своем классе композицию объектов Form. Поэтому мы имели возможность использовать только общедоступные ( public ) методы и свойства этого класса. Но класс Form имеет подавляющее большинство свойств и методов, доступных для наследников ( protected ). Поэтому более правильным будет подход создания нашего класса как наследника класса Form с последующим расширением его функциональности. Следует помнить, что C# поддерживает только одиночное наследование.

  • Переименуйте в панели Solution Explorer файл FirstClass в DerivedClass
  • То же самое сделайте в коде этого файла ( либо через панель Properties, предварительно выделив через Object Browser или через Class View ), переименовав имя класса в DerivedClass
  • Объявите класс DerivedClass наследующим базовому классу Form
public class DerivedClass : Form
  • Внесите изменения, чтобы класс выглядел так
using System;
using System.Windows.Forms;
using System.Drawing;
  
namespace FirstProject
{
  public class DerivedClass : Form
  {
  static void Main()
  {
  DerivedClass frm = new DerivedClass();
  frm.Text = "Наш класс - наследник от Form";
  frm.BackColor = Color.Red;
  
  Application.Run(frm);
  }
  }
}
Листинг 12.22 . Наш класс наследует от класса Form

При создании экземпляра нашего класса в функции Main() мы использовали синтаксис вызова конструктора по умолчанию. Круглые скобки в этом случае всегда обязательны при создании экземпляра класса. Но если бы мы определили в своем классе хотя бы один конструктор, то система по умолчанию нам его уже не предоставит и нужно объявлять свой конструктор по умолчанию, пусть даже с пустым телом.

using System;
using System.Windows.Forms;
using System.Drawing;
  
namespace FirstProject
{
  public class DerivedClass : Form
  {
  int width = 600, height = 300;
  
  // Общий конструктор
  public DerivedClass(int width, int height)
  {
  Width = width;
  Height = height;
  Text = "Общий конструктор";
  BackColor = Color.Red;
  }
  
  // Конструктор по умолчанию
  public DerivedClass()
  {
  Width = width;
  Height = height;
  Text = "Конструктор по умолчанию";
  BackColor = Color.Blue;
  }
  
  static void Main()
  {
  DerivedClass frm = new DerivedClass(300, 600);
  Application.Run(frm);
  }
  }
}
Листинг 12.23 . Несколько перегружаемых конструкторов

Вынесение точки входа в отдельный класс

Разгрузим функцию Main от лишнего кода, да и вынесем ее в другой класс (свой единоличный), чтобы не засорять пользовательский класс несвойственным ему кодом. Функция Main должна обязательно принадлежать какому-нибудь классу, поскольку глобальные функции в C# запрещены.

using System;
using System.Windows.Forms;
using System.Drawing;
  
namespace FirstProject
{
  public class DerivedClass : Form
  {
  public DerivedClass()// Конструктор
  {
  // Прямое обращение к свойствам класса Form
  Text = "Наследник от Form";
  BackColor = Color.Red;
  StartPosition = FormStartPosition.CenterScreen;
  this.Height /= 2; // this - удобно для  IntelliSense
  }
  }
  
  class EntryPoint
  {
  static void Main()
  {
  // Создание экземпляра и передача 
  // его в главный цикл сообщений
  // Так все и делают !!!
  Application.Run(new DerivedClass());
  }
  }
}
Листинг 12.24 . Вынесение точки входа в отдельный класс

Устранение неопределенности при нескольких точках входа

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

using System;
using System.Windows.Forms;
using System.Drawing;
  
namespace FirstProject
{
  public class DerivedClass : Form
  {
  int width = 600, height = 300;
  
  // Общий конструктор
  public DerivedClass(int width, int height)
  {
  Width = width;
  Height = height;
  Text = "Общий конструктор";
  BackColor = Color.Red;
  }
  
  // Конструктор по умолчанию
  public DerivedClass()
  {
  Width = width;
  Height = height;
  Text = "Конструктор по умолчанию";
  BackColor = Color.Blue;
  }
  
  static void Main()
  {
  // Создание экземпляра и передача 
  // его в главный цикл сообщений
  // Так все и делают !!!
  Application.Run(new DerivedClass(300, 600));
  }
  }
  
  class EntryPoint
  {
  static void Main()
  {
  // Создание экземпляра и передача 
  // его в главный цикл сообщений
  // Так все и делают !!!
  Application.Run(new DerivedClass());
  }
  }
}
Листинг 12.25 . Две точки входа в одном приложении

При запуске приложения будет ошибка о неопределенной точке входа. Теперь нужно определить, какой из классов, содержащих точки входа, будет стартовым в приложении.

  • Выполните команду главного меню оболочки Project/Properties и установите в открывшемся окне вкладки Common Properties/General параметр Startup Object в значение класса с нужной точкой входа.

Отключение консольного окна

Операционная система при запуске нашего приложения параллельно создает и консольное окно, поскольку имеет установку на то, что тип приложения является консольным. Отменим эту установку для компилятора.

  • Выполните команду главного меню оболочки Project/Properties
  • Установите параметр Output Type компилятора в значение Windows Application. Примените установку и закройте окно.

  • Запустите приложение и убедитесь, что консольное окно больше не появляется.
  • Верните таким же способом режим компилятора в значение Console Application, поскольку для испытаний средств языка C# такой режим нам еще нужен.

Переопределение стандартного обработчика, наследуемого из базового класса формы

Теперь, вместо того, чтобы самому регистрировать событие Paint и конструировать его обработчик, мы воспользуемся унаследованным от класса System.Windows.Forms.Control обработчиком OnPaint(),который вызывается формой автоматически при разрушении ее вида. Мы хотим контролировать этот обработчик своим кодом. В базовом классе этот обработчик объявлен виртуальным ( virtual ), поэтому его нужно переопределить в наследнике с ключевым словом override.

using System;
using System.Windows.Forms;
using System.Drawing;
  
namespace FirstProject
{
  public class DerivedClass : Form
  {
  public DerivedClass()// Конструктор
  {
  // Прямое обращение к свойствам класса Form
  Text = "Переопределение наследуемого "
       + "обработчика OnPaint";
  BackColor = Color.Blue;// Синий фон
  StartPosition = FormStartPosition.CenterScreen;
  // this - удобнее для вызова IntelliSense
  this.Height /= 2; 
  this.Width *= 2;
  }
  
  // Замещающий метод обработки события Paint
  // Переопределение наследуемого обработчика OnPaint()
  protected override void OnPaint(PaintEventArgs e) // Набрать вручную !!!
  {
  System.Drawing.Graphics gr = e.Graphics;
  System.String str = "Привет из замещенного "
       + "обработчика OnPaint";
  System.Int32 x = 0, y = 0; // то же, что int - псевдоним
    gr.DrawString(str, Font, // Применить как у владельца (формы)
    Brushes.White, // Белый текст
    x, y); // Привязка текста к клиентской области
  Console.WriteLine("Сработал замещенный "
          + "обработчик OnPaint");
  
  // Обработчик базового класса
  base.OnPaint (e);
  }
  }
  
  class EntryPoint
  {
  static void Main()
  {
  // Создание экземпляра и передача 
  // его в главный цикл сообщений
  // Так все и делают !!!
  Application.Run(new DerivedClass());
  }
  }
}
Листинг 12.26 . Переопределение наследуемого обработчика OnPaint()
Максим Филатов
Максим Филатов

Прошел курс. Получил код Dreamspark. Ввожу код на сайте, пишет:

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

 

Как активировать код?