Жанр: Учеба
Си шарп: создание приложений для windows
... с СОМ, отказ от поддержки RMI и JNI и введение
делегатов - привели к нарушению совместимости со стандартом Java.
Вследствие этого Sun Microsystems предъявило иск Microsoft в октябре
1997 года за нарушение лицензионного соглашения. Это был приговор
будущему разработок Java и Visual J++ компании Microsoft. Но в Microsoft
решили использовать наработки в Java, компиляторах и JVM и преобразовать
их в еще более амбициозный проект - Microsoft .NET.
Программы, написанные на С#, компилируются в промежуточный язык
под названием "MSIL", с некоторой натяжкой его можно назвать эквивалентом
байт-кода или р-кода Visual Basic. Как уже говорилось ранее,
любой язык, который можно скомпилировать во MSIL, может воспользоваться
такими возможностями CLR, как сборка мусора, отражения, метаданные,
контроль версий, события и защита. Кроме этого, класс, написанный
на одном языке, может наследовать от класса на другом языке и
подменять его методы.
Интересно, что Microsoft продвигает кросс-языковую разработку, a Sun/
Java - кросс-платформную.
К сожалению, и у того, и у другого подхода есть свои недостатки.
Создание компонент на нескольких языках всегда влечет за собой проблемы
взаимодействия. Более того, всегда есть проблема -что делать,
когда ваш программист-постановщик задач найдет местечко потеплее.
Кросс-платформная разработка тоже никогда не была безупречна, как
знают Java-программисты, особенно в части GUI и потоков.
362 Раздел I I I . Программирование для Windows
СХОДСТВО С# И Java
Не говоря о множестве других общих черт, большинство ключевых
слов в Java имеют соответствия в С#. Некоторые ключевые слова совпадают,
например, new, bool, this, break, static, class, throw, virtual и null. Этого
можно было ожидать, поскольку данные ключевые слова заимствованы
из C++. Занимательно, что многие ключевые слова Java, не имеющие
прямых эквивалентов в С#, например, super, import, package, synchronized
и final, просто называются по-другому в С# (base, using, namespace, lock и
sealed, соответственно). Ниже в таблице приведены некоторые ключевые
слова и черты, существующие в обоих языках, но выглядящие слегка
иначе в С#.
Наследование
Ссылка
на базовый класс
Использование
внешних типов
Java
class Foo extends Bar
implements IFooBar { }
super.hashCode ();
import Java.util;
c#
class
base.
usin?
Foo: Bar, IFooBar { }
GetHashCode ();
I System.Net;
Пространства
имен
package MyStuff;
class MyClass { }
namespace MyStuff
{
class MyClass {...}
Предотвращение
наследования
Константы
final
final
class
static
Foo
int
{}
MAX - 50;
sealed
const
class Foo
int MAX =
U
= 50;
Комментарии /**
* Convert string to
* uppercase.
*
* @param s The string to
* convert
*
* ©return The uppercase
* string
/// "summary"
/// Convert string to
/// uppercase.
/// "/summary"
/// "param name-"s""
/// The string to convert
/// "/param"
/// "returns"
/// The uppercase string
/// "/returns"
Устаревшие,
не рекомендуемые
к использованию
классы или методы
©deprecated He использовать! [obsolete ("He использовать!")]
Синхронизация synchronized (this) { ++ refs; } lock (this) { ++ refs; }
Так что же лучше, С# или Java? 363
КЛАСС Object
Другой хороший пример косметических различий двух языков - класс
System.Object в С#, имеющий точно те же методы, что и Java-класс
Java.long.Object, если не считать того, что они несколько иначе пишутся.
Метод clone в Java называется MemberwiseClone в С#, equals из
Java - это Equals в С#, getClass - getType, hashCode - GetHashCode, a
toString - ToString.
Простое совпадение? Да, в недавнем интервью Андерс Хиджисберг говорил,
что "С# - это не клон Java". Совершенно верно, это MemberwiseClone.
МОДИФИКАТОРЫ ДОСТУПА
В отличие от C++, в С# модификатор public и ему подобные относятся
к одному определению (метода, класса, переменной) наподобие того, как
это сделано в Java. Модификаторы public и private имеют одно и то же
значение во всех трех языках. Но "protected access" в Java называется
"protected internal" в С#, a "package access" в Java называется "internal"
в С#. Модификатор protected в С# дает наследникам доступ к членам
класса, даже если наследники находятся в другой программе. Другое
различие - в Java по умолчанию применяется package access, а в С# -
private.
ЧТО В С# ЛУЧШЕ, ЧЕМ В Java
Итак, если С# и Java во многом выглядят и действуют похоже, зачем
же вообще использовать С#? Как и следует ожидать от очередного
языка, С# совершеннее Java в некоторых областях. В дополнение к
появившимся новым возможностям, в С# проще синтаксис для таких
вещей, как итерации, события и работа с примитивными типами вроде
объектов и т. п., что уменьшает количество кода и ускоряет процесс
разработки.
КОНТРОЛЬ ВЕРСИИ
Контроль версий - очень нужная в Windows- и Java-разработке вещь.
Java-разработчики не хуже остальных знакомы с устаревшими API и
несовместимыми версиями сериализованных объектов.
.NET в очередной раз обещает устранить эти проблемы, позволяя указать
зависимости версий между компонентами и поддержкой одновременного
исполнения нескольких версий компонента. Более того, на ком364
Раздел I I I . Программирование для Windows
пьютере может иметься несколько версий runtime .NET одновременно,
что позволяет использовать в каждом случае ту версию, под которую компилировались
компоненты. Это похоже на возможности контроля версий,
оговоренные в Java Product Versioning Specification, за исключением того,
что в .NET Framework принудительный контроль во время исполнения,
компиляции и инсталляции уже встроен.
СРЕДСТВА ОТЛАДКИ ВО ВРЕМЯ ИСПОЛНЕНИЯ
Как уже говорилось, среди стандартных библиотек CLR присутствует
библиотека, дающая возможности runtime-отладки - вывода сообщения
в консоль, выдачи Assert и т. п. Естественно, С# предоставляет полный
доступ к этим возможностям, как, впрочем, и любой другой CLR-совместимый
язык.
Assert не поддерживаются в Java, но, как и над большинством других
недоработок, в Java Community Process над этим работают.
ref- И out-ПАРАМЕТРЫ
В С# параметры можно передавать по значению (in), по ссылке (ref),
или указывать, что это - выходные параметры (out). Так как Java позволяет
только передачу по значению, для передачи в метод чего-либо по
ссылке приходится заниматься натуральным шаманством, например, использовать
возвращаемые значения, передачу в одноэлементном массиве
или помещение объекта в класс-обертку. Метод, принимающий параметр
по ссылке в С#:
void swap (ref long nl, ref long n2| ;
Вызов С#-метода:
int i l - 123, 12 - 321;
swap ( i l , i2);
Аналогичный пример на Java:
void swap (long[] nl, long[] n2);
Вызов java-метода:
int il = 123, 12 = 321;
int[1] itmpl;
itmpl = il;
int [1] icmp2;
itmp2 = 12;
swap {itmpl, itmp2);
Необходимо снова подчеркнуть, что возможность определения параметров
методов как прямых, передающихся по ссылке или обратно возвращаемых,
заложена на уровне CLR, а конкретные языки только предоставляют
некоторый синтаксис, позволяющий воспользоваться этими
возможностями.
Так что же лучше, С# или Java? 365
ВИРТУАЛЬНЫЕ МЕТОДЫ
По умолчанию, в Java все методы виртуальны и могут подменяться
наследниками класса. С# более привержен традициям. В нем, как и в
C++, виртуальные методы должны быть явно объявлены виртуальными.
Более того, С# несколько улучшает модель декларации виртуальных
методов, заставляя программиста явно указывать, что он хочет подменить
реализацию базового класса. Это позволяет избежать трудноуловимых
ошибок, часто встречающихся в C++- и Java-программах. Например,
стоит в C++ при подмене методов неумышленно изменить сигнатуру
метода базового класса (описать параметр как long вместо int), и вместо
ожидаемого переопределения метода вы создадите дополнительную (перегруженную)
реализацию метода. При этом базовый класс будет вызывать
свою реализацию. Программист может часами смотреть на место,
где допущена ошибка, и не видеть ее. С# интерпретирует неявную перегрузку
как ошибку компиляции, требуя от производного класса использовать
ключевое слово override для подмены виртуального метода. Кроме
этого, при компиляции выдается предупреждение, если метод производного
класса скрывает метод базового класса. В этом случае, чтобы убрать
предупреждение, можно использовать ключевое слово new.
ПЕРЕЧИСЛЕНИЯ (enums)
В отличие от C/C++, в Java не реализованы перечисления, так как создатели
Java заявили, что перечисления не объектно-ориентированы. По
правде говоря, enums куда безопаснее и удобнее, чем static final int в Java.
Перечисления не только существуют в С#, они типо-безопасны, к ним можно
применять операторы ++, -, ", и " и конвертировать в строку и обратно.
ТИП ДАННЫХ decimal
В С# поддерживается типы данных decimal, пришедший в CLR из
Automation и Visual Basic, decimal -128-битный тип, имеющий большую
точность и меньший разброс, чем типы с плавающей точкой. Он особенно
полезен для финансовых приложений.
ВЫРАЖЕНИЯ switch
Очень распространенной ошибкой С/С++-программистов, особенно
начинающих, является пропущенный оператор break в конце раздела case
оператора switch. Программист подсознательно считает, что в конце раздела
case управление должно быть прервано и продолжиться после one366
Раздел I I I . Программирование для Windows
ратора switch. Но в C++ это не так, причем умышленно - чтобы позволить
программисту создать один раздел с несколькими метками. В других
языках обычно применяется перечисление меток через запятую в
одном case-операторе. В 90 процентах случаев это удовлетворяет имеющимся
потребностям, но реализация C++ более гибка. Разработчики С#
нашли довольно красивое альтернативное решение.
По умолчанию при достижении конца case-раздела происходит выход
из оператора switch. Чтобы достичь такой же функциональности,
как в C++, можно применять оператор goto. В качестве меток используются
соответствующие case-метки. Кроме того, с С# как метки можно
использовать не только целые числа, но и строки (прямое заимствование
из VB).
ДЕЛЕГАТЫ И СОБЫТИЯ
Делегаты - это объектно-ориентированные аналоги указателей на
функции, предоставляющие типо-безопасный механизм для реализации
функций обратного вызова и событий. Они могут указывать на статические
методы или на нормальные методы класса. Эта возможность также
является не особенностью языка, а унаследована от CLR, но именно в С#
она наиболее органично встроена в язык.
Java работает с событиями через модель событий JavaBeans и классыадаптеры.
Обработка событий в С# проще и требует только реализовать
индивидуальные методы вместо целых интерфейсов.
Как видно из этой главы, прямым предком С# был Visual J++. Именно
в нем появились так называемые делегаты и сама концепция делегирования.
Именно эта замечательная возможность стала каплей, переполнившей
чашу терпения Sun Microsystems. Как вы думаете, в каком смертном
грехе Sun обвинил делегаты? Правильно, делегаты не объектноориентированны.
Ключевое слово event вводит в ваш класс делегата,
позволяющего рассылать события.
ПРОСТЫЕ ТИПЫ (Value-ТИПЫ)
Как говорилось выше, все типы данных, поддерживаемые CLR, наследуются
от базового класса object. Поэтому простые типы в С# (long, int,
char) можно использовать везде, где необходима передача ссылки на
объект. Java в данном случае проигрывает, поскольку простые типы в
ней не рассматриваются как классы и в некоторых контекстах для работы
с ростыми типами их приходится заворачивать в специальные классы-обертки,
например, java.lang.Long. С#-компилятор неявно конвертирует
простые типы в объекты (и наоборот) по потребности, через процесс
под названием "упаковка и распаковка (boxing и un-boxing)". Причем если
простые типы не рассматриваются как объекты, это не влечет никаких
Так что же лучше, С# или Java? 367
накладных расходов. Это позволяет С#-разработчикам смотреть на мир
как на целостную систему типов. Ниже показан пример использования
простых типов как объектов на Java:
int i = 10;
System.out.println((new Integer(i)) .hashCode() I ; // Используется класс-обертка
А вот так это выглядит на С#:
int i = 10;
System.Console.WriteLine[i.GetHashCode()); // Скрытая конвертация
СВОЙСТВА
Хотя во многих языках свойства и поля выглядят одинаково, реально
свойства и поля - это две большие разницы. Поле - это член данных
класса, а свойство - это пара методов получения и предоставления доступа,
предоставляющих доступ или вычисляющих нужные значения.
И С#, и Java (посредством JavaBeans) поддерживают работу со свойствами.
Однако в С# свойства напрямую поддерживаются языком вместо
использования отражений и соглашений именования, как в JavaBeans.
Это дает краткий, легко читаемый синтаксис. Приведенный ниже пример
показывает реализацию свойства Name с использованием поля name
на Java:
String name;
public String getNamef) ( return name; }
public void setName(String value) { name = value; }
Использование свойства:
obj.setName ("Marc");
if (obj.getName() != "Marc")
throw new Exception("Это не я!");
и на С#:
string name;
public string Name
{
get ( return name; )
set { name = value; ) // 'value'-это новое значение
1
Использование свойства:
obj.Name = "Marc";
if (obj.Name != "Marc")
throw new System.Exception ("Это не я!");
Преимущества стиля С# в том, что методы get и set находятся в том
же блоке кода и в том, что для обращения к свойствам используется
более интуитивный синтаксис, поскольку доступ к свойствам производится
точно так же, как к нормальным полям. Свойства JavaBeans тоже
выглядят как нормальные поля, когда к ним обращаются из скриптов
или визуальных дизайнеров, но не при доступе из Java-кода.
368 Раздел I I I . Программирование для Windows
ИНДЕКСИРУЕМЫЕ СВОЙСТВА
И СВОЙСТВА ПО УМОЛЧАНИЮ
Кроме переопределения операторов, в С# можно определять индексируемые
свойства. К тому же, индексируемые свойства можно помечать
как свойства по умолчанию для класса. Это позволяет рассматривать
объект как массив, каждый элемент которого становится доступным с
помощью операторов доступа к свойствам (get и set). Ниже приведен
пример класса с индексированным свойством по умолчанию:
public class Skyscraper
{
Story[] stories;
public Story this [int index]
{
get ( return stories [index]; }
set
{
if (value != null)
stories [index] = value;
Применение класса с индексированным свойством по умолчанию:
Skyscraper empireState = new Skyscraper (...);
empireState[102] = new Story ("The Top One",... );
МАССИВЫ, КОЛЛЕКЦИИ И ИТЕРАЦИИ
Выражение foreach в С# (украденное из VB) позволяет легко перечислять
классы, поддерживающие интерфейс Enumerable, включающий массивы
и коллекции. Это избавляет от необходимости писать for (int i=0; i
" ary.length;i++) и триаду getlterator/hasNext/next как в Java и C++.
Следующий листинг демонстрирует итерации на Java:
import java.util.*;
class Iterate
{
public static void main (String [] args)
{
// Перебор массива аргументов командной строки
for (int i = 0; i " args.length; i++)
System.out.printIn(args [i]);
// Создание связанного списка
Так что же лучше, С# или Java? 369
LinkedList list = new LinkedListf);
list.add ("Элемент 1");
list.add ("Элемент 2") ;
// Перебор значений списка
Listlterator it = list.listlterator (0);
while (it.hasNext())
System.out.println (it.next |));
И на С#:
using System.Collections;
class Iterate
Посмотри в окно!
Чтобы сохранить великий дар природы — зрение,
врачи рекомендуют читать непрерывно не более 45–50 минут,
а потом делать перерыв для ослабления мышц глаза.
В перерывах между чтением полезны
гимнастические упражнения: переключение зрения с ближней точки на более дальнюю.
public static void Main(string [] args]
f
// Перебор массива аргументов командной строки
foreach (string arg in args)
System.Console.WriteLine (arg);
// Создание связанного списка
ObjectList list = new ObjectList ();
list.Add("Элемент 1");
list.Add("Элемент 2");
// Перебор значений списка
foreach (string str in list)
System.Console.WriteLine (str);
ИНТЕРФЕЙСЫ
Интерфейсы С# похожи на интерфейсы Java, но С# дает большую
гибкость при их использовании. Класс может реализовать методы интерфейса
явно или неявно:
public interface ITeller
(
void Next ();
public interface Ilterator
{
void Next ();
370 Раздел I I I . Программирование для Windows
public class Clark: I Те Her, lite rat or
\
void ITeller.Next () {... }
void Ilterator.Next () (... }
Это дает классу двойную выгоду. Во-первых, класс может реализовать
несколько интерфейсов, не беспокоясь о конфликтах имен. Во-вторых,
класс может "спрятать" метод, если он не должен быть доступен всем
пользователям класса. Чтобы получить доступ к методам, при реализации
которых было явно указано имя интерфейса, необходимо использовать
явное приведение типов:
Clark clark - new Clark ();
( (ITeller)clark) .Next(};
МНОГОМЕРНЫЕ МАССИВЫ
C# позволяет создавать как вложенные, так и многомерные массивы.
Вложенные массивы очень похожи на реализацию массивов в C++ и Java.
Многомерные массивы обеспечивают более точное и эффективное решение
некоторых задач. Пример такого массива:
inn [,,] array = new int [3, 4, 5]; // creates 1 array
int [1, 1,1] = 5;
Использование вложенных массивов:
i n t [ ] [ ] [ ] array = new i n t [ 3 ] [ 4 ] [ 5 ] ; // c r e a t e s 1+3+12=16 a r r a y s
i n t [1] [1] [1] = 5;
ПРИЛОЖЕНИЕ
Полный листинг программы "Графический редактор"
Файл Forml.cs
using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;
namespace GraphEditorApp
public enum Tools
{
PEN = 1, TEXT, LINE, ELLIPSE, NONE = 0
}
/// "summary"
/// Summary description for Forml.
/// "/summary"
public class Forml: System.Windows.Forms.Form
{
public Tools currentTool;
private System.Windows.Forms.ToolBar toolBarl;
private System.Windows.Forms.ImageList imageListl;
private System.Windows.Forms.ToolBarButton tooIBarButtonPen;
private System.Windows.Forms.ToolBarButton tooIBarButtonLine;
private System.Windows.Forms.ToolBarButton toolBarButtonElXipse;
private System.Windows.Forms.MainMenu mainMenul;
private System.Windows.Forms.MenuItern menuItemFile;
private System.Windows.Forms.MenuItern menuItemNew;
privace System.Windows.Forms.MenuItern menuItemClose;
private System.Windows.Forms.MenuItern menuItemWindow;
private System.Windows.Forms.MenuItern menuItemTool;
private System.Windows.Forms.Menultem menuItemPen;
priva-e System.Windows.Forms.Menultem menuItemLine;
private System.Windows.Forms.Menultem menuItemEllipse;
priva-e System.Windows.Forms.ToolBarButton toolBarButtonText;
private System.Windows.Forms.Menultem menuItemText;
372 Приложение
private System.ComponentModel.IContainer components;
public Forral ()
(
//
// Required for Windows Form Designer support
//
InitializeComponent();
//
// TODO: Add any constructor code after InitializeComponent call
/// "summary"
/// Clean up any resources being used.
/// "/summary"
protected override void Dispose( bool disposing
{
if( disposing )
{
if (components != null)
{
components.Dispose() ;
)
base.Dispose( disposing );
tregion windows Form Designer generated code
/// "survimary"
/// Required method for Designer support--do nor modify
/// the contents of this method with the code editor.
/// "/summary"
private void InitializeComponent{)
{
this.components = new System.ComponentModel.Container();
System.Resources.ResourceManager resources = new
System.Resources.ResourceManager(typeof(Forml));
this.toolBarl - new System.Windows.Forms.ToolBar();
this.toolBarButtonPen = new System.Windows.Forms.ToolBarButton (};
this.toolBarButtonText = new System.Windows.Forms.ToolBarButton();
this.toolBarButtonLine - new System.Windows.Forms.ToolBarButton();
this.toolBarButtonEllipse - new System.Windows.Forms.ToolBarButton ();
this.imageListl = new System.Windows.Forms.ImageList(this.components)
this.mainMenul = new System.Windows.Forms.MainMenu();
Приложение 373
this.menuItemFile = new System.Windows.Forms.Menultem();
this.menuItemNew = new System.Windows.Forms.Menultem();
this.menuItemClose = new System.Windows.Forms.Menultem();
this.menuItemTool = new System.Windows.Forms.Menultem();
this.menuItemPen = new System.Windows.Forms.Menultem();
this.menultemText = new System.Windows.Forms.Menultem();
this.menuItemLine = new System.Windows.Forms.MenuItem();
this.menuItemEIlipse = new System.Windows.Forms.Menultem();
this.menuItemWindow - new System.Windows.Forms.Menultem(1;
this.SuspendLayout();
// toolBarl
this.toolBarl.Buttons.AddRange(new System.Windows.Forms.ToolBarButton[
this.toolBarButtonPen,
this.toolBarButtonText,
this.tOOlBarButtonLine,
this.toolBarButtonEllipse});
this.toolBarl.DropDownArrows = true;
this.toolBarl.ImageList - this.imageListl;
this.toolBarl.Name = "toolBarl";
this.toolBarl.ShowToolTips = true;
this.toolBarl.Size = new System.Drawing.Size(292, 25);
this.toolBarl.Tablndex = 0;
this .toolBarl .ButtonClick н-= new
System.Windows.Forms.ToolBarButtonClickEventHandler(this.toolBarl_ButtonClick)
//
// toolBarButtonPen
//
this.toolBarButtonPen.Imagelndex = 0;
this.toolBarButtonPen.Style =
System.Windows.Forms.ToolBarButtonStyle.ToggleButton;
//
// toolBarButtonText
//
this.toolBarButtonText.Imagelndex - 1;
this.toolBarButtonText.Style ^
System.Windows.Forms.ToolBarButtonStyle.ToggleButton;
374 Приложение
// toolBarButtonLine
//
this.toolBarButtonLine.ImageIndex - 2;
this.toolBarButtonLine.Style =
System.Windows.Forms.ToolBarButtonStyle.ToggleButton;
//
// toolBarButtonEllipse
//
this.toolBarButtonEllipse.Imagelndex = 3;
this.toolBarButtonEllipse.Style =
System.Windows.Forms.ToolBarButtonStyle.ToggleButton;
//
// imageListl
//
this.imageListl.ColorDepth = System.Windows.Forms.ColorDepth.Depth8Bit;
this.imageListl.ImageSize - new System.Drawing.Size(16, 16);
this.imageListl.ImageStream =
((System.Windows.Forms.ImageListStreamer) (resources.GetObject f"imageListl.ImageStream")))
this.imageListl.TransparentColor = System.Drawing.Color.Transparent;
//
// mainMenul
//
this.mainMenul.MenuIterns.AddRange(new System.Windows.Forms.Menultem[] {
this.menuItemFile,
this.menuItemTool,
this .ir.enuItemWindow]) ;
// menuItemFile
this.menuItemFile.Index = 0;
this.menuItemFile.MenuItems.AddRange(new System.Windows.Forms.MenuItern[]
this.menuItemNew,
this.menuItemClose});
this.menuItemFile.Text = "&Файл";
Приложение 375
// menuItemNew
//
this.menuItemNew.Index = 0;
this.menuItemNew.Text = "&Создать";
this .menuItemNew.Click н-= new
System.EventHandler(this.menuItemNew Click) ;
//
// menuItemClose
//
this .menuItemClose . Index =• 1 ;
this.menuItemClose.Text = "йЗакрыть";
//
// menuItemTool
//
this.menuItemTool.Index = 1;
this.menuItemTool.Menultems.AddRange(new System.Windows.Forms.MenuItern[
this.menuItemPen,
this.menuItemText,
this.menuItemLine,
this.menuItemEllipse)) ;
this .menuItemTool. Text = "{.Инструмент"
//
// menuItemPen
//
this.menuItemPen.Index = 0;
this.menuItemPen.Text = "&Карандаш";
this.menuItemPen.Click += new
System.EventHandler(this.menuItemTool_ Click)
//
// menuItemText
//
this.menuItemText.Index = 1;
this.menuItemText.Text = "бТекст";
this.menuItemText.Click +- new
System.EventHandler(this.menuItemTool_Click)
376 Приложение
// menuItemLine
//
this.menuItemLine.Index = 2;
this.menuItemLine.Text = "&Линия";
this.menuItemLine.Click +^ new
System.EventHandler(this.menuItemTool_Click);
//
// menuItemEllipse
//
this.menuItemEllipse.Index = 3;
this.menuItemEllipse.Text = "sЭллипс";
this.menuItemEllipse.Click += new
System.EventHandler(this.menuItemTool_Click) ;
//
// menuItemWindow
//
this.menuItemWindow.Index - 2;
this.menuItemWindow.MdiList ^ true;
this.menuItemWindow.Text = "&Окно";
//
// Forml
//
this.AutoScaleBaseSize - new System.Drawing.Size(5, 13);
this.ClientSize - new System.Drawing.Size(292, 273);
this.Controls.AddRange(new System.Windows.Forms.Control[] {
this.toolBarl});
this.IsMdiContainer = true;
rhis.Menu = this.mainMenul;
this.Name = "Forml";
this.Text = "Графический редактор";
this.ResumeLayout (false);
tendregion
/// "summary"
'/// The main entry point for the application.
/// "/summary"
[STAThread]
static void Main()
f
Application.Run(new Forml());
private void toolBarl_ButtonClick(object sender.
Приложение 377
System.Windows.Forms.ToolBarButtonClickEventArgs e)
switch(e.Button.ImageIndex)
case 0:
// установка режима рисования карандашом
currentTool - Tools.PEN;
break;
case 1:
// установка режима заливки
currentTool - Tools.TEXT;
break;
case 2:
// установка режима рисования линий
currentTool ^ Tools.LINE;
break;
case 3:
// установка режима рисования эллипсов
currentTool = Tools.ELLIPSE;
break;
SerTooIBarButtonsPushedState(e.Button) ;
SetMenuItemsCheckedState fmenuItemTool.MenuI terns[e.Button.ImageIndex]
private void SetToolBarButtonsPushedState(ToolBarButton button)
foreach (ToolBarButron btnltem in toolBarl.Buttons)
if(btinlT:em == button)
btnltem.Pushed ~ true;
else
btnltem.Pushed = false;
private void menuItemTool_Click(object sender. System.EventArgs e)
{
// получаем пункт меню
Menultem item = (Menulnem)sender;
378 Приложение
switch(item.Text)
\
case "&Карандаш":
// установка режима рисования карандашом
CurrentTool = Tools.PEN;
break,-
case "^Заливка":
// установка режима заливки
currentTool = Tools.TEXT;
break;
case "&Ликия":
// установка режима рисования линий
currentTool = Tools.LINE;
break;
case "ЬЭллипс":
// установка режима рисования эллипсов
currentTool = Tools.ELLIPSE;
break;
// устанавливаем состояние пунктов меню
SetMenuItemsCheckedState(item);
// устанавливаем состояние кнопок
SetToolBarButtonsPushedState(toolBarl.Buttons[item.Index])
private void SetMenuItemsCheckedState(Menultera item)
{
// для каждого пункта меню
foreach(Menultem raenultem in raenuItemTool.Menulteras)
{
if(menultem == item)
{
menultem.Checked - true;
menultem.Checked - false;
private void menuItemNew_Click(object sender, System.EventArgs e)
{
Form2 newMDIChild - new Form2();
Приложение 379
riewMDIChild.MdiParent = t h i s ;
newMDIChild.Show() ;
}
Файл Form2.cs
using System;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
namespace GraphEditorApp
{
/// "summary"
/// Summary description for Form2.
/// "/summary"
public class Form2: System.Windows.Forms.Form
Закладка в соц.сетях