MS Visual C++ 2010 в среде .NET. Библиотека программиста
Қосымшада ыңғайлырақҚосымшаны жүктеуге арналған QRRuStore · Samsung Galaxy Store
Huawei AppGallery · Xiaomi GetApps

автордың кітабын онлайн тегін оқу  MS Visual C++ 2010 в среде .NET. Библиотека программиста

 

В. Зиборов

MS Visual C++ 2010 в среде .NET. Библиотека программиста

на примерах

Технический редактор Е. Пасечник

Литературный редактор Е. Пасечник

Художники Л. Адуевская, Л. Харитонов

Корректоры В. Листова, В. Листова

Верстка Е. Егорова

 

В. Зиборов

MS Visual C++ 2010 в среде .NET. Библиотека программиста. — СПб.: Питер, 2014.

 

ISBN 978-5-459-00786-2

© ООО Издательство "Питер", 2014

 

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

 

Введение

Система разработки программного обеспечения Microsoft Visual Studio 2010 является продуктом номер один на рынке программного обеспечения. Используя эту систему, можно «малой кровью» и очень быстро написать, почти сконструировать, как в детском конструкторе, довольно-таки функционально сложные как настольные приложения (в виде exe-файлов), так и приложения, исполняемые в браузере. В центре системы Visual Studio 2010 находится среда программирования или платформа .NET Framework — это встроенный компонент Windows, который поддерживает создание и выполнение приложений нового поколения и веб-служб. Основными компонентами .NET Framework являются общеязыковая среда выполнения (CLR) и библиотека классов.NET Framework, включающая ADO.NET, ASP.NET, Windows Forms и Windows Presentation Foundation (WPF). Платформа .NET Framework предоставляет среду управляемого выполнения, возможности упрощения разработки и развертывания, а также возможности интеграции со многими языками программирования.

Среда разработки программного обеспечения Visual Studio 2010 включает в себя языки программирования Visual Basic, Visual C#, Visual C++ и Visual F#. Используя эти языки программирования, можно подключаться к библиотекам классов и тем самым иметь все преимущества ускоренной разработки приложений. Если читатель уже имел опыт разработки на языке C++ различных реализаций (Borland, GNU, Intel), то он может очень быстро освоить MS Visual C++ для среды .NET. Данное подмножество языка C++ еще называют C++/CLI. При этом вы будете приятно удивлены тому, что здесь программный код пишется проще, легче читается, а конечный продукт получается очень быстро.

Существенный положительный эффект достигается при групповой разработке какого-либо проекта. Используя Visual Studio, над одним проектом могут работать программисты на C#, на Visual Basic и на C++, при этом среда .NET обеспечит совместимость программных частей, написанных на разных языках.

Целью этой книги является, прежде всего, популяризация программирования. Для достижения этой цели автор выбрал форму демонстрации на примерах решения задач от самых простых, элементарных до более сложных.

Так, рассмотрены примеры программ с экранной формой и элементами управления в форме, такими как текстовое поле, метка, кнопка и др. Написанные программы управляются событиями, в частности событиями мыши и клавиатуры. Поскольку большинство существующих программ взаимодействуют с дисковой памятью, в книге приведены примеры чтения и записи файлов в долговременную память. Описаны решениясамых типичных задач, которые встречаются в практике программирования, таких как работа с графикой и буфером обмена. Приведено несколько подходов к выводу диаграмм (графиков). Рассмотрены манипуляции табличными данными, в том числе организация связанных таблиц. Показан принцип использования элемента управления WebBrowser для отображения различных данных, а также для программного заполнения веб-форм. Обсуждены примеры программирования с применением функций (методов) объектных библиотек систем MS Excel, MS Word, AutoCAD и MATLAB. Представлено несколько выразительных примеров создания PDF-файла. Разобраны вопросы обработки баз данных SQL Server и MS Access с помощью технологии ADO.NET. Рассмотрены методы обработки различных источников данных с использованием технологии LINQ, хотя эту технологию именно для C++/CLI компанияMicrosoft разработала еще недостаточно. Представлено много различных авторских оригинальных решений задач программирования, которых читатель не сможет найти в Интернете.

Несколько слов об особенностях книги. Спросите у любого программиста, как он работает (творит...) над очередной поставленной ему задачей. Он вам скажет, что всю задачу он мысленно разбивает на фрагменты и вспоминает, в каких ранее решенных им задачах он уже сталкивался с подобной ситуацией. Далее он просто копирует фрагменты отлаженного программного кода и вставляет их в новую задачу. Сборник таких фрагментов (более 100 примеров) содержит данная книга. Автор пытался выделить наиболее типичные, актуальные задачи и решить их, с одной стороны, максимально эффективно, а с другой стороны, кратко ивыразительно. С сайта издательства «Питер» (www.piter.com) вы можете скачать архив с рассмотренными в книге примерами.

Самая серьезная проблема, возникающая в процессе создания больших, сложных программ, — это сложность, запутанность текстов. Из-за запутанности программ появляются ошибки, нестыковки и т.п. Как следствие, страдает производительность процесса создания программ и их сопровождение. Решение этой проблемы состоит в структуризации программ. Появление объектно-ориентированного программирования связано в большой степени со структуризацией программирования. Мероприятия для обеспечения большей структуризации — это проектирование программы как иерархической структуры, отдельные процедуры, входящие в программу, не должны быть слишком длинными, не должны использоваться операторы перехода goto и т.п. Кроме того, современные системы программирования разрешают в названиях переменных, методов, свойств, событий, классов, объектовиспользовать кириллические символы. Между тем, современные программисты, как правило, не используют данную возможность, хотя появление среди англоязычного текста русских слов вносит большую выразительность в текст программы и, как следствие, большую структуризацию. Программный код начинает от этого лучше читаться, восприниматься человеком (транслятору, компилятору — все равно).

Данная книга предназначена для начинающих программистов, программистов среднего уровня, а также для программистов, имеющих навыки разработки программ на других языках и желающих ускоренными темпами освоить новый для себя язык MS Visual C++/CLI. Как пользоваться этой книгой? Эффективно пользоваться книгой можно, последовательно решая примеры в том в порядке, в котором они представлены в книге, поскольку примеры расположены от простого к более сложному. Это будет способствовать постепенному совершенствованию ваших навыков разработки на данном языке программирования. А для программистов среднего уровня можно посоветовать решатьвыборочно именно те задачи, которые возникли у них при написании их текущих программ. Если вы программируете на C# или Visual Basic, то вам также будет полезна данная книга, поскольку и C#, и Visual Basic «питаются» все той же средой .NET, следовательно, названия соответствующих классов, методов, свойств и событий одинаковы, а программные коды различных языков отличаются всего лишь синтаксисом.

Надеюсь, что читатель получит одновременно интеллектуальное удовольствие ипрок от использования данной книги в своей работе и творчестве. Свои впечатления о данной книге присылайте по адресу ziborov@ukr.net, я с удовольствием их почитаю.

От издательства

Ваши замечания, предложения, вопросы отправляйте по адресу электронной почты comp@piter.com (издательство «Питер», компьютерная редакция).

Мы будем рады узнать ваше мнение!

На web-сайте издательства http://www.piter.com вы найдете подробную информацию о наших книгах.

 

Что такое «хороший стиль программирования»?

Отвечая на этот вопрос одной строчкой, можно сказать, что хороший стиль программирования подразумевает наличие структуры у написанной программы. Соответственно, если программа содержит много строк программного кода в одной процедуре, не разделена на смысловые блоки, напоминает «спагетти», то есть имеет множество переходов управления, содержит мало комментариев и, как следствие, выглядит запутанной, громоздкой, трудно модифицируемой и управляемой — это это и есть «плохой стиль программирования».

Отсюда появилось понятие структурное программирование. Появилось оно еще в 60-е годы, когда весь мир переживал кризис программного обеспечения. То есть разработка больших автоматизированных систем затягивалась, программисты не укладывалось в сроки, а в готовых программах обнаруживалось множество ошибок. С этими двумя проблемами (низкая производительность разработки программ и ошибки в них) программисты ведут неустанную борьбу. В 1968 году голландский математик-программист Эдсгер Вибе Дейкстра назвал (предположил) причину возникновения проблем: в больших программах зачастую отсутствует четкая логическая структура, они неоправданно сложны. Причем эту «неоправданную» сложность вносит команда goto. Программу с множеством goto называют «спагетти». Представьте, что вы читаете роман: сначала две страницы назад, потом четыре страницы вперед и т.д. Если программа содержит много goto, то человеку проследить передачу управления (последовательность управления) весьма затруднительно (компьютер затруднений не испытывает). Вместо операторов goto Дейкстра предложил использовать всего три типа управляющих структур. Первый тип — это простая последовательность (следование), когда операторы выполняются друг за другом слева направо и сверху вниз. Второй тип — это альтернатива (ветвление), выбор по условию (if — else), множественный выбор (switch — case). И третий тип управляющей структуры — это цикл, то есть повторение одного или нескольких операторов до выполнения условия выхода из цикла.

Так вот, основная идея Дейкстры заключается в том, что, используя эти три структуры (отсюда и название «структурное программирование»), можно обходиться без операторов goto. Он утверждал, что отсутствие наглядности — это и есть основной источник ошибок. Сначала программисты лишь посмеивались над идеями Дейкстры, тем более что он был всего лишь теоретиком программирования. Однако смеяться над чем-то новым — это опрометчиво. Один русский прославленный генерал, когда ему впервые показали только что изобретенный пулемет, снисходительно похлопал изобретателя по плечу и сказал, что если бы в реальном бою нужно было убить одного человека несколько раз, то его изобретение было бы очень кстати. Поэтому не следует спешить высмеивать новое, непонятное и непривычное.

Так случилось и с идеями Дейкстры, фирма IBM весьма успешно применила принципы структурного программирования для создания базы данных газеты «Нью-Йорк таймс», и это стало весомым аргументом в пользу такого подхода. Со временем оператор goto программисты стали называть «позорным» и использовать его лишь в очень крайних случаях. И с тех пор концепция структурного программирования оказывает заметное влияние на теорию и практику программного обеспечения всех рангов.

Сегодня структурное программирование как альтернатива «интуитивному», «рефлекторному» подходу — это методология разработки программного обеспечения, в основе которой лежат не только три типа управляющих структур, но и многое другое, что помогает представлять программу в виде иерархической структуры и тем самым «прятать сложность». Все тело программы стараются делить на логически целостные вычислительные блоки, которые оформляются в виде подпрограмм, функций и классов. Эти вычислительные блоки представляют собой иерархическую структуру, причем наименее значимые «подробности» программы прячут в самые дальние ветви иерархии, чтобы они не мешали пониманию основной логики программы. Пряча те или иные смысловые блоки подальше от глаз, мы тем самым скрываем сложность программы для того, чтобы ее (программы) логика была максимально понятой. Причем «понятность», читабельность нужно обеспечить не только для автора программы, но и для других разработчиков, которые, возможно, будут работать с данной программой. Можно утверждать, что любую самую сложную программу можно сделать доступной для понимания «широким слоям разработчиков», скрывая сложность в смысловых блоках.

Каждый смысловой вычислительный блок должен содержать как можно больше комментариев, а в его начало необходимо вставлять преамбулу, в которой указывать, что этот блок делает и какие технологии и приемы при этом используются. Концепция объектно-ориентированного программирования — это одна из ступеней к большей структуризации программ. Современные системы программирования стараются обеспечить максимальную читабельность наших программ; обратите внимание на отступы и разноцветность программного кода, это придает программам бо`льшую выразительность и понятность.

Следует всегда учитывать простой факт: суть программы, которую вы писали неделю назад, очень быстро забывается. А если вы посмотрите на программу, написанную вами месяц назад? Вы удивитесь, но у вас создастся впечатление, что это чужая программа, написанная кем-то другим, но никак не вами. Не стоит удивляться, это особенность человеческого организма — отбрасывать все на его (организма) взгляд ненужное!

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

Таким образом, большая структуризация программы — это путь повышения производительности разработки, уменьшения количества ошибок, это и есть «хороший стиль программирования».

Глава 1. Простейшие программы с экранной формой и элементами управления

Пример 1. Форма, кнопка, метка и диалоговое окно

После инсталляции системы программирования Visual Studio 2010, включающей в себя Visual C++ 2010, загрузочный модуль системы devenv.exe будет, скорее всего, расположен в папке: C:\Program Files\Microsoft Visual Studio 10.0\Common7\IDE.

После запуска системы мы увидим начальный пользовательский интерфейс, показанный на рис. 1.1.

 

Рис. 1.1. Фрагмент стартовой страницы системы Visual Studio 2010

Чтобы запрограммировать какую-либо задачу, необходимо в пункте меню File выполнить команду New Project. В появившемся окне New Project в левой колонке находится список установленных шаблонов (Installed Templates). Среди них — шаблоны языков программирования, встроенных в Visual Studio, в том числе Visual Basic, Visual C#, Visual C++, Visual F# и др. Нам нужен язык Visual C++. В узле Visual C++ области типов проектов выберем среду CLR, а затем в области шаблонов (в средней колонке) выберем шаблон (Templates) Windows Forms Application Visual C++. Теперь введем имя проекта (Name) First и щелкнем на кнопке OK, в результате увидим окно, представленное на рис. 1.2.

 

Рис. 1.2. Окно для проектирования пользовательского интерфейса

В этом окне изображена экранная форма — Form1, в которой программисты располагают различные компоненты графического интерфейса пользователя или, как их иначе называют, элементы управления. Это поля для ввода текста TextBox, командные кнопки Button, строчки текста в форме — метки Label, которые не могут быть отредактированы пользователем, и прочие элементы управления. Следует отметить, что здесь используется самое современное, так называемое визуальное программирование, предполагающее простое перетаскивание элементов с помощью мыши из панели элементов Toolbox, где расположены всевозможные элементы управления, в форму. Это помогает свести к минимуму непосредственное написание программного кода.

Ваша первая программа будет отображать такую экранную форму, в которой будет что-либо написано, например «Microsoft Visual C++ 2010», также в форме будет расположена командная кнопка с надписью «Нажми меня». При нажатии кнопки будет появляться диалоговое окно с сообщением «Всем привет!»

Написать такую программку — вопрос 2–3 минут. Но вначале я хотел бы буквально двумя словами объяснить современный объектно-ориентированный подход к программированию. Подход заключается в том, что в программе все, что может быть названо именем существительным, называют объектом. Так в нашей программе мы имеем четыре объекта: форму Form, надпись на форме Label, кнопку Button и диалоговое окно MessageBox с текстом «Всем привет!» (окно с приветом).

Теперь давайте добавим в форму названные элементы управления. Для этого нам понадобится панель элементов управления Toolbox. Если в данный момент вы не видите панель элементов, то ее можно добавить, например, с помощью комбинации клавиш Ctrl+Alt+x или View\Toolbox. Итак, добавьте метку Label и кнопку Button в форму, дважды щелкая на этих элементах на панели Toolbox. А затем следует расположить их примерно так, как показано на рис. 1.3.

 

Рис. 1.3. Форма первого проекта

Любой такой объект можно создавать самому, а можно воспользоваться готовыми объектами. В данной задаче мы пользуемся готовыми визуальными объектами, которые можно перетаскивать с помощью мыши из панели элементов управления Toolbox. В этой задаче нам следует помнить, что каждый объект имеет свойства (properties). Например, свойствами кнопки являются (рис. 1.4): имя кнопки (Name) — button1, надпись на кнопке (Text), расположение кнопки (Location) в системе координат формы X, Y, размер кнопки Size и т.д. Свойств много, их можно увидеть, если щелкнуть правой кнопкой мыши в пределах формы и выбрать в контекстном меню команду Properties, при этом появится панель свойств Properties (рис. 1.4).

 

Рис.1.4. Свойства кнопки button1

Указывая мышью на другие элементы управления в форме, можно просмотреть их свойства: формы Form1 и надписи в форме — метки label1.

Вернемся к нашей задаче. Для объекта label1 выберем свойство Text и напишем напротив этого поля «Microsoft Visual C++ 2010» (вместо текста label1). Для объекта button1 также в свойстве Text напишем «Нажми меня».

Следует помнить, что объекты не только имеют свойства, но и обрабатываются событиями. Событием, например, является щелчок на кнопке, щелчок в пределах формы, загрузка (Load) формы в оперативную память при старте программы и пр. Управляют тем или иным событием посредством написания процедуры обработки события в программном коде. Для этого вначале нужно получить «пустой» обработчик события. В нашей задаче единственным событием, которым мы управляем, является щелчок на командной кнопке. Для получения пустого обработчика этого события следует в свойствах кнопки button1 (см. рис. 1.4) щелкнуть на значке молнии Events (события) и в списке всех возможных событий кнопки button1 выбрать двойным щелчком событие Click. После этого мы попадаем на вкладку программного кода Form1.h (см. рис. 1.5).

 

Рис 1.5.Вкладка программного кода

На вкладке Form1.h мы увидим, что управляющая среда Visual C++ 2010 сгенерировала довольно-таки много строк программного кода. Не стоит ужасаться такому обилию непонятного кода, постепенно многое прояснится. Во всяком случае, в этом тексте вы уже можете найти те присваивания, которые сделали в панели свойств Properties. Например, для свойства Text кнопки Button управляющая среда назначила строку «Нажми меня»:

this->button1->Text = L"Нажми меня";

На рис. 1.5. показан только фрагмент программного кода, причем только его заключительная часть, где мы имеем уже упомянутый нами пустой обработчик события button1_Click:

private: System::Void button1_Click(System::Object^ sender, System::EventArgs^ e) { }

Здесь в фигурных скобках мы можем написать команды, подлежащие выполнению после щелчка на кнопке. Вы видите, что у нас теперь две вкладки: Form1.h и Form1.h [Design], то есть вкладка программного кода и вкладка визуального проекта программы (другое название этой вкладки — дизайнер формы). Переключаться между ними можно с помощью мыши или с помощью комбинации клавиш Ctrl+Tab, как это принято обычно при переключении между вкладками в Windows, а также функциональной клавишей F7.

Напомню, что по условию задачи после щелчка на кнопке должно появиться диалоговое окно, в котором написано: «Всем привет!» Поэтому в фигурных скобках обработчика события напишем:

MessageBox::Show("Всем привет!");

Здесь вызывается метод (программа) Show объекта MessageBox с текстом «Всем привет!» Оператор разрешения области действия (::) указывает системе найти метод Show среди методов объекта Messagebox. Таким образом, я здесь «нечаянно» проговорился о том, что объекты кроме свойств имеют также и методы, то есть программы, которые обрабатывают объекты. Кстати, после каждого оператора в C-программах ставят точку с запятой. Это вместе с фигурными скобками по форме отличает C-программу от программных кодов на других языках программирования.

Таким образом, мы написали процедуру обработки события щелчка (Click) на кнопке button1. Теперь нажмем клавишу F5 и проверим работоспособность программы (рис. 1.6).

 

 

Рис. 1.6. Фрагмент работы программы

Поздравляю, вы написали свою первую программу на MS Visual C++!

Убедиться в работоспособности программы можно, открыв решение First.sln в папке First.

Пример 2. Событие MouseHover

Немного усложним задачу из предыдущего примера. Добавим еще одну обработку события MouseHover мыши для объекта label1. Событие MouseHover наступает тогда, когда пользователь указателем мыши «зависает» над каким-либо объектом, причем именно «зависает»», а не просто перемещает мышь над объектом (от англ. hover — реять, парить). Можно сказать, что событие MouseHover происходит, когда указатель мыши наведен на элемент. Есть еще событие MouseEnter (Войти), когда указатель мыши входит в пределы области элемента управления (в данном случае меткиlabel1), но в данном примере будем использовать именно событие MouseHover.

Таким образом, программа в данном примере должна содержать на экранной форме текстовую метку Label и кнопку Button. Метка должна отображать текст «Microsoft Visual C++ 2010»; при щелчке на командной кнопке, на которой по-прежнему будет написано «Нажми меня», появится диалоговое окно с сообщением «Всем привет!» Кроме того, когда указатель мыши наведен на текстовую метку (то самое событие MouseHover), должно появиться диалоговое окно с текстом «Событие Hover».

Для решения этой задачи запустим Visual Studio 2010, щелкнем на пункте меню New Project. В появившемся окне New Project в левой колонке в узле Visual C++ выберем среду CLR, а затем в области шаблоны (в средней колонке) выберем шаблон (Templates) Windows Forms Application Visual C++. В качестве имени проекта введем имя Hover и щелкнем на кнопке OK.

В дизайнере формы из панели Toolbox перетащим на форму метку Label и кнопку Button, а затем немного уменьшим размеры формы на свое усмотрение. Теперь добавим три обработчика событий в программный код. Для этого в панели Properties следует щелкнуть на значке молнии (Events) и двойным щелчком последовательно выбрать событие загрузки формы Form_Load, событие «щелчок на кнопке button1_Click» и событие label1_MouseHover.

При этом осуществится переход на вкладку программного кода Form1.h, и среда Visual Studio 2010 сгенерирует три пустых обработчика события. Например, обработчик последнего события будет иметь вид:

private:System::Void lab el1_MouseHover(System::ObjectsenderSystem::EventArgse){}

Между фигурными скобками вставим вызов диалогового окна:

MessageBox::Show("Событие Hover!");

Теперь проверим возможности программы: нажимаем клавишу F5, «зависаем» указателем мыши над label1, щелкаем на кнопке button1. Все работает!

А теперь я буду немного противоречить сам себе. Я говорил про визуальную технику программирования, направленную на минимизацию написания программного кода. А сейчас хочу сказать про наглядность, оперативность, технологичность работы программиста. Посмотрите на свойства каждого объекта в панели Properties. Как много строчек! Если вы меняете какое-либо свойство, то оно выделяется жирным шрифтом. Удобно! Но еще удобнее свойства объектов назначать (устанавливать) в программном коде. Почему?

Каждый программист имеет в своем арсенале множество уже отлаженных фрагментов, которые он использует в своей очередной новой программе. Программисту стоит лишь вспомнить, где он уже программировал ту или иную ситуацию. Программа, которую написал программист, имеет свойство быстро забываться. Если вы посмотрите на строчки кода, которые писали три месяца назад, то поймете, что многое забыли; если прошел год, то вы смотрите на написанную вами программу, как на чужую. Поэтому при написании программ на первое место выходят понятность, ясность, очевидность написанного программного кода. Для этого каждая система программирования имеет определенные средства. Кроме того, сам программист должен придерживаться некоторых правил, помогающих ему работать производительно и эффективно.

Назначать свойства объектов в программном коде удобно или сразу после инициализации компонентов формы (после вызова процедуры InitializeComponent), или при обработке события Form1_Load, то есть события загрузки формы в оперативную память при старте программы. Для того чтобы получить простой обработчик этого события, как и в предыдущих случаях, можно выбрать нужное событие в панели свойств объекта, а можно поступить еще проще: дважды щелкнуть в пределах проектируемой формы на вкладке Form1.h [Design]. В любом случае получаем пустой обработчик события на вкладке программного кода. Заметим, что для формы таким умалчиваемым событием, для которого можно получить пустой обработчик двойным щелчком, является событие загрузки формы Form1_Load, для командной кнопки Button и метки Label таким событием является одиночный щелчок мышью на этих элементах управления. То есть если дважды щелкнуть в дизайнере формы по кнопке, то получим пустой обработчик button1_Click в программном коде, аналогично — для метки Label.

Итак, вернемся к событию загрузки формы, для него управляющая среда сгенерировала пустой обработчик:

private: System::Void Form1_Load(System::Object^  sender, System::EventArgs^  e) { } 

В фигурных скобках обычно помещают свойства различных объектов и даже часто пишут много строчек программного кода. Здесь мы назначим свойству Text объекта label1 значение «Microsoft Visual C++ 2010»:

label1->Text = "Microsoft  Visual  C++ 2010";

Аналогично для объекта button1:

button1->Text = "Нажми меня";

Совершенно необязательно писать каждую букву приведенных команд. Например, для первой строчки достаточно написать «la», уже это вызовет появление раскрывающегося меню, где вы сможете выбрать нужные для данного контекста ключевые слова. Это очень мощное и полезное современное средство, называемое IntelliSense (его иногда называют суфлером), для редактирования программного кода! Если вы от Visual Studio 2010 перешли в другую систему программирования, в которой отсутствует подобный сервис, то будете ощущать сильный дискомфорт. Возможно, вам досталась такая версия Visual Studio 2010, в которой функция IntelliSense недоступна, в этом случае система в левом нижнем углу пишет: «Intellisense: Unavailable for C++/CLI» (функция IntelliSense недоступна для C++/CLI). В таком случае я посоветую использовать плагин Visual Assist X для Microsoft Visual Studio разработанный компанией Whole Tomato; привожу адрес их сайта, где этот плагин можно скачать и инсталлировать: http://www.wholetomato.com.

Пользуясь функцией IntelliSense, очень удобно после ввода оператора разрешения области действия (::), оператора-точки (.) или оператора-стрелки (->) получать список допустимых вариантов дальнейшего ввода. Можно выделить элемент и нажать клавишу Tab или Enter или дважды щелкнуть на элементе, чтобы вставить его в код. Как видите, не следует пугаться слишком длинных ключевых слов, длинных названий объектов, свойств, методов, имен переменных. Система подсказок современных систем программирования значительно облегчает всю нетворческую работу. Вот почему в современных программах можно встретить такие длинные имена ключевых слов, переменных и т.п. Я призываю вас, уважаемые читатели, также использовать в своих программах для названий переменных и объектов наиболее ясные, полные имена, причем можно на вашем родном русском языке. Потому что на первое место выходят ясность, прозрачность программирования, а громоздкость названий с лихвой компенсируется системой подсказок.

Далее хотелось бы, чтобы слева вверху формы на синем фоне (в так называемой строке заголовка) была не надпись «Form1», а что-либо осмысленное. Например, слово «Приветствие». Для этого ниже присваиваем эту строку свойству Text формы. Поскольку мы изменяем свойство объекта Form1 внутри подпрограммы обработки события, связанного с формой, следует к форме обращаться или через ссылку this или используя имя объекта Form1:

this->Text = "Приветствие"; или  Form1::Text = "Приветствие";

После написанная последней строчки кода мы должны увидеть на экране программный код, представленный в листинге 1.1, где приведен лишь фрагмент с нашими корректировками.

Листинг 1.1Фрагмент файла Form1.h, содержащего программный код с тремя обработчиками событий

            // ...............

            // Программный код, расположенный выше, создан средой  Visual  Studio

            // автоматически, поэтому автором не приводится

            this->ResumeLayout(false);

            this->PerformLayout();

        }

#pragma endregion

        // Данная программа управляется тремя событиями. Событие загрузки формы

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

        // и кнопки. Событие щелчок на кнопке button1_Click вызывает появление

        // диалогового окна с текстом "Всем привет!". Событие, когда указатель

        // мыши наведен на метку, вызывает появление диалогового окна с текстом

        // "Событие Hover".

    private: System::Void Form1_Load(System::Object^  sender, 

                                                      System::EventArgs^  e)

             { // Обработка события загрузки формы:

                 this->Text = "Приветствие";

                 // или Form1::Text = "Приветствие";

                 label1->Text = "Microsoft  Visual  C++ 2010";

                 button1->Text = "Нажми меня";

             }

    private: System::Void button1_Click(System::Object^  sender, 

                                                      System::EventArgs^  e)

             { // Обработка события щелчок на кнопке:

                 MessageBox::Show("Всем привет!");

             }

    private: System::Void label1_MouseHover(System::Object^  sender,

                                                      System::EventArgs^  e) 

             { // Обработка события, когда указатель мыши наведен на метку:

                 MessageBox::Show("Событие Hover!");             

             }

    };

}

Комментарии, поясняющие работу программы, в окне редактора кода будут показаны зеленым цветом, что в тексте выделяет их среди прочих элементов программы. В языках C комментарий пишут после двух слэшей (//) или внутри пар /* */. Уважаемые читатели, даже если вам кажется весьма очевидным то, что вы пишете в программном коде, напишите комментарий. Как показывает опыт, даже самый очевидный замысел программиста забывается удивительно быстро. Человеческая память отметает все, что по оценкам организма считается ненужным. Кроме того, даже если текст программы вполне ясен, в начале программы должны быть описаны ее назначение и способ использования, то есть как бы «преамбула» программы. Далее в последующих примерах мы будем следовать этому правилу.

На рис. 1.7 приведен фрагмент работы программы.

 

 

Рис. 1.7. Фрагмент работы программы

Обычно в редакторах программного кода используется моноширинный шрифт, поскольку все символы такого шрифта имеют одинаковую ширину, в том числе и точка, и прописная русская буква «Ш». По умолчанию в редакторе программного кода C++ 2010 задан шрифт Consolas. Однако если пользователь привык к шрифту Courier New, то его настройку можно изменить, выбрав меню Tools\Options\Environment\Fonts and Colors.

Теперь закроем проект (File\Close Project). Система предложит нам сохранить проект, сохраним проект под именем Hover. Теперь программный код этой программы можно посмотреть, открыв решение Hover.sln, в папке Hover.

Пример 3. Выбор нужной даты

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

Для решения этой задачи запустим систему программирования Visual Stu­dio 2010, щелкнем на пункте New Project. В появившемся окне New Project в узле Visual C++ выберем среду CLR, а затем в области шаблоны (в средней колонке) выберем шаблон (Templates) Windows Forms Application Visual C++. В качестве имени проекта введем имя ВыборДаты и щелкнем на кнопке OK.

В дизайнере формы из панели Toolbox перетащим на форму командную кнопку Button, метку Label и элемент DateTimePicker. Этот элемент непосредственно выполняет функцию выбора даты. Если щелкнуть на стрелке элемента DateTimePicker, то раскроется календарь для выбора даты, как видно из рис. 1.8. Также мы хотим, чтобы календарь элемента DateTimePicker раскрывался при нажатии кнопки Button. В итоге выбранная дата должна отображаться в текстовой метке Label.

С помощью указателя мыши немного уменьшим размеры экранной формы и расположим элементы управления, как показано на рис. 1.8. Двойной щелчок в пределах формы вызовет переход на вкладку программного кода Form1.h. При этом среда Visual Studio сгенерирует пустой обработчик события загрузки формы Form_Load (листинг 1.2). Таким же способом, то есть двойным щелчком на командной кнопке в дизайнере формы, мы получим пустой обработчик события «щелчок на кнопке». Нам еще понадобится обработчик события ValueChanged. Чтобы его получить, перейдем на вкладку конструктора формы Form1.h[Design] и в панели свойств, щелкнув на значке молнии (Events), для элемента dateTimePicker1 двойным щелчком выберем событие ValueChanged. Это приведет к созданию пустого обработчика этого события на вкладке Form1.h. На вкладке программного кода добавим недостающие команды (см. листинг 1.2).

Листинг 1.2Фрагмент файла Form1.h, содержащего программный код выбора необходимой даты

            // ...............

            // Программный код, расположенный выше, создан средой  Visual  Studio

            // автоматически, поэтому автором не приводится

            this->ResumeLayout(false);

            this->PerformLayout();

        }

#pragma endregion

        // Программа выбора нужной даты

    private: System::Void Form1_Load(System::Object^  sender, 

                 System::EventArgs^  e)

             { // Обработка события загрузки формы:

                 this->Text = "Средство выбора даты";

                 dateTimePicker1->Format = DateTimePickerFormat::Custom;

                 dateTimePicker1->CustomFormat = "ddd, dd MMM, yyyy";

                 button1->Text = "Выбрать дату:";

                 label1->Text = String::Format("Сегодня: {0}", 

                                                 dateTimePicker1->Text);

             }

    private: System::Void dateTimePicker1_ValueChanged(System::Object^ sender,

                                                       System::EventArgs^ e)

             { // Обработка события изменения даты:

                 label1->Text = String::Format("Выбранная дата: {0}",

                     dateTimePicker1->Text);

             }

    private: System::Void button1_Click(System::Object^  sender, 

                                        System::EventArgs^  e) 

             { // Обработка события "щелчок на кнопке"

                 // Передаем фокус на элемент управления dateTimePicker1:

                 dateTimePicker1->Focus();

                 // Имитируем нажатие клавиши <F4>:

                 SendKeys::Send("{F4}");

             }

    };

}

Как видно из программного кода, при обработке события загрузки формы задается нужный формат отображения даты: вначале (первые три буквы ddd) задаем вывод дня недели в краткой форме; затем (dd MMM) — дня и названия месяца, также в краткой форме, и наконец, вывод года (yyyy). При обработке события изменения даты ValueChanged текстовой метке label1 присваиваем выбранное значение даты. При этом пользуемся методом String::Format. Использованный формат «Выбранная дата: {0}» означает: взять нулевой выводимый элемент, то есть свойство Text объекта dataTimePicker1, и записать его вместо фигурных скобок.

При обработке события «щелчок на кнопке» вначале передаем фокус на элемент управления dateTimePicker1. Теперь можем использовать нажатие клавиши F4 для раскрытия календаря. Функциональная клавиша F4 обеспечивает раскрытие списка в приложениях Windows. Например, в интернет-браузерах, если передать фокус (щелчком мыши) на адресную строку, после нажатия F4 раскроется список уже посещавшихся вами веб-страниц, и вам останется лишь выбрать в этом списке нужный ресурс. В данном случае мы имитируем нажатие F4. Метод Send посылает сообщение активному приложению о нажатии соответствующей клавиши.

Фрагмент работы программы показан на рис. 1.8.

Заметим, что подобный пример использования раскрывающегося календаря приведен в документации Visual Studio на сайте Microsoft www.msdn.com. Автором внесены лишь некоторые изменения.

Убедиться в работоспособности программы можно, открыв решение ВыборДаты.sln в папке ВыборДаты.

 

Рис. 1.8. Выбор нужной даты из раскрывающегося календаря

Пример 4. Ввод данных через текстовое поле TextBox с проверкой типа методом TryParse

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

Решая сформулированную задачу, запускаем Visual Studio, выбираем пункт меню File\New\Project. В окне New Project в узле Visual C++ выберем среду CLR, а затем в области шаблоны выберем шаблон (Templates) Windows Forms Application Visual C++. В качестве имени проекта введем имя Корень и щелкнем на кнопке OK. Далее из панели элементов управления Toolbox (если в данный момент вы не видите панель элементов управления, то ее можно добавить, например, с помощью комбинации клавиш Ctrl+Alt+x или меню View\Toolbox) в форму с помощью указателя мыши перетаскиваем текстовое поле TextBox, метку Label и командную кнопку Button. Получить названные элементы на проектируемой экранной форме можно, также дважды щелкая указателем мыши на каждом элементе в панели Tools. Таким образом, в форме будут находиться три элемента управления. Расположим их на экранной форме так, как показано на рис. 1.9.

Теперь нам следует изменить некоторые свойства элементов управления. Это уместно сделать после инициализации компонентов формы в программном коде файла Form1.h, то есть сразу после вызова процедуры InitializeComponent. Но это неудобно с точки зрения изложения, нам проще присвоить новые свойства при обработке загрузки формы. Чтобы получить пустой обработчик загрузки формы, дважды щелкнем по проектируемой экранной форме. Сразу после этого мы попадаем на вкладку программного кода Form1.h. Здесь задаем свойствам формы (к форме обращаемся посредством ссылки this), кнопкам button1 и текстового поля textBox1, метке label1 следующие значения:

this->Text  = "Извлечение квадратного корня";

button1->Text  = "Извлечь корень";

textBox1->Clear(); //  Очистка текстового поля

label1->Text  = nullptr; // или = String::Empty;

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

Далее программируем событие button1_Click — «щелчок мышью на кнопке Извлечь корень». Создать пустой обработчик этого события удобно, дважды щелкнув мышью на этой кнопке. Между двумя появившимися строчками программируем диагностику правильности вводимых данных, конвертирование строковой переменной в переменную типа Single и непосредственное извлечение корня (листинг 1.3).

Листинг 1.3Фрагмент программы извлечения корня с проверкой типа методом TryParse

            // ...............

            // Программный код, расположенный выше, создан средой  Visual  Studio

            // автоматически, поэтому автором не приводится

            this->ResumeLayout(false);

            this->PerformLayout();

        }

#pragma endregion

        // Программа вводит через текстовое поле число, при щелчке на командной

        // кнопке извлекает из него квадратный корень и выводит результат

        // на метку label1. В случае ввода не числа сообщает пользователю об

        // этом, выводя красным цветом предупреждение также на метку label1.

    private: System::

                 Void Form1_Load(System::Object^  sender, System::EventArgs^  e) 

             {

                 button1->Text = "Извлечь корень";

                 label1->Text = String::Empty;

                 // или label1->Text = nullptr;

                 this->Text = "Извлечение квадратного корня";

                 textBox1->Clear(); // Очистка текстового поля

                 textBox1->TabIndex = 0; // Установка фокуса в текстовом поле

             }

    private: System:: // Обработка щелчка на кнопке "Извлечь корень":

                 Void button1_Click(System::Object^  sender, System::EventArgs^  e)

             {  

                 Single X; // - из этого числа будем извлекать корень

                 // Преобразование из строковой переменной в Single:

                 bool Число_ли = Single::TryParse(textBox1->Text,

                     System::Globalization::NumberStyles::Number,

                     System::Globalization::NumberFormatInfo::CurrentInfo, X);

                 // Второй параметр - это разрешенный стиль числа (Integer, 

                 // шестнадцатеричное число, экспоненциальный вид числа и прочее).

                 // Третий параметр форматирует значения на основе текущего языка

                 // и региональных параметров из Панели управления - Язык и

                 // региональные стандарты - число допустимого формата; метод

                 // возвращает значение в переменную X

                 if (Число_ли == false)

                 { // Если пользователь ввел не число:

                     label1->Text = "Следует вводить числа";

Листинг 1.3 (продолжение)

                     label1->ForeColor = Color::Red; // - цвет текста на метке

                     return; // - выход из процедуры

                 }

                 Single Y = (Single)Math::Sqrt(X); // - извлечение корня

                 label1->ForeColor = Color::Black; // - черный цвет текста

                 на метке

                 label1->Text = String::Format("Корень из {0} равен {1:F5}", X, Y);

             }

    };

}

Здесь при обработке события «щелчок мышью на кнопке Извлечь корень» ­проверяется, введено ли число в текстовом поле. Проверка осуществляется с помощью функции TryParse. Первым параметром метода TryParse является анализи­руемое поле textBox1->Text. Второй параметр — это разрешаемый для преобразования стиль числа, он может быть целого типа (Integer), шестнадцатеричным (HexNumber), представленным в экспоненциальном виде и пр. Третий параметр указывает, на какой основе формируется допустимый формат, в нашем случае мы использовали CurrentInfo, то есть на основе текущего языка и региональных параметров. По умолчанию при инсталляции русифицированной версии Windows XP разделителем целой и дробной части числа является запятая. Однако эту уста­новку можно изменить, если в Панели управления выбрать значок Язык и региональные стандарты, затем на вкладке Региональные параметры щелкнуть на кнопке Настройка и на появившейся новой вкладке указать в качестве разделителя целой и дробной частей точку вместо запятой. В обоих случаях (и для запятой, и для точки) метод TryParse будет работать так, как указано на вкладке Региональные параметры.

Четвертый параметр метода TryParse возвращает результат преобразования. Кроме того, функция TryParse возвращает булеву переменную true или false, которая сообщает, успешно ли выполнено преобразование. Как видно из текста программы, если пользователь ввел не число (например, введены буквы), то на метку label1 ­выводится красным цветом текст: «Следует вводить числа». Далее, поскольку ввод неправильный, организован выход из программы обработки события button1_Click с помощью оператора return. На рис. 1.9 показан фрагмент работы программы.

 

Рис 1.9. Фрагмент работы программы

Как видно из рисунка, функция TryParse не восприняла введенные символы «2,3» как число, поскольку автор специально для демонстрации данного примера указал на вкладке Региональные параметры точку в качестве разделителя целой и дробной частей.

Если пользователь ввел все-таки число, то будет выполняться следующий оператор извлечения квадратного корня Math::Sqrt(X). Математические функции Visual Studio 2010 являются методами класса Math. Их можно увидеть, набрав Math и введя так называемый оператор разрешения области действия (::). В раскрывающемся списке вы увидите множество математических функций: Abs, Sin, Cos, Min и т.д. и два свойства — две константы E = 2,718... (основание натуральных логарифмов) и PI = 3,14... (число диаметров, уложенных вдоль окружности). Функция Math::Sqrt(X)возвращает значение типа double (двойной точности с плавающей запятой), которое мы приводим с помощью неявного преобразования (Single) к переменной одинарной точности.

Последней строчкой обработки события button1_Click является формирование строки label1->Text с использованием метода String::Format. Использованный формат «Корень из {0} равен {1:F5}» означает: взять нулевой выводимый элемент, то есть переменную X, и записать эту переменную вместо фигурных скобок; после чего взять первый выводимый элемент, то есть Y, и записать его вместо вторых фигурных скобок в формате с фиксированной точкой и пятью десятичными знаками после запятой.

Нажав клавишу F5, проверяем, как работает программа.

Результат работающей программы представлен на рис. 1.10.

 

Рис. 1.10. Извлечение квадратного корня

Если появились ошибки, то работу программы следует проверить отладчиком — клавиши F10 или F11. В этом случае управление останавливается на каждом операторе, и вы можете проверить значение каждой переменной, наводя указатель мыши на переменные. Можно выполнить программу до определенной программистом точки (точки останова), используя, например, клавишу F9 или оператор Stop, и в этой точке проверить значения необходимых переменных.

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

Пример 5. Ввод пароля в текстовое поле и изменение шрифта

Это очень маленькая программа для ввода пароля в текстовое поле, причем при вводе вместо вводимых символов некто, «находящийся за спиной пользователя», увидит только звездочки. Программа состоит из формы, текстового поля TextBox, метки Label, куда для демонстрации возможностей мы будет копировать пароль (паспорт, то есть секретные слова), и командной кнопки Button — Покажи паспорт.

После запуска Visual Studio и выбора приложения в среде CLR шаблона Windows Forms Application Visual C++ перемещаем в форму все названные элементы управления. Текст программы приведен в листинге 1.4.

Листинг 1.4Фрагмент программы, организующей ввод пароля

            // ...............

            // Программный код, расположенный выше, создан средой  Visual  Studio

            // автоматически, поэтому автором не приводится

            this->ResumeLayout(false);

            this->PerformLayout();

        }

#pragma endregion

        // Программа для ввода пароля в текстовое поле, причем при вводе вместо

        // вводимых символов некто, "находящийся за спиной пользователя", увидит

        // только звездочки

    private: System:: // Обработка события "загрузка формы":

                 Void Form1_Load(System::Object^  sender, System::EventArgs^  e)

             {

                 Form1::Text = "Введи пароль";

                 textBox1->Text = nullptr; textBox1->TabIndex = 0;

                 textBox1->PasswordChar = ‘*’; 

                 textBox1->Font = gcnew System::Drawing::Font("Courier New",

                 9.0F);

                 // или textBox1->Font = gcnew System::Drawing::Font(FontFamily::

                 //                                        GenericMonospace,9.0F);

                 label1->Text = String::Empty;

                 label1->Font = gcnew System::Drawing::Font("Courier New", 9.0F);

                 button1->Text = "Покажи паспорт";

             }

    private: System:: // Обработка события "щелчок на кнопке":

                 Void button1_Click(System::Object^  sender, System::EventArgs^  e)

             {

                 label1->Text = textBox1->Text;

             }

    };

}

Как видно из текста программы, при обработке события загрузки формы мы очищаем текстовое поле и делаем его «защищенным от посторонних глаз» c помощью свойства textBox1->PasswordChar; каждый введенный пользователем символ маскируется символом звездочки (*). Далее мы хотели бы для большей выразительности и читабельности программы сделать так, чтобы вводимые звездочки и результирующий текст имели одинаковую длину. Все символы шрифта Courier New имеют одинаковую ширину, поэтому его называют моноширинным шрифтом. Кстати, используя именно этот шрифт, благодаря одинаковой ширине букв удобно программировать таблицу. Еще одним широко используемым моноширинным шрифтом является шрифт Consola. Задаем шрифт, используя свойство Font обоих объектов: textBox1 и label1. Число 9.0 означает размер шрифта. Свойство текстового поля TabIndex = 0 обеспечивает передачу фокуса при старте программы именно в текстовое поле.

Осталось обработать событие button1_Click — щелчок на кнопке. Здесь — банальное присваивание текста из поля тексту метки. Программа написана, нажимаем клавишу F5. На рис. 1.11 приведен вариант работы данной программы.

 

Рис 1.11. Вариант работы программы

При необходимости используйте отладчик (клавиша F11 или F10) для пошагового выполнения программы и выяснения всех промежуточных значений переменных путем «зависания» указателя мыши над переменными.

Убедиться в работоспособности программы можно, открыв решение Паспорт.sln в папке Паспорт.

Пример 6. Управление стилем шрифта с помощью элемента управления CheckBox

Кнопка CheckBox (Флажок) также находится на панели элементов управления Toolbox. Флажок может бытьлибо установлен (содержит«галочку»), либо сброшен (пустой). Напишем программу, которая управляет стилем шрифта текста, выведенного на метку Label. Управлять стилем будем посредством флажка CheckBox.

Запустим Visual Studio 2010 и выберем приложение в среде CLR шаблона Win­dows Forms Application Visual C++. Используя панель элементов Toolbox, в форму поместим метку Label и флажок CheckBox. В листинге 1.5 приведен текст программы управления этими объектами.

Листинг 1.5Фрагмент программы, управляющей стилем шрифта

            // ...............

            // Программный код, расположенный выше, создан средой  Visual  Studio

            // автоматически, поэтому автором не приводится

            this->ResumeLayout(false);

            this->PerformLayout();

        }

#pragma endregion

        // Программа управляет стилем шрифта текста, выведенного на метку Label,

        // посредством флажка CheckBox

    private: System::

                 Void Form1_Load(System::Object^  sender, System::EventArgs^  e) 

             {

                 this->Text = "Флажок CheckBox";

                 checkBox1->Text = "Полужирный"; checkBox1->Focus();

                 label1->Text = "Выбери стиль шрифта";

                 label1->TextAlign = ContentAlignment::MiddleCenter;

                 label1->Font = gcnew System::Drawing::Font("Courier New",

                 14.0F);

             }

    private: System::Void checkBox1_CheckedChanged(System::Object^  sender, 

                                                            System::EventArgs^  e)

             { // Изменение состояния флажка на противоположное

                 if (checkBox1->Checked == true) label1->Font = gcnew System::

                              Drawing::Font("Courier New", 14.0F,

                              FontStyle::Bold);

                 if (checkBox1->Checked == false) label1->Font = gcnew System::

                           Drawing::Font("Courier New", 14.0F,

                           FontStyle::Regular);

             }

    };

}

При обработке события загрузки формы задаем начальные значения некоторых свойств объектов Form1 (посредством ссылки this), label1 и checkBox1. Так, тексту флажка, выводимого с правой стороны, присваиваем значение «Полужирный». Кроме того, при старте программы фокус должен находиться на флажке (checkBox1.Focus();), в этом случае пользователь может изменять установку флажка даже клавишей Пробел.

Текст метки — «Выбери стиль шрифта», выравнивание метки TextAlign задаем посередине и по центру (MiddleCenter) относительно всего того места, которое предназначено для метки. Задаем шрифт метки Courier New (в этом шрифте все буквы имеют одинаковую ширину) размером 14 пунктов.

Изменение состояния флажка соответствует событию CheckedChanged. Чтобы получить пустой обработчик события CheckedChanged, следует дважды щелкнуть на элементе checkBox1 вкладки Form1.h [Design]. Между соответствующими строчками следует записать (см. текст программы): если флажок установлен (то есть содержит «галочку») Checked = true, то для метки label1 устанавливается тот же шрифт Courier New, 14 пунктов, но Bold, то есть полужирный.

Далее — следующая строчка кода: если флажок не установлен, то есть checkBox1.Checked = false, то шрифт устанавливается Regular, то есть обычный. Очень часто эту ситуацию программируют, используя ключевое слово else (иначе), однако это ­выражение будет выглядеть более выразительно и понятно так, как написали его мы.

Программа написана, нажмите клавишу F5. Проверьте работоспособность программы. В рабочем состоянии она должна работать примерно так, как показано на рис. 1.12.

 

Рис. 1.12. Фрагмент работы программы управления стилем шрифта

Убедиться в работоспособности программы можно, открыв решение Флажок1.sln в папке Флажок1.

Пример 7. Побитовый оператор «исключающее ИЛИ»

Несколько изменим предыдущую программу в части обработки события CheckedChanged (изменение состояния флажка). Вместо двух условий if() напишем один оператор:

label1->Font = gcnew System::Drawing::Font(

          "Courier New", 14.0F, label1->Font->Style ^ FontStyle::Bold);

Здесь каждый раз при изменении состояния флажка значение параметра label1->Font->Style сравнивается с одним и тем же значением FontStyle::Bold. Поскольку между ними стоит побитовый оператор (^) (исключающее ИЛИ), он будет назначать «Bold», если текущее состояние label1->Font->Style «не Bold». А если label1->Font->Style пребывает в состоянии «Bold», то оператор (^) будет назначать состояние «не Bold». Этот оператор еще называют логическим XOR.

Таблица истинности логического XOR такова:

A Xor B = C

0 Xor 0 = 0

1 Xor 0 = 1

0 Xor 1 = 1

1 Xor 1 = 0

В нашем случае мы имеем всегда B = 1 (FontStyle::Bold), а A (label1->Font->Style) попеременно то Bold, то Regular (то есть «не Bold»). Таким образом, оператор (^) всегда будет назначать противоположное тому, что записано в label1->Font->Style.

Как видно, применение побитового оператора привело к существенному уменьшению количества программного кода. Использование побитовых операторов может значительно упростить написание программ со сложной логикой.

Посмотрите, как работает программа, нажав клавишу F5.

Теперь добавим в форму еще один элемент управления CheckBox. Мы собираемся управлять стилем шрифта FontStyle двумя флажками. Один, как и прежде, задает полужирный стиль Bold или обычный Regular, а второй задает наклонный Italic или возвращает в Regular. Фрагмент новой программы приведен в листинге 1.6.

Листинг 1.6Усовершенствованный программный код

            // ...............

            // Программный код, расположенный выше, создан средой Visual Studio

            // автоматически, поэтому автором не приводится

            this->ResumeLayout(false);

            this->PerformLayout();

        }

#pragma endregion

        // Программа использует побитовый оператор "^" - исключающее ИЛИ

    private: System::

                 Void Form1_Load(System::Object^  sender, System::EventArgs^  e) 

             {

                 this->Text = "Флажок CheckBox";

                 checkBox1->Text = "Полужирный"; checkBox2->Text = "Наклонный";

                 label1->Text = "Выбери стиль шрифта";

                 label1->TextAlign = ContentAlignment::MiddleCenter;

                 label1->Font = gcnew System::Drawing::Font("Courier New",

                 14.0F);

             }

    private: System::Void checkBox1_CheckedChanged(System::Object^  sender,

                                                             System::EventArgs^  e)

Листинг 1.6 (продолжение)

             {

                 label1->Font = gcnew System::Drawing::Font(

                      "Courier New", 14.0F, label1->Font->Style ^

                      FontStyle::Bold);

             }

    private: System::Void checkBox2_CheckedChanged(System::Object^  sender,

                                                             System::EventArgs^  e) 

             {

                 label1->Font = gcnew System::Drawing::Font(

                    "Courier New", 14.0F, label1->Font->Style ^ 

                    FontStyle::Italic);

             }

    };

}

Как вы видите, здесь ничего принципиально нового нет, только лишь добавлена обработка события изменения состояния флажка CheckedChanged для CheckBox2. Фрагмент работы программы можно увидеть на рис. 1.13.

 

Рис. 1.13. Фрагмент работы усовершенствованной программы

Убедиться в работоспособности программы можно, открыв решение Флажок2.sln в папке Флажок2.

Пример 8. Вкладки TabControl и переключатели RadioButton

Вкладки программируют для организации управления и оптимального использования экранного пространства. Выразительным примером использования вкладок является диалоговое окно Internet Explorer Свойства обозревателя. То есть если требуется отобразить большое количество управляемой информации, то весьма уместно использовать вкладки TabControl.

Поставим задачу написать программу, позволяющую выбрать текст из двух вариантов, задать цвет и размер шрифта этого текста на трех вкладках TabControl с использованием переключателей RadioButton. Фрагмент работы программы приведен на рис. 1.14.

Программируя поставленную задачу, запустим Visual Studio и выберем приложение в среде CLR шаблона Windows Forms Application Visual C++. Назовем этот проект Вкладки. Используя панель элементов Toolbox, в форму перетащим с помощью мыши элемент управления TabControl. Как видно, по умолчанию имеем две вкладки, а по условию задачи, как показано на рис. 1.14, три вкладки. Добавить третью вкладку можно в конструкторе формы, а можно программно.

 

Рис. 1.14. Программа с переключателями и вкладками

Рассмотрим, как добавить третью вкладку в конструкторе. Для этого в свойствах (окно Properties) элемента управления tabControl1 выбираем свойство TabPages, в результате попадаем в диалоговое окно TabPage Collection Edit, где добавляем (кнопка Add) третью вкладку (первые две присутствуют по умолчанию). Эти вкладки нумеруются от нуля, то есть третья вкладка будет распознаваться как TabPages(2). Название каждой вкладки будем указывать в программном коде.

Для того чтобы вы могли в большей степени управлять всем процессом, рассмотрим, как добавить третью вкладку не в конструкторе, а в программном коде при обработке события загрузки формы (листинг 1.7). Однако прежде чем перейти на вкладку программного кода, для каждой вкладки выбираем из панели Toolbox по два переключателя RadioButton, а в форму перетаскиваем метку Label. Теперь с помощью щелчка правой кнопкой мыши в пределах формы переключаемся на редактирование программного кода.

Листинг 1.7Фрагмент программы, управляющей вкладками и переключателями

            // ...............

            // Программный код, расположенный выше, создан средой  Visual  Studio

            // автоматически, поэтому автором не приводится

            this->ResumeLayout(false);

            this->PerformLayout();

        }

#pragma endregion

        // Программа, позволяющая выбрать текст из двух вариантов, задать цвет

        // и размер шрифта для этого текста на трех вкладках TabControl

        // с использованием переключателей RadioButton

    private: System::

                 Void Form1_Load(System::Object^  sender, System::EventArgs^  e)

             {

                 // Создание третьей вкладки "программно":

                 auto tabPage3 = gcnew System::Windows::Forms::TabPage();

                 tabPage3->UseVisualStyleBackColor = true;

Листинг 1.7 (продолжение)

                 // Добавление третьей вкладки в существующий набор

                 // вкладок tabControl1:

                 this->tabControl1->Controls->Add(tabPage3);

                 // Добавление переключателей 5 и 6 на третью вкладку:

                 tabPage3->Controls->Add(this->radioButton5);

                 tabPage3->Controls->Add(this->radioButton6);

                 // Расположение переключателей 5 и 6: 

                 this->radioButton5->Location = System::Drawing::Point(20, 15);

                 this->radioButton6->Location = System::Drawing::Point(20, 58);

                 this->Text = "Какая улыбка вам ближе";

                 // Задаем названия вкладок:

                 tabControl1->TabPages[0]->Text = "Текст";

                 tabControl1->TabPages[1]->Text = "Цвет";

                 tabControl1->TabPages[2]->Text = "Размер";

                 // Эта пара переключателей изменяет текст:

                 radioButton1->Text =

                     "Восхищенная, сочувственная,\nскромно-смущенная";

                 radioButton2->Text = "Нежная улыбка, ехидная, бес" +

                     "стыжая,\nподленькая, снисходительная";

                 // или

                 // radioButton2->Text = "Нежная улыбка, бесстыжая," +

                 // Environment::NewLine + "подленькая, снисходительная";

                 // Эта пара переключателей изменяет цвет текста:

                 radioButton3->Text = "Красный";

                 radioButton4->Text = "Синий";

                 // Эта пара переключателей изменяет размет шрифта:

                 radioButton5->Text = "11 пунктов";

                 radioButton6->Text = "13 пунктов";

                 label1->Text = radioButton1->Text;

             }

    private: System::Void radioButton1_CheckedChanged(System::Object^  sender, 

                                                      System::EventArgs^  e) 

             {  label1->Text = radioButton1->Text;  }

    private: System::Void radioButton2_CheckedChanged(System::Object^  sender, 

                                                      System::EventArgs^  e) 

             {  label1->Text = radioButton2->Text;  }

    private: System::Void radioButton3_CheckedChanged(System::Object^  sender, 

                                                      System::EventArgs^  e) 

             {  label1->ForeColor = Color::Red;  }

    private: System::Void radioButton4_CheckedChanged(System::Object^  sender, 

                                                      System::EventArgs^  e) 

             {  label1->ForeColor = Color::Blue;  }

    private: System::Void radioButton5_CheckedChanged(System::Object^  sender, 

                                                      System::EventArgs^  e) 

             {  label1->Font = gcnew System::Drawing::

                                             Font(label1->Font->Name, 11);  }

    private: System::Void radioButton6_CheckedChanged(System::Object^  sender, 

                                                      System::EventArgs^  e) 

             {  label1->Font = gcnew System::Drawing::

                                             Font(label1->Font->Name, 13);  }

    };

}

Как видно из текста программы, при обработке события загрузки формы Form1_Load (этот участок программного кода можно было бы задать сразу после вызова процедуры InitializeComponent) создаем «программно» третью вкладку. Заметьте, что мы ее объявили как auto, то есть тип переменной tabPage3 выводится из выражения инициализации (как объявление var в C#) — это новая возможность в Visual C++ 2010. Далее добавляем новую вкладку tabPage3 в набор вкладок tabControl1, созданный в конструкторе. Затем «привязываем» пятый и шестой переключатели к третьей вкладке.

Дальнейшие установки очевидны и не требуют дополнительных комментариев. Заметим, что каждая пара переключателей, расположенных на каком-либо элементе управления (в данном случае на различных вкладках), «отрицают» друг друга, то есть если пользователь выбрал один, то другой переходит в противоположное состояние. Отслеживать изменения состояния переключателей удобно с помощью обработки событий переключателей CheckChanged (см. листинг 1.7). Чтобы получить пустой обработчик этого события в конструкторе формы, следует дважды щелкнуть на соответствующем переключателе и таким образом запрограммировать изменения состояния переключателей.

Убедиться в работоспособности программы можно, открыв решение Вкладки.sln в папке Вкладки.

Пример 9. Свойство Visible и всплывающая подсказка ToolTip в стиле Balloon

Продемонстрируем возможности свойства Visible (Видимый). Программа пишет в метку Label некоторый текст, а пользователь с помощью командной кнопки делает этот текст невидимым, а затем опять видимым и т.д. При зависании мыши над кнопкой появляется подсказка «Нажми меня».

Для программирования этой задачи запускаем Visual Studio 2010, далее, щелкая мышью на пунктах меню File\New\Project, выберем приложение в среде CLR шаблона Windows Forms Application Visual C++. Назовем этот проект Visible. Затем из панели элементов управления Toolbox в форму перетаскиваем метку Label, кнопку Button и всплывающую подсказку ToolTip. Только в этом случае каждый элемент управления в форме (включая форму) получает свойство ToolTip on Tip. Убедитесь в этом, посмотрев свойства (окно Properties) элементов управления.

Для кнопки button1 напротив свойства ToolTip on Tip мы могли бы написать «Нажми меня». Однако я предлагаю написать это непосредственно в программном коде. В этом случае программист не будет долго искатьсоответствующее свойство, когда станет применять данный фрагмент в своей новой программе!

Перейдем на вкладку программного кода — щелчок правой кнопкой мыши в пределах формы и выбор команды View Code. Окончательный текст программы представлен в листинге 1.8.

Листинг 1.8Свойство Visible и всплывающая подсказка ToolTip

            // ...............

            // Программный код, расположенный выше, создан средой  Visual  Studio

            // автоматически, поэтому автором не приводится

            this->ResumeLayout(false);

            this->PerformLayout();

        }

#pragma endregion

        // Программа пишет в метку Label некоторый текст, а пользователь

        // с помощью командной кнопки делает этот текст либо видимым, либо

        // невидимым. Здесь использовано свойство Visible. При зависании мыши

        // над кнопкой появляется подсказка "Нажми меня" в стиле Balloon

    private: System:: // Обработка события "загрузка формы":

                 Void Form1_Load(System::Object^  sender, System::EventArgs^  e) 

             {

                 Form1::Text = "Житейская мудрость";

                 label1->Text = "Сколько ребенка не учи хорошим манерам,\n" +

                                "он будет поступать так, как папа с мамой";

                 label1->TextAlign = ContentAlignment::MiddleCenter;

                 button1->Text = "Кнопка";

                 toolTip1->SetToolTip(button1, "Кнопка\r\nсчастья");

                 // Должна ли всплывающая подсказка использовать всплывающее

                 // окно:

                 toolTip1->IsBalloon = true;

                 // Если IsBalloon = false, то используется стандартное

                 // прямоугольное окно

             }

    private: System:: // Обработка события "щелчок на кнопке":

                 Void button1_Click(System::Object^  sender, System::EventArgs^  e)

             {        

                 // Можно программировать так:

                 // if (label1->Visible == true) label1->Visible = false;

                 // else label1->Visible = true;

                 // или так:

                 // label1->Visible = label1->Visible ^ true;

                 // здесь "^" - логическое исключающее ИЛИ,

                 // или совсем просто:

                 label1->Visible = !label1->Visible;

             }

    };

}

При обработке события загрузки формы свойству Text метки присваиваем некоторый текст, «склеивая» его с помощью знака «плюс» (+) из отдельных фрагментов. Использование в текстовой строке символов «\n» (или «\r\n») означает перенос текста на новую строку1 (это так называемый перевод строки). Можно переводить строку с помощью конструкции Environment::NewLine. В перечислении Environment можно выбрать и другие управляющие символы. Свойство метки TextAlign располагает текст метки по центру и посередине (MiddleCenter). Выражение, содержащее toolTip1, устанавливает (Set) текст всплывающей подсказки для кнопки button1 при «зависании» над ней указателя мыши (см. рис. 1.14). По умолчанию свойство IsBalloon пребывает в состоянии false, и при этом во всплывающей подсказке используется стандартное прямоугольное окно, установка IsBalloon = true переводит подсказку в стиль комиксов (в стиль Balloon) (рис. 1.15).

Чтобы в программном коде получить пустой обработчик события «щелчок мышью на кнопке», следует в дизайнере (конструкторе) формы (то есть на вкладке Form1.cs[Designer]) дважды щелкнуть на кнопке button1. При обработке этого события, как видно, закомментированы пять строчек, в которых записана логика включения видимости метки или ее выключение. Логика абсолютно понятна: если свойство видимости (Visible) включено (true), то его следует выключить (false); иначе (else) — включить.

 

Рис. 1.15. Фрагмент работы программы

Несколько путано, но разобраться можно. И все работает. Проверьте! Кнопку можно нажимать мышью, клавишей Enter и клавишей Пробел.

Однако можно пойти другим путем. Именно поэтому пять строчек этой сложной логики переведены в комментарий. Мы уже встречались с побитовым оператором ^ (исключающее ИЛИ). Напоминаю, что этот оператор, говоря кратко, выбирает «да» (true), сравнивая «нет» и «да», и выбирает «нет» (false), сравнивая «да» и «да». Однако можно еще более упростить написание программного кода:

label1->Visible  = ! label1->Visible;

То есть при очередной передаче управления на эту строчку свойство label1->Visible будет принимать противоположное значение. Вы убедились, что можно по-разному программировать подобные ситуации.

Как видно, мы использовали много закомментированных строчек программного кода. Очень удобно комментировать строки программного кода в редакторе Visual Studio 2010, вначале выделяя их, а затем использовать комбинацию клавиш Ctrl+K\C (Comment). Чтобы убрать с нескольких строк знак комментария, можно точно так же вначале отметить их, а затем воспользоваться другой комбинацией клавиш Ctrl+K\U (Uncomment).

Текст программы можно посмотреть, открыв решение Visible.sln в папке Visible.

Пример 10. Калькулятор на основе комбинированного списка ComboBox

Элемент управления ComboBox служит для отображения вариантов выбора в раскрывающемся списке. Продемонстрируем работу этого элемента управления на примере программы, реализующей функции калькулятора. Здесь для отображения вариантов выбора арифметических операций используется комбинированный список ComboBox.

Запустим Visual Studio 2010, выберем приложение в среде CLR шаблона Windows Forms Application Visual C++. Назовем этот проект Комби. Из панели Toolbox перетащим в форму два текстовых поля TextBox, кнопку Button, метку Label и комбинированный список ComboBox.

Текст программы представлен в листинге 1.9.

Листинг 1.9Суперкалькулятор

            // ...............

            // Программный код, расположенный выше, создан средой  Visual  Studio

            // автоматически, поэтому автором не приводится

            this->ResumeLayout(false);

            this->PerformLayout();

        }

#pragma endregion

        // Программа, реализующая функции калькулятора. Здесь для отображения

        // вариантов выбора арифметических действий используется комбинированный

        // список ComboBox

    private: System:: // Обработка события загрузки формы:

                 Void Form1_Load(System::Object^  sender, System::EventArgs^  e) 

             {

                 this->Text = "Суперкалькулятор"; label1->Text = "Равно: ";

                 button1->Text = "Выбери операцию";

                 comboBox1->Text = "Выбери операцию";

                 // Заполение (инициализация) раскрывающегося списка:

                 array<String^>^ Операции = {"Прибавить", "Отнять", 

                     "Умножить", "Разделить", "Очистить"};

                 // Инициализировать массив можно также таким образом:

                 // auto Операции = gcnew array<String^>{"Прибавить", "Отнять", 

                 //                        "Умножить", "Разделить", "Очистить"};

                 comboBox1->Items->AddRange(Операции);

                 comboBox1->TabIndex = 2;

                 textBox1->Clear(); textBox1->TabIndex = 0;

                 textBox2->Clear(); textBox2->TabIndex = 1;

             }

    private: System::Void comboBox1_SelectedIndexChanged(System::Object^ sender, 

                                                         System::EventArgs^  e) 

             { // Обработка события изменения индекса выбранного элемента

                 label1->Text = "Равно: ";

                 // Преобразование из строковой переменной в Single:

                 Single X, Y, Z = 0;

                 bool Число_ли1 = Single::TryParse(textBox1->Text,

                     System::Globalization::NumberStyles::Number,

                     System::Globalization::NumberFormatInfo::CurrentInfo, X);

                 bool Число_ли2 = Single::TryParse(textBox2->Text,

                     System::Globalization::NumberStyles::Number,

                     System::Globalization::NumberFormatInfo::CurrentInfo, Y);

                 if (Число_ли1 == false || Число_ли2 == false)

                 {

                     MessageBox::Show("Следует вводить числа!", "Ошибка",

                         MessageBoxButtons::OK, MessageBoxIcon::Error);

                     return;

                 }

                 // Оператор множественного выбора:

                 switch (comboBox1->SelectedIndex) 

                 { // Выбор арифметической операции:

                 case 0:   // Выбрали "Прибавить":

                     Z = X + Y; break;

                 case 1:   // Выбрали "Отнять":

                     Z = X - Y; break;

                 case 2:   // Выбрали "Умножить":

                     Z = X * Y; break;

                 case 3:   // Выбрали "Разделить":

                     Z = X / Y; break;

                 case 4:   // Выбрали "Очистить":

                     textBox1->Clear(); textBox2->Clear();

                     label1->Text = "Равно: "; return;

                 }

                 label1->Text = String::Format("Равно {0:F5}", Z);

             }

    private: System::Void button1_Click(System::Object^  sender, 

                                        System::EventArgs^  e) 

             { // Обработка события "щелчок на кнопке":

                 // "Принудительно" раскрываем список:

                 comboBox1->DroppedDown = true;

             }

    };

}

В данной программе сразу при обработке события загрузки формы присваиваем начальные значения некоторым свойствам, в том числе задаем коллекцию элементов комбинированного списка: «Прибавить», «Отнять» и т.д. Здесь также задаем табличные индексы TabIndex для текстовых полей и комбинированного списка. ­Табличный индекс определяет порядок обхода элементов. Так, при старте программы фокус будет находиться в первом текстовом поле, поскольку мы назначили textBox1->TabIndex = 0. Далее при нажатии пользователем клавиши Tab будет происходить переход от элемента к элементу соответственно табличным индексам (рис. 1.16).

 

Рис.1.16. Переход от одного текстового поля к другому

При обработке события «изменение индекса выбранного элемента» сomboBox1_SelectedIndexChanged с помощью функции TryParse проверяем, можно ли текстовые поля преобразовать в число. Первым параметром метода TryParse является анализируемое поле. Второй параметр — это разрешаемый для преобразования стиль числа, в данном случае тип Number, то есть десятичное число, которое имеет целую и дробную части. Третий параметр указывает, на какой основе формируется допустимый формат, в нашем случае мы использовали CurrentInfo, то есть на основе текущего языка и региональных параметров. По умолчанию при инсталляции русифицированной версии Windows разделителем целой и дробной частей числа является запятая. Однако эту установку можно изменить, если в Панели управления выбрать значок Язык и региональные стандарты, а затем на вкладке Региональные параметры щелкнуть на кнопке Настройка и на появившейся новой вкладке указать в качестве разделителя целой и дробной частей точку вместо запятой. В обоих случаях (и для запятой, и для точки) метод TryParse будет работать так, как указано на вкладке Региональные параметры.

Четвертый параметр метода TryParse возвращает результат преобразования. Кроме того, функция TryParse возвращает булеву переменную true или false, которая сообщает, успешно ли выполнено преобразование. Как видно из текста программы, если хотя бы одно поле невозможно преобразовать в число, то программируем сообщение «Следует вводить числа!» и выход из процедуры обработки события с помощью оператора return.

Далее оператор switch осуществляет множественный выбор арифметической операции в зависимости от индекса выбранного элемента списка SelectedIndex. Оператор switch передает управление той или иной метке case. Причем, как говорят программисты, оператор множественного выбора в С++ (C#, Turbo C) в отличие от других языков, например Basic, «проваливается», то есть управление переходит на следующую метку case, поэтому приходиться использовать оператор break для выхода из switch.

Последний оператор в процедуре обработки события изменения индекса выбранного элемента осуществляет формирование строки с помощью метода String::Format для вывода ее на метку label1. Формат «{0:F5}» означает, что значение переменной Z следует выводить по фиксированному формату с пятью знаками после запятой (или точки). Отметим, что в этом примере даже не пришлось программировать событие деления на ноль. Система Visual Studio сделала это за нас (см. рис. 1.16).

Последняя процедура обработки события «щелчок на кнопке» обеспечивает раскрытие комбинированного списка через нажатие на кнопку, а не на стрелку в элементе ComboBox. Эта возможность реализована с помощью метода DroppedDown объекта comboBox1.

Убедиться в работоспособности программы можно, открыв решение Комби.sln в папке Комби.

Пример 11. Вывод греческих букв, символов математических операторов.Кодовая таблица Unicode

Немного ликбеза. Хранение текстовых данных в памяти ЭВМ предполагает кодирование символов по какому-либо принципу. Таких кодировок несколько. Каждой кодировке соответствует своя таблица символов. В этой таблице каждой ячейке соответствуют номер в таблице и символ. Мы упомянем такие кодовые таблицы: ASCII, ANSI Cyrillic (другое название этой таблицы — Windows 1251), а также Unicode.

Первые две таблицы являются однобайтовыми, то есть каждому символу соответствует 1 байт данных. Поскольку в 1 байте — 8 битов, байт может принимать 28 = 256 различных состояний, этим состояниям можно поставить в соответствие 256 разных символов. Так в таблице ASCII от 0 до 127 — базовая таблица — есть английские буквы, цифры, знаки препинания, управляющие символы. От 128 до 255 — это расширенная таблица, в ней находятся русские буквы и символы псевдографики. Некоторые из этих символов соответствуют клавишам IBM-совместимых компьютеров. Еще эту таблицу называют «ДОСовской» по имени операционной системы MS-DOS, где она применяется. Эта кодировка встречается также иногда у некоторых веб-страниц.

В операционной системе Windows используется преимущественно ANSI (Windows 1251). Базовые символы с кодами от 0 до 127 в этих таблицах совпадают, а расширенные — нет. То есть русские буквы в этих таблицах находятся в разных местах таблицы. Из-за этого бывают недоразумения. В ANSI нет символов псевдографики. ANSI Cyrillic — другое название кодовой таблицы Windows 1251.

Существует также двухбайтовый стандарт Unicode. Здесь один символ кодируется двумя байтами. Размер такой таблицы кодирования — 216 = 65 536 ячеек. ­Кодовая таблица Unicode включает в себя практически все современные шрифты. Когда в текстовом редакторе MS Word мы выполняем команду Вставка\Символ, то вставляем символ из таблицы Unicode. В Блокноте также можно сохранять файлы в кодировке Unicode: Сохранить как Кодировка Юникод. В этом случае в Блокноте будут, например, греческие буквы, математические операторы Π, D, и пр. Кстати, греческой букве S и математическому оператору соответствуют разные коды в таблице Unicode. Размер файла при сохранении в Блокноте будет ровно в два раза б

...