Text
                    I
□
и
S
3
m
и
X
ВИКТОР ЗИБОРОВ
Visual
Basic 2010
Разработка веб-приложений
Создание веб-служб
и их клиентов
Разработка
Windows-приложений
для обработки текстовых?
табличных и графических
данных
Обработка баз данных
с использованием
технологии ADO.NET

Виктор Зиборов Visual Basic 2010 НА ПРИМЕРАХ Санкт-Петербург « БХВ-Петербург» 2010
УДК 681.3.06 ББК 32.973.26-018.2 3-59 Зиборов В. В. 3-59 Visual Basic 2010 на примерах. — СПб.: БХВ-Петербург, 2010. — 336 с.: ил. + CD-ROM ISBN 978-5-9775-0402-7 Рассмотрено более сотни типичных примеров, встречающихся в практи- ке реального программирования для платформы .NET Framework в среде Microsoft Visual Basic 2010: работа с экранной формой и элементами управ- ления, обработка событий мыши и клавиатуры, чтение/запись'текстовых и бинарных файлов, редактирование графических данных, управление буфе- ром обмена, ввод/вывод табличных данных, решение системы уравнений, использование функций MS Word, MS Excel и AutoCAD, обработка баз данных с использованием технологии ADO.NET, разработка веб-прило- жений, создание веб-служб и многое другое. Материал располагается по принципу от простого к сложному, что позволяет использовать книгу одно- временно как справочник для опытных и как пособие для начинающих про- граммистов. Компакт-диск содержит исходные коды примеров, приведен- ных в книге. Для программистов УДК 681.3.06 ББК 32.973.26-018.2 Группа подготовки издания: Главный редактор Зам. главного редактора Зав. редакцией Редактор Компьютерная верстка Корректор Дизайн серии Оформление обложки Зав. производством Екатерина Кондукова Игорь Шишигин Григорий Добин Анна Кузьмина Ольги Сергиенко Зинаида Дмитриева Игоря Цырульникова Елены Беляевой Николай Тверских Лицензия ИД № 02429 от 24.07.00. Подписано в печать 31.03.10. Формат 70х1001/1в. Печать офсетная. Усл. печ. л. 27,09. Тираж 2000 экз. Заказ № 145 "БХВ-ПетербурГ', 190005, Санкт-Петербург, Измайловский пр., 29. Санитарно-эпидемиологическое заключение на продукцию № 77.99.60.953 Д.005770.05.09 от 26.05.2009 г. выдано Федеральной службой по надзору в сфере защиты прав потребителей и благополучия человека. Отпечатано с готовых диапозитивов в ГУП "Типография "Наука" 199034, Санкт-Петербург, 9 линия, 12 ISBN 978-5-9775-0402-7 О Зиборов В. В., 2010 © Оформление, издательство "БХВ-Петербург", 2010
Оглавление Введение..............................................................9 Глава 1. Простейшие программы с экранной формой и элементами управления......................................................... 11 Пример 1. Форма, кнопка, метка и диалоговое окно......................11 ПРИМЕР 2. Событие MouseHover.........................................16 Пример 3. Ввод и вывод в консольном приложении.......................20 Пример 4. Проверка типа данных: функция IsNumeric....................23 Пример 5. Ввод данных через текстовое поле TextBox....................26 Пример 6. Ввод пароля в текстовое поле и изменение шрифта.............29 Пример 7. Управление стилем шрифта с помощью элемента управления Checkbox.............................................................31 Пример 8. Побитовый оператор Хог.....................................33 Пример 9. Вкладки TabControl и переключатели RadioButton.............35 Пример 10. Свойство Visible и всплывающая подсказка ToolTip..........38 Пример 11. Калькулятор на основе использования комбинированного списка ComboBox.............................................................40 Пример 12. Ссылка на другие ресурсы LinkLabel........................43 Пример 13. Греческие буквы, математические операторы. Символы Unicode.45 Глава 2. Инициирование и обработка событий мыши и клавиатуры..........51 Пример 14. Инициирование события в создаваемом классе................51 ПРИМЕР 15. Создание элемента управления Button программным способом и подключение события для него.......................................53 Пример 16. Координаты курсора мыши относительно экрана и элемента управления...........................................................55 Пример 17. Ассоциация нескольких элементов управления с одним событием с помощью Handles....................................................57 Пример 18. Калькулятор...............................................60
4 Оглавление Пример 19. Обработка событий клавиатуры..................................64 Пример 20. Контроль вводимых пользователем числовых данных при обработке события нажатия клавиши...................................................67 Глава 3. Чтение, запись текстовых и бинарных файлов, текстовый редактор........................................................69 Пример 21. Чтение/запись текстового файла в кодировке Unicode. Блоки Try... Catch..............................................................69 Пример 22. Чтение/запись текстового файла в кодировке Windows 1251........73 Пример 23. Простой текстовый редактор. Открытие и сохранение файла. Событие формы Closing.....................................................74 Пример 24. Простой RTF-редактор...........................................80 Пример 25. Печать текстового документа....................................84 Пример 26. Чтение/запись бинарных файлов с использованием потока данных..89 Глава 4. Редактирование графических данных................................93 Пример 27. Простейший вывод отображения графического файла в форму........93 Пример 28. Рисование в форме указателем мыши..............................96 Пример 29. Рисование в форме графических примитивов (фигур)...............99 Пример 30. Выбор цвета с использованием ListBox..........................102 Пример 31. Печать графических примитивов.................................105 Пример 32. Печать ВМР-файла..............................................106 Глава 5. Управление буфером обмена с данными в текстовом и графическом форматах...................................................109 Пример 33. Буфер обмена с данными в текстовом формате....................109 Пример 34. Элемент управления PictureBox. Буфер обмена с растровыми данными..................................................................111 Пример 35. Имитация нажатия комбинации клавиш <Alt>+<PrintScreen>........114 Пример 36. Запись содержимого буфера обмена в ВМР-файл...................116 ПРИМЕР 37. Использование таймера Timer...................................117 Пример 38. Запись в файлы текущих состояний экрана с интервалом 5 секунд.119 Глава 6. Ввод и вывод табличных данных. Решение системы уравнений................................................123 Пример 39. Формирование таблицы. Функция String.Format...................123 Пример 40. Форматирование Dow/j/е-переменных в виде таблицы. Вывод таблицы на печать. Поток StringReader............................................126 Пример 41. Вывод таблицы в Internet Explorer.............................130 Пример 42. Формирование таблицы с помощью элемента управления DataGridView.........................................................:.. 134 ПРИМЕР 43. Табличный ввод данных. DataGridView. DataTable. DataSet. Файл XML.................................................................136 Пример 44. Решение системы линейных уравнений. Ввод коэффициентов через DataGridView.......................................................140
Оглавление 5 Глава 7. Элемент управления WebBrowser...............................145 Пример 45. Отображение HTML-таблиц...................................145 Пример 46. Отображение Flash-файлов..................................147 Пример 47. Отображение Web-страницы и ее HTML-кода...................148 Глава 8. Использование функций MS Word, MS Excel, AutoCAD..............151 Пример 48. Проверка правописания в текстовом поле с помощью обращения к MS Word............................................................151 Пример 49. Вывод таблицы средствами MS Word..........................154 Пример 50. Обращение к функциям MS Excel из Visual Basic 2010........156 Пример 51. Использование финансовой функции MS Excel.................158 Пример 52. Решение системы уравнений с помощью функций MS Excel......161 ПРИМЕР 53. Построение диаграммы средствами MS Excel..................165 Пример 54. Управление функциями AutoCAD из программы на VB2010.......167 Глава 9. Обработка баз данных с использованием технологии ADO.NET..............................................................171 Пример 55. Создание базы данных SQL Server.............................171 Пример 56. Отображение таблицы базы данных SQL Server в экранной форме.173 Пример 57. Создание базы данных в среде MS Access....................175 Пример 58. Редактирование таблицы базы данных MS Access в среДе Visual Studio без написания программного кода...............................176 Пример 59. Отображение таблицы базы данных MS Access в экранной форме..178 Пример 60. Чтение всех записей из таблицы БД MS Access на консоль с помощью объектов Command и DataReader..............................180 Пример 61. Создание БД MS Access в программном коде..................182 Пример 62. Запись структуры таблицы в пустую БД MS Access. Программная реализация подключения к БД..........................................185 Пример 63. Добавление записей в таблицу базы данных MS Access........187 ПРИМЕР 64. Чтение всех записей из таблицы БД с помощью объектов Command, DataReader и элемента управления DataGridView........................189 Пример 65. Чтение данных из БД в сетку данных DataGridView с использованием объектов Command, Adapter и DataSet..................................191 Пример 66. Обновление записей в таблице базы данных MS Access........194 Пример 67. Удаление записей из таблицы БД с использованием SQL-запроса и объекта Command....................................................197 Глава 10. Другие задачи, решаемые с помощью Windows Forms Application............................................199 ПРИМЕР 68. Проверка вводимых данных с помощью регулярных выражений.....199 Пример 69. Управление прозрачностью формы..............................202 Пример 70. Время по Гринвичу в полупрозрачной форме..................203
6 Оглавление Пример 71. Создание ссылки на процесс, работающий в фоновом режиме, в форме значка в области уведомлений.................................207 Пример 72. Нестандартная форма. Перемещение формы мышью..............210 Пример 73. Проигрыватель Windows Media Player 11.....................212 ПРИМЕР 74. Программирование контекстной справки. Стандартные кнопки в форме..............................................................216 Пример 75. Создание инсталляционного пакета для распространения программы............................................................218 Глава 11, Программирование Web-ориентированных приложений на Visual Basic 2010.................................................221 Создание Web-страницы на языке HTML. Интернет-технологии.............221 Web-хостинг на платформах UNIX и Windows.........................223 Клиент-серверное взаимодействие на основе технологии ASP.NET.....223 Отладка активного Web-приложения.................................224 Пример 76. Создание простейшей активной Web-страницы на VB2010.......225 Пример 77. Проверка введенных пользователем числовых данных с помощью валидаторов..........................................................228 Пример 78. Проверка достоверности ввода имени, адреса e-mail, URL-адреса и пароля с помощью валидаторов.......................................231 ПРИМЕР 79. Регистрация и аутентификация пользователя с помощью базы данных Access...............................................................236 ПРИМЕР 80. Таблица с переменным числом ячеек, управляемая двумя раскрывающимися списками.......................................245 Пример 81. Организация раскрывающегося меню гиперссылок с помощью DropDownList.........................................................248 Пример 82. Передача данных между Web-страницами через параметры гиперссылки..........................................................250 Пример 83. Передача данных формы на другую Web-страницу методами класса Request.......................................................254 Пример 84. Передача значений элементов управления на другую Web-страницу с помощью объекта PreviousPage.......................................258 ПРИМЕР 85. Отображение табличных данных в Web-форме с помощью элемента управления Grid View.................................................261 Пример 86. Отображение в Web-форме хэш-таблицы.......................263 Пример 87. Чтение/запись текстового файла Web-приложением............266 Пример 88. Программирование счетчика посещений сайта с использованием базы данных и объекта Session........................................270 Пример 89. Чтение/запись cookie-файлов...............................275 Пример 90. Вывод изображения в Web-форму.............................279 Пример 91. Формирование изображения методами класса Graphics и вывод его в Web-форму..........................................................284 Пример 92. Гостевая книга............................................286 Пример 93. Отображение времени в Web-форме с использованием технологии AJAX......................................................292
Оглавление 7 Глава 12. Создание Web-служб и их клиентов........................295 О Web-службах.....................................................295 Пример 94. Клиентское приложение, потребляющее сервис Web-службы ’’Прогноз погоды”.................................................297 Пример 95. Создание простейшей Web-службы.........................301 ПРИМЕР 96. Создание Windows-приложения, потребителя сервиса Web-службы.304 ПРИМЕР 97. Web-служба "Торговая рекомендация на рынке Forex"......306 Пример 98. Клиентское приложение, потребляющее сервис Web-службы "Торговая рекомендация на рынке Forex"............................309 Пример 99. Клиентское Web-приложение, потребляющее сервис Web-службы "Морфер"..........................................................311 Пример 100. Получение данных от Web-службы Центрального банка РФ Web-приложением...................................................313 Пример 101. Получение данных от Web-службы Национального банка Республики Беларусь Windows-приложением......................... 315 Приложение. Описание компакт-диска................................319 Предметный указатель..............................................327

Введение Система разработки программного обеспечения Microsoft Visual Basic 2010 является хорошим средством быстрой разработки программ для ускоренно- го создания приложений для Microsoft Windows и Интернета. Целью книги является популяризация программирования. Автор стремился показать, как малой кровью можно написать, почти сконструировать, как в детском конст- рукторе, довольно-таки функционально сложные приложения. Для реализа- ции этой цели автор выбрал форму демонстрации "на примерах" решения за- дач от самых простых, элементарных до более сложных. Рассмотрены примеры программ с экранной формой и элементами управле- ния в форме, такими как текстовое поле, метка, кнопка и др. Написанные программы управляются событиями, в частности событиями мыши и кла- виатуры. Поскольку большинство существующих программ взаимодействует с дисковой памятью, в книге приведены примеры чтения и записи файлов в долговременную память. Описаны решения типичных задач, которые встре- чаются в практике программирования, в частности работа с графикой и буфе- ром обмена. Рассмотрены манипуляции табличными данными, использова- ние элемента управления WebBrowser для отображения различных данных. Приведены примеры программирования с помощью функций (методов) объ- ектных библиотек систем Microsoft Office и AutoCAD. Разобраны вопросы обработки баз данных SQL Server и MS Access с применением технологии ADO.NET, программирования Web-ориентированных приложений, а также использование и разработка Web-сервисов. Несколько слов об особенностях книги. Спросите у любого программиста, как он работает (творит...) над очередной поставленной задачей. Он вам ска- жет, что всю задачу он мысленно разбивает на фрагменты и вспоминает, в каких ситуациях он уже решал подобную задачу. Далее он просто копирует фрагменты отлаженного программного кода и вставляет их в новую задачу. Сборник таких фрагментов (101 пример) содержит данная книга. Автор пы-
10 Введение тался выделить наиболее типичные, актуальные задачи и решить их, с одной стороны, максимально эффективно, а с другой — кратко и выразительно. Вместе с книгой читателю предлагается компакт-диск с рассмотренными в ней примерами. Самая серьезная проблема в проектировании больших программ — это сложность, запутанность текстов. Из-за запутанности программ имеются ошибки, нестыковки и проч. Как следствие — страдает производительность процесса создания программ и их сопровождение. Решение этой проблемы состоит в структуризации программ. Появление объектно-ориентированного программирования связано в большой степени со структуризацией програм- мирования. Мероприятия для обеспечения большей структуризации — это проектирование программы как иерархической структуры, отдельные про- цедуры, входящие в программу, не должны быть слишком длинными, налага- ется запрет на использование операторов перехода goto и проч. Современные системы программирования разрешают в названиях переменных использо- вать русские буквы. Между тем современные программисты, как правило, не используют данную возможность, хотя когда вдруг в среде англоязычного текста появляются русские слова, это вносит большую выразительность в текст программы. Программный код начинает от этого лучше читаться, вос- приниматься человеком (транслятору, компилятору — все равно). Данная книга предназначена для начинающих программистов, программи- стов среднего уровня, а также для программистов, имеющих навыки про- граммирования на других языках и желающих ускоренными темпами освоить новый для себя язык Visual Basic 2010. Как пользоваться книгой? Эффектив- но пользоваться ею можно, последовательно решая примеры, в порядке их следования в книге, поскольку они расположены в последовательности от простого к более сложному, и тем самым постепенно совершенствуя свои навыки программирования на Visual Basic. А для программистов среднего уровня можно посоветовать искать выборочно именно те примеры, которые необходимы им при программировании их текущих задач. Надеюсь, что читатель получит одновременно удовольствие и пользу от ис- пользования этой книги в своей работе и творчестве. Свои впечатления о данной книге присылайте по адресу ziborov@ukr.net, я с удовольствием их почитаю.
ГЛАВА 1 Простейшие программы с экранной формой и элементами управления Пример 1. Форма, кнопка, метка и диалоговое окно После инсталляции системы программирования Visual Studio 2010, вклю- чающей в себя Visual Basic 2010 (далее VB2010), загрузочный модуль систе- мы devenv.exe будет, скорее всего, расположен в папке: C:\Program Files\Microsoft Visual Studio 10.0\Common7\lDE. Целесообразно создать ярлык на рабочем столе для запуска VB2010. После запуска увидим начальный пользовательский интерфейс, показанный на рис. 1.1. Чтобы запрограммировать какую-либо задачу, необходимо в пункте меню File выполнить команду New Project. В появившемся окне New Project в ле- вой колонке находится список инсталлированных шаблонов (Installed Templates). Среди них— шаблоны языков программирования, встроенных в Visual Studio, в том числе Visual Basic, Visual С#, Visual C++, Visual F# и др. Нам нужен язык Visual Basic. В средней колонке выберем шаблон (Templates) Windows Forms Application и щелкнем на кнопке ОК. В результате увидим окно, представленное на рис. 1.2. В этом окне изображена экранная форма — Forml, в которой программисты располагают различные компоненты графического интерфейса пользователя или, как их иначе называют, элементы управления. Это поля для ввода текста TextBox, командные кнопки Button, строчки текста в форме — метки Label, которые не могут быть отредактированы пользователем, и прочие элементы управления. Причем здесь используется самое современное так называемое
12 Гпава 1 Рис. 1.1. Фрагмент стартовой страницы системы Visual Studio 2010 Рис. 1.2. Окно для проектирования пользовательского интерфейса
Простейшие программы с экранной формой и элементами управления 13 визуальное программирование, предполагающее простое перетаскивание мышью из панели элементов Toolbox, где расположены всевозможные эле- менты управления, в форму. Таким образом, стараются свести к минимуму непосредственное написание программного кода. Ваша первая программа будет отображать такую экранную форму, в которой будет что-либо написано, например, "Microsoft Visual Basic20l0", также в форме будет расположена командная кнопка с надписью "Нажми меня". При нажатии кнопки появится диалоговое окно с сообщением "Всем привет!". Написать такую программку— вопрос 2—3 минут. Но вначале я хотел бы буквально двумя словами объяснить современный объектно-ориентиро- ванный подход к программированию. Подход заключается в том, что в про- грамме все, что может быть названо именем существительным, называют объектом. Так в нашей программе мы имеем четыре объекта: форму Form, надпись на форме Label, кнопку Button и диалоговое окно меззадевох с тек- стом "Всем привет!" (окно с приветом). Итак, добавьте метку и кнопку на форму примерно так, как показано на рис. 1.3. Рис. 1.3. Форма первого проекта Любой такой объект можно создавать самому, а можно пользоваться готовы- ми объектами. В данной задаче мы пользуемся готовыми визуальными объ- ектами, которые можно перетаскивать мышью из панели элементов управле- ния Toolbox. В этой задаче нам нужно знать, что каждый объект имеет свой- ства (properties). Например, свойствами кнопки являются (рис. 1.4): имя кнопки (Name)— Buttonl, надпись на кнопке (Text), расположение кнопки (Location) в системе координат формы х, Y, размер кнопки size и т. д. Свойств много, их можно увидеть, если щелкнуть правой кнопкой мыши в пределах формы и выбрать в контекстном меню команду Properties.
14 Гпава 1 Рис. 1.4. Свойства кнопки Buttonl Указывая мышью на все другие элементы управления в форме, можно про- смотреть их свойства: формы Forml и надписи в форме — метки Label 1. Вернемся к нашей задаче. Для объекта Label 1 выберем свойство Text и напи- шем напротив этого поля ’’Microsoft Visual Basic 2010” (вместо текста Labeii). Для объекта Buttonl также в свойстве Text напишем ’’Нажми меня". Кроме того, что объекты имеют свойства, следует знать, что объекты обраба- тываются событиями. Событием, например, является щелчок на кнопке, щел- чок в пределах формы, загрузка (Load) формы в оперативную память при старте программы и проч. В нашей задаче единственным событием, которым мы управляем, является щелчок по командной кнопке. Напомню, что после щелчка на кнопке должно появиться диалоговое окно, в котором написано: "Всем привет!”. Чтобы обработать это событие, необходимо написать всего одну строчку программного кода. Перейдем на вкладку для написания кода: щелчок правой кнопкой мыши в пределах формы, затем выбор команды View Code. Слева вверху мы видим раскрывающийся список, где перечислены объекты, кото- рые присутствуют в данном проекте. Здесь мы выберем Buttonl (командную кнопку). Справа вверху находится раскрывающийся список, в котором пере- числены все события для кнопки; выбираем событие Click. При этом управляющая среда VB2010 генерирует две строчки программного кода (рис. 1.5).
Простейшие программы с экранной формой и элементами управления 15 Рис. 1.5. Вкладка программного кода Таким образом, система VB2010 написала начало процедуры Sub обработки события Buttoni ciick и конец процедуры End Sub. Эти две строчки называют пустым обработчиком события. Заполним этот обработчик. Для этого меж- ду этими строчками пишем: MessageBox. Show (’’Всем привет! ”) Здесь вызывается метод (программа) Show объекта MessageBox с текстом ’’Всем привет!”. Таким образом, я здесь ’’нечаянно” проговорился о том, что объек- ты кроме свойств имеют также и методы. т. е. программы, которые обраба- тывают объекты. Рис. 1.6. Работающая программа
16 Гпава 1 В этих трех строчках мы написали процедуру обработки события нажатия кнопки (click) Buttonl. Теперь нажмем клавишу <F5> и проверим работоспо- собность программы (рис. 1.6). Пример 2. Событие MouseHover Немного усложним предыдущую задачу. Добавим еще одну обработку собы- тия MouseHover мыши для объекта Labeli. Событие MouseHover наступает то- гда, когда пользователь указателем мыши "зависает" над каким-либо объек- том, причем именно "зависает", а не просто перемещает мышь над объектом (от англ, hover — реять, парить). Есть еще событие MouseEnter (Войти), когда указатель мыши входит в пределы области элемента управления (в данном случае метки Label 1). Переключимся на вкладку программного кода Forml.vb. Вы видите, что у нас две вкладки: Forml.vb и Forml.vb [Design], т. е. вкладка программного кода и вкладка визуального проекта программы. Переключаться между ними можно мышью или нажатием комбинации клавиш <Ctrl>+<Tab>. Итак, запрограммируем событие MouseHover объекта Labeli. Для этого в окне редактора кода (где мы сейчас находимся) в левом верхнем раскрывающемся списке выбираем объект Labeli, а в правом — событие MouseHover. При этом среда VB2010 генерирует две строки программного кода (пустой обработ- чик): Private Sub Labell_MouseHover (Параметры процедуры. . .) End Sub Между этими двумя строчками вставляем вызов диалогового окна: MessageBox.Show("Событие Hover!") Теперь проверим возможности программы: нажимаем клавишу <F5>, "зави- саем" указателем мыши над Labeli, щелкаем на кнопке Buttonl. Все работает! А теперь я буду немного противоречить сам себе. Я говорил про визуальную технику программирования, направленную на минимизацию написания про- граммного кода. А сейчас хочу сказать про наглядность, оперативность, технологичность работы программиста. Посмотрите на свойства каждого объекта в окне Properties. Вы видите, как много строчек. Если вы меняете какое-либо свойство, то оно будет выделено жирным шрифтом. Удобно! Но все-таки еще более удобно свойства объектов назначать (устанавливать) в программном коде. Почему? Каждый программист имеет в своем арсенале множество уже отлаженных фрагментов, которые он использует в своей очередной новой программе. Программисту стоит лишь вспомнить, где он программировал ту или иную
Простейшие программы с экранной формой и элементами управления 17 ситуацию. Программа, которую написал программист, имеет свойство быстро забываться. Если вы посмотрите на строчки кода, которые писали три месяца назад, то будете ощущать, что многое забыли; если прошел год, то вы смот- рите на написанную вами программу, как на чужую. Поэтому при написании программ на первое место выходит понятность, ясность, очевидность напи- санного программного кода. Для этого каждая система программирования имеет какие-либо средства. Кроме того, сам программист придерживает- ся некоторых правил, помогающих ему работать производительно и эффек- тивно. Назначать свойства объектов в программном коде удобно при обработке со- бытия Formi Load, т. е. события загрузки формы в оперативную память при старте программы. На вкладке программного кода слева вверху выбираем (Forml Events), а справа— событие Load. А можно еще быстрей, просто сде- лать двойной щелчок в пределах формы на вкладке Forml.vb [Design]. При этом управляющая среда генерирует две строчки: Private Sub Forml_Load() End Sub Между этими двумя строчками обычно вставляют свойства различных объ- ектов и даже часто пишут много строчек программного кода. Здесь мы на- значим свойству Text объекта Labeli значение ’’Microsoft Visual Basic 2010": Labeli.Text = "Microsoft Visual Basic 2010" Аналогично для объекта Buttonl: Buttonl.Text = "Нажми меня!" Совершенно необязательно писать каждую букву приведенных команд. На- пример, для первой строчки достаточно написать "1а” (даже с маленькой бук- вы), уже это вызовет выпадающее меню, где вы сможете выбрать нужные для данного контекста ключевые слова. Это очень мощное и полезное современ- ное средство редактирования программного кода! Если вы от VB2010 пере- шли в другую систему программирования, в которой отсутствует данная функция, то будете ощущать сильный дискомфорт. Вы написали название объекта Labeli, поставили точку. Теперь вы видите выпадающее меню, где можете выбрать либо нужное свойство объекта, либо метод (т. е. подпрограмму). В данном случае вы выберите свойство Text. Как видите, не следует пугаться слишком длинных ключевых слов, длинных названий объектов, свойств, методов, имен переменных. Система подсказок современных систем программирования значительно облегчает всю нетвор- ческую работу. Вот почему в современных программах можно наблюдать такие длинные имена ключевых слов, имен переменных и проч. Потому что
18 Глава 1 на первое место выходит ясность, прозрачность программирования, а гро- моздкость программ компенсируется системой подсказок. Далее хотелось бы, чтобы слева вверху формы на синем фоне (в так называе- мой строке заголовка) была не надпись Forml, а что-либо осмысленное. На- пример, слово "Приветствие". Для этого ниже присваиваем эту строку свой- ству Text формы. Поскольку мы изменяем свойство объекта Forml внутри подпрограммы обработки события, связанного с формой, следует к форме обращаться через ссылку Me: Me.Text = "Приветствие" ИЛИ MyBase.Text = ’’Приветствие". После написания последней строчки кода мы должны увидеть на экране про- граммный код, показанный в листинге l.l. ......................... MUIMUIMUI МП Public Class Forml Private Sub Forml_Load(ByVai sender As Object, ByVai e As System.EventArgs) Handles Me.Load Labeli.Text = "Microsoft Visual Basic 2010" Buttonl.Text = "Нажми меня!" ’ Здесь объект Forml ссылается на себя — Me Me.Text = "Приветствие" End Sub Private Sub Buttonl_Click(ByVai sender As Object, ByVai e As System.EventArgs) Handles Buttonl.Click MessageBox.Show("Всем привет!") End Sub Private Sub Labell_MouseHover(ByVai sender As Object, ByVai e As System.EventArgs) Handles Labeli.MouseHover ’ Событие Hover, когда указатель мыши "завис" над меткой Labeli MessageBox.Show("Событие Hover!") End Sub End Class Комментарии, поясняющие работу программы, в окне редактора кода будут выделены зелёным цветом, чтобы в тексте выразительно отделять его от про- чих элементов программы. В VB комментарий пишут после одиночной ка- вычки (') или после ключевого слова rem (от англ, remark— примечание). Уважаемые читатели, даже если вам кажется весьма очевидным то, что вы пишете в программном коде, напишите комментарий. Как показывает опыт,
Простейшие программы с экранной формой и элементами управления 19 даже очень очевидный замысел программиста забывается удивительно быст- ро. Человеческая память отметает все, что по оценкам организма считается ненужным. Посмотрим еще раз на текст программы. Обратите внимание на то, что для улучшения читаемости программы второй параметр процедуры обработки события загрузки формы FormljLoad был перенесен на другую строку. При этом использован символ продолжения (_) для обозначения того, что остаток строки переносится на следующую строку. Замечу, что для обозначения пе- реноса строки символ продолжения можно не использовать, если при перено- се не разделять параметр процедуры, как это сделано, например, в процедуре обработки события щелчок на кнопке. Здесь запятая после первого параметра означает, что завершение строки нужно искать на следующей строке. В VB2010 существуют также ситуации, когда строку программного кода можно разрывать, а символ переноса (_) ставить не обязательно. Эти ситуа- ции с примерами приведены по адресу http://msdn.microsoft.com/en-us/ library/865x40k4(VS.100).aspx. В дальнейшем мы будем ориентироваться на эти допущения, в написании кода. Но если вы захотите использовать код в предыдущих версиях VB, вам придется использовать символ переноса. На рис. 1.7 приведена работа программы. Рис. 1.7. Работа программы Обычно в редакторах программного кода используется моноширинный шрифт, поскольку все символы такого шрифта имеют одинаковую ширину, в том числе точка и прописная русская буква "ИГ. По умолчанию в редакторе программного кода VB2010 задан шрифт Consolas. Однако если пользователь привык к шрифту Courier New, то настройку шрифта можно изменить, вы- брав меню Tools | Options | Environment | Fonts and Colors.
20 Гпава 1 Теперь закроем проект (File | Close Project). Система предложит нам сохра- нить проект, сохраним его под именем Hover. Теперь программный код этой программы можно посмотреть, открыв решение Hover.sln, в папке Hover. Пример 3. Ввод и вывод в консольном приложении Иногда, например для научных расчетов, требуется организовать какой- нибудь самый простой ввод данных, выполнить, может быть, весьма слож- ную математическую обработку введенных данных и оперативно вывести на экран результат вычислений. Такая же ситуация возникает тогда, когда большая программа отлаживается по частям. И для отладки вычислительной части совершенно не важен сервис при вводе данных. Можно по-разному организовать такую программу, в том числе программи- руя так называемое консольное приложение (от англ, console — пульт управ- ления). Под консолью обычно подразумевают экран компьютера и клавиа- туру. Для примера напишем консольное приложение, которое приглашает пользо- вателя ввести два числа, складывает их и выводит результат вычислений в диалоговое окно. Для этого запускаем VB2010, далее создаем новый проект (New Project), вы- бираем шаблон Console Application. После двойного щелчка на этом шабло- не попадаем сразу на вкладку программного кода (рис. 1.8). Рис 1.8. Вкладка программного кода
Простейшие программы с экранной формой и элементами управления 21 Как видите, здесь управляющая среда VB2010 приготовила четыре строки кода. Между sub Main о и End Sub мы можем вставлять собственный про- граммный код. Sub Main о — это стартовая точка, с которой начинается вы- полнение программы. В программе будут участвовать три переменные: х, y, z. х и у вводятся поль- зователем, далее z = х + у и z выводится в диалоговое окно со словами ’’Сумма Эти переменные следует объявить как single. Тип данных single применяется тогда, когда число, записанное в переменную, может иметь це- лую и дробную части. Переменная типа single занимает 4 байта. Объявление этих переменных на VB2010 может иметь такой вид: Dim X, Y, Z As Single При этом в отличие от Visual Basic версии 6 (VB6), все три переменные будут иметь тип Single. Далее используем объект console для ввода х: Console.WriteLine("Введите первое слагаемое:") X = Console.ReadLine() Аналогично для у: Console.WriteLine("Введите второе слагаемое:") Y = Console.ReadLine() Далее вычисление z: Z = X + Y Заметьте, каждую команду (оператор) традиционно пишут с нобой строчки. Если вы видите целесообразность написать несколько операторов в одной строке, то после каждого оператора надо ввести двоеточие (:). После вычисления суммы необходимо вывести z из оперативной памяти на экран. Для этого воспользуемся форматированным выводом в фигурных скобках метода WriteLine объекта Console: Console.WriteLine("{0} + {1} = {2}", X, Y, Z) Программа написана. Нажмите клавишу <F5>, чтобы увидеть результат. Вы видите, что все окна появляются на фоне черного окна. Вообще говоря, консольное приложение задумывалось, чтобы программировать в этом чер- ном окне. Вы можете попробовать, если вам это любопытно. Здесь ввод дан- ных организуют через функцию Console.WriteLine (листинг 1.2).
22 Гпава 1 Листинг 1.2. Ввод и вывод данных в консольном приложении ; Module Modulel Sub Main () Dim X, Y, Z As Single Console.Title = ’’Складываю два числа:” Console. WriteLine (’’Введите первое слагаемое: ”) X = Console.ReadLine() Console. WriteLine (’’Введите второе слагаемое: ’’) Y = Console.ReadLine() Z = X + Y Console.WriteLine(”{0} + {1} = {2}”, X, Y, Z) Console.Read() ’ Чтобы остановить и увидеть все, что на консоли End Sub End Module Такое программирование напоминает период конца 1980-х годов, когда по- явились первые персональные компьютеры с очень слабой производитель- ностью и небольшой памятью. Поэтому рекомендую пользоваться в консоль- ном приложении не объектом Console, а функциями InputBox И MsgBox. Для вывода данных Visual Basic, начиная с версии VB.NET, имеет удобное средство MessageBox. show, однако в консольном приложении его вызвать нельзя. Альтернативой MessageBox.Show может быть функция MsgBox, хорошо знакомая лицам, программировавшим на VB6: MsgBox("Сумма = " & Z) Функция MsgBox осталась в VB2010 и может применяться наряду с MessageBox.Show. Допустимо использовать MsgBox и в консольном приложе- нии. Заменив в консольном приложении все методы объекта console функ- циями InputBox и MsgBox, получим такой программный код, который очень напоминает VB6 (листинг 1.3). Листинг 1.3. Ввод и вывод данных в стиле VB6 Module Modulel Sub Main () Dim X, Y, Z As Single
Простейшие программы с экранной формой и элементами управления 23 X = Input Box (’’Введите первое слагаемое:”) Y = Input Box (’’Введите второе слагаемое:”) Z = X + Y MsgBox ("Сумма = ’’ & Z) End Sub End Module Кстати, в консольном приложении вместо MsgBox можно все-таки использо- вать MessageBox.Show. Для этого в пункте меню Project выбираем команду Add Reference, на вкладке .NET выбираем строку System.Windows.Forms, а затем в программном коде перед Module вставляем строку imports System.windows.Forms. Ключевое слово imports используется для импортиро- вания пространства имен, которое содержит класс MessageBox. При организации научных расчетов или в ситуации, когда необходимо отла- дить расчетную часть большой программы, когда сервис при вводе данных вообще не имеет значения, можно просто присваивать значения переменным при их объявлении. Очень технологичным является вариант, когда дан- ные записываются в текстовый файл с помощью, например, Блокнота (notepad.exe), а в программе предусмотрено чтение текстового файла в опера- тивную память. Пример 4. Проверка типа данных: функция IsNumeric В предыдущей программе при вводе данных пользователь может ошибочно вводить символы вместо чисел, поэтому целесообразно в этом случае предла- гать пользователю ввести дайные еще раз. При этом можно воспользоваться проверкой типа введенных данных с помощью функции IsNumeric (X) и веч- ным циклом Do <тело цикла> Loop. В программе это выглядит таким образом: Do ’ Вечный цикл, пока пользователь не введет именно число: X = InputBox("Введите первое слагаемое", "Суммирование") If IsNumeric(X) = True Then Exit Do Loop В этом фрагменте операторы, заключенные между Do и Loop, будут выпол- няться до тех пор, пока функция IsNumeric (X) не вернет значение True (Исти- на), т. е. введенное значение х является числом. Только в этом случае про- изойдет выход из цикла Exit Do. Кроме того, обе вводимые переменные сле- дует объявить как string, т. е. как строковые переменные: Dim X, Y As String
24 Гпава 1 Заметим, что при введении чисел, имеющих целую и дробную части в каче- стве разделителя, следует использовать запятую, а не точку1. Иначе функция IsNumeric будет воспринимать введенные символы как строку, а не число. Немножко изменим приведенный выше вечный цикл Do.. .Loop: Do X = InputBox("Введите первое слагаемое", "Суммирование") If IsNumeric(X) Then Exit Do Loop Здесь проверку на выход из цикла мы написали более компактно, словами эту проверку можно описать так: "Если х является числом, то выйти из цикла". Кроме того, обратите внимание на InputBox. Здесь у этой функции появился еще один параметр после запятой — "Суммирование". Этот текст будет в за- головке окна ввода. Аналогично организуем ввод Y. Законченный программ- ный код представлен в листинге 1.4. Листинг 1.4. Программный код с проверкой типа : Module Modulel ’ Эта программа проверяет, числовые ли данные ввел пользователь, ’ а затем складывает два введенных числа. Sub Main () Dim X, Y As String Do ' Вечный цикл, пока пользователь не введет именно число X = InputBox("Введите первое слагаемое", "Суммирование") If IsNumeric(X) = True Then Exit Do ' Проверка типа Loop Do Y = InputBox("Введите второе слагаемое", "Суммирование") If IsNumeric(Y) = True Then Exit Do Loop Dim Z As Single = Vai(X) + Vai(Y) Z = Convert.ToSingle(X) + Convert.ToSingle(Y) ' Возможности конвертирования в VB.NET и выше, в т. ч. VB 2010 ’ Z = СТуре(X, Single) + СТуре(Y, Single) ’ Z = Single.Parse(X) + Single.Parse(Y) 1 В общем случае десятичный разделитель задается в Панели управления. Если вы работаете в русифицированной версии Windows, то по умолчанию у вас в качестве такого разделителя действительно задана запятая. — Ред.
Простейшие программы с экранной формой и элементами управления 25 ' Конвертирование в VB6: Z = CSng(X) + CSng(Y) MsgBox ("Сумма = " & Z, , ’’Результат:") End Sub End Module В тексте программы после ввода двух чисел в строковые переменные х и Y объявляем переменную z как single, в переменную z будет копироваться сумма введенных чисел. Однако чтобы сложить эти два числа, их необходимо привести (преобразовать) также к типу single. Для преобразования строко- вых переменных в VB6 имелись удобные названия функций преобразования: CDbl(X), csng(X), cint (X). Они конвертируют (от англ, convert— преобразо- вать) строковую переменную х соответственно в переменную типа Double, single и integer. В VB6 имелась также функция Vai (X), однако она корректно конвертирует строковую переменную в числовой тип данных, если в качестве разделителя целой и дробной частей применяют десятичную точку (не запя- тую). Начиная с VB.NET, кроме этих функций в Visual Basic имеется класс Convert, который включает в себя функции преобразования типов. Поэтому использу- ем в нашей программе наиболее современную возможность преобразования Convert. ToSingie (х). Конвертировать переменные одного типа в переменные другого типа можно также и другими функциями, такими как стуре, Parse, конкретное использование этих функций приведено в тексте программы в комментарии (см. листинг 1.4). Для вывода результата сложения на экран используем функцию MsgBox, здесь она получила еще один параметр для более привлекательного дизайна. По- пробуем запустить эту программу, нажав клавишу <F5>, фрагмент работы этой программы показан на рис. 1.9. Рис 1.9. Фрагмент работы программы Если появились ошибки, то работу программы следует проверить отладчи- ком — клавиши <F8> или <F11>. В этом случае управление останавливается на каждом операторе, и вы можете проверить значение каждой переменной, наводя указатель мыши на переменные. Можно выполнить программу до оп- ределенной программистом точки (точки останова), используя, например,
26 Гпава 1 клавишу <F9> или оператор stop, и в этой точке проверить значения необхо- димых переменных. Текст этой программы можно посмотреть, открыв решение conso_input.sln в папке conso_input. Пример 5. Ввод данных через текстовое поле TextBox При работе с формой чаще всего ввод данных организуют через элемент управления текстовое поле TextBox. Напишем типичную программу, которая вводит через текстовое поле число, при нажатии командной кнопки извлекает из него квадратный корень и выводит результат на метку Label. В случае ввода не числа сообщает пользователю об этом, очищая текстовое поле. Есть еще одна кнопка Очистка для обнуления текстового поля и метки. Для этого запускаем VB2010, выбираем пункт меню File | New Project, за- тем — шаблон Windows Forms Application и щелкаем на кнопке ОК. Далее из панели элементов управления Toolbox в форму указателем мыши перетас- киваем текстовое поле TextBoxi, метку Labeli и две командные кнопки Buttoni и Button2. Таким образом, в форме будут находиться четыре элемента управления. Двойной щелчок в пределах проектируемой формы, и мы попадаем на вклад- ку программного кода в обработку события Formi_Load— события загрузки формы. Здесь задаем свойствам формы (к форме обращаемся посредством ссылки ме), кнопкам Buttoni и Button2, текстовому полю TextBoxi, метке Labeli следующие значения: Me.Text = "Извлечение квадратного корня" Buttoni.Text = "Извлечь корень"- Button2.Text = "Очистка" TextBoxi.Clear() ' Очистка текстового поля Labeli.Text = "" Labeli.TextAlign = ContentAlignment.MiddleCenter Последняя строка означает выравнивание текста, записанного в Labeli.Text, по центру и на середине метки. Нажмите клавишу <F5> для выявления возможных опечаток, т. е. синтакси- ческих ошибок и предварительного просмотра дизайна будущей программы. Далее программируем событие Buttoni ciick— щелчок мышью на кнопке Извлечь корень. Создать пустой обработчик этого события удобно, дважды щелкнув мышью на этой кнопке. Между двумя появившимися строчками
Простейшие программы с экранной формой и элементами управления 27 программируем диагностику правильности вводимых данных, конвертирова- ние строковой переменной в переменную типа single и непосредственное извлечение корня (листинг 1.5). ’ Программа вводит через текстовое поле число, при нажатии ’ командной кнопки извлекает из него квадратный корень и выводит ’ результат на метку Labeli. В случае ввода не числа сообщает ’ пользователю об этом, очищая текстовое поле. Есть еще одна кнопка ’ Очистка для обнуления текстового поля и метки. Public Class Forml Private Sub Forml_Load(ByVai sender As System.Object, ByVai e As System.EventArgs) Handles MyBase.Load Me.Text = ’’Извлечение квадратного корня” Buttonl.Text = "Извлечь корень" Button2.Text = "Очистка" TextBoxl.Clear() ’ Очистка текстового поля Labeli. Text = ’”’ Labeli.TextAlign = ContentAlignment.MiddleCenter End Sub Private Sub Buttonl_Click(ByVai sender As System.Object, ByVai e As System.EventArgs) Handles Buttonl.Click ’ Обработка события "щелчок на кнопке" Извлечь корень If Not IsNumeric(TextBoxl.Text) Then MessageBox.Show("Следует вводить числа", "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error) TextBoxl.Clear() ’ Очистка текстового поля TextBoxl.Focus() ’ Установить фокус на текстовом поле Exit Sub End If Dim X, Y As Single ’ Преобразование из строковой переменной в Single X - Convert.ToSingle(TextBo\l.Text) Y = Math.Sqrt(X) Labeli.Text = "Корень из " + X.ToString + ’’ равен " + Y.ToString End Sub Private Sub Button2_Click(ByVai sender As System.Object, ByVai e As System.EventArgs) Handles Button2.Click
28 Гпава 1 ’ Обработка события "щелчок на кнопке" Очистка: Label1.Text = "" TextBoxl.Clear() ’ Очистка текстового поля TextBoxl.Focus() End Sub End Class Здесь при обработке события "щелчок мышью на кнопке” Извлечь корень проводится проверка, введено ли число в текстовом поле. Проверка осущест- вляется с помощью функции isNumeric: если введено не число (например, введены буквы), то выводится диалоговое окно с текстом "Следует вводить числа” (рис. 1.10). Рис. 1.10. Диагностика правильности вводимых данных Далее, поскольку ввод неправильный, текстовое поле очищается — TextBoxl. clear (), а фокус передается опять на текстовое поле для ввода числа (т. е. курсор будет находиться в текстовом поле). Оператор Exit sub означает выход из программы обработки события Buttonl_Click. Если пользователь ввел число, то управление не пойдет на ветку if.. .Then, а будет выполняться следующий оператор Dim— объявление переменных х и Y. Обычно все объявления делают в начале подпрограммы, но удобно объявить переменную там, где она впервые используется. Далее функция convert.ToSingle конвертирует строковую переменную TextBoxl .Text в число х, из которого уже можно извлекать квадратный корень Math.sqrt (X). Математические функции VB2010 являются методами класса Math. Их можно увидеть, набрав Math и поставив точку (.). В выпадающем списке вы увидите множество математических функций: Abs, sin, Cos, Min и т. д. и два свойства — две константы е = 2,71... (основание натуральных логарифмов) и pi = 3,14... (число диаметров, уложенных вдоль окруж- ности).
Простейшие программы с экранной формой и элементами управления 29 Последней строчкой обработки события Buttoni ciick является присваивание переменной Labeli.Text длинного текста. Здесь символ + (можно также & — амперсанд) означает ’’сцепить” переменные в одну строку. Нажав клавишу <F5>, проверяем, как работает программа. Заметьте, что при вводе в текстовое поле числа, имеющего целую и дробную части, в качестве разделителя необходимо ставить запятую, а не точку. Иначе, введенное в текстовое поле не будет восприниматься как число. Аналогично обработаем событие Button2_ciick— очистка текстового поля и метки, а также передача фокуса опять на текстовое поле. Результат работаю- щей программы представлен на рис. 1.11. Рис. 1.11. Извлечение квадратного корня При необходимости используйте отладчик (клавиша <Fl l>) для пошагового выполнения программы и выяснения всех промежуточных значений перемен- ных путем "зависания” указателя мыши над переменными. Текст этой программы можно посмотреть, открыв решение sqrt.sln в папке sqrt. Пример 6. Ввод пароля в текстовое поле и изменение шрифта Это очень маленькая программа для ввода пароля в текстовое поле, причем при вводе вместо вводимых символов некто, "находящийся за спиной поль- зователя”, увидит только звездочки. Программа состоит из формы Forml, тек- стового поля TextBoxi, метки Labeli, куда для демонстрации возможностей мы будет копировать пароль (паспорт, т. е. секретные слова), и командной кнопки Buttoni — Покажи паспорт.
30 Гпава 1 Перемещаем в форму все названные элементы управления. Текст программы приведен в листинге 1.6. j Листинг 1.6. Ввод пароля ... = ’ Программа для ввода пароля в текстовое поле, причем при вводе вместо ' вводимых символов некто, ’’находящийся за спиной пользователя”, ’ увидит только звездочки Public Class Forml Private Sub Forml_Load(ByVai sender As System.Object, ByVai e As System.EventArgs) Handles MyBase.Load Me.Text = "Введи пароль" TextBoxl.Text = Nothing TextBoxl. PasswordChar = TextBoxl.Font = New System.Drawing.Font("Courier New", 9.0!) Labe11.Text = "" Label1.Font = New System.Drawing.Font("Courier New", 9.0!) Buttonl.Text = "Покажи паспорт" End Sub Private Sub Buttonl_Click(ByVai sender As System.Object, ByVai e As System.EventArgs) Handles Buttonl.Click ’ Обработка события "щелчок на кнопке" Label1.Text = TextBoxl.Text End Sub End Class Обрабатываем два события. Первое событие— загрузка формы Formi Load. Здесь очищаем текстовое поле и делаем его "защищенным от посторонних глаз" с помощью свойства TextBoxl.Passwordchar, каждый введенный пользо- вателем символ маскируется символом звездочки (*). Далее мы хотели бы для большей выразительности и читабельности программы, чтобы вводимые звездочки и результирующий текст имели одинаковую длину. Все символы шрифта Courier New имеют одинаковую ширину, поэтому его называют мо- ноширинным шрифтом. Кстати, используя именно этот шрифт, удобно про- граммировать таблицу благодаря одинаковой ширине букв этого шрифта. Еще одним широко используемым моноширинным шрифтом является шрифт Consola. Задаем шрифт, используя свойство Font обоих объектов: TextBoxl и Labeii. Число 9.0 означает размер шрифта. Осталось обработать событие Buttoni ciick— щелчок на кнопке. Здесь — банальное присваивание текста из поля тексту метки. Программа написана,
Простейшие программы с экранной формой и элементами управления 31 нажимаем клавишу <F5>. На рис. 1.12 приведен вариант работы данной про- граммы. Рис. 1.12. Вариант работы программы Убедиться в работоспособности программы можно, открыв решение passport.sln в папке passport. Пример 7. Управление стилем шрифта с помощью элемента управления CheckBox Кнопка CheckBox (Флажок) также находится на панели элементов управле- ния Toolbox. Флажок может быть либо установлен (содержит "галочку”), ли- бо сброшен (пустой). Напишем программу, которая управляет стилем шриф- та текста, выведенного на метку Label. Управлять стилем будем посредством флажка CheckBox. Используя панель инструментов, в форму поместим метку Labeli и флажок checkBoxi. В листинге 1.7 приведен текст программы управления этими объ- ектами. ’ Программа управляет стилем шрифта текста, выведенного на метку ’ Label, посредством флажка CheckBox Public Class Forml Private Sub Forml_Load(ByVai sender As System.Object, ByVai e As System.EventArgs) Handles MyBase.Load
32 Гпава 1 Me.Text = "Флажок CheckBox" CheckBoxl.Text = "Полужирный" CheckBoxl.Focus() Labeli.Text = "Выбери стиль шрифта" Labeli.TextAlign = ContentAlignment.Middlecenter Labeli.Font = New System.Drawing.Font("Courier New", 14.0!) End Sub Private Sub CheckBoxl_CheckedChanged(ByVai sender As System.Object, ByVai e As System.EventArgs) Handles CheckBoxl.CheckedChanged ’ Изменение состояния флажка на противоположное If CheckBoxl.Checked = True Then Labeli.Font = New Drawing.Font("Courier New", 14.0!, Fontstyle.Bold) If CheckBoxl.Checked = False Then Labeli.Font = New Drawing.Font("Courier New", 14.0!, Fontstyle.Regular) End Sub End Class При обработке события Fomi Load задаем начальные значения некоторых свойств объектов Formi, Labeli и CheckBoxl. Удобно получить пустой обра- ботчик этого события, дважды щелкнув в пределах формы. Между строчками Private Sub Fomi Load и End Sub присваиваем начальные значения некото- рым свойствам и запускаем методы объектов. Так, тексту флажка, выводимо- го с правой стороны, присваиваем значение ’’Полужирный”. Кроме того, при старте программы фокус должен находиться на флажке (CheckBoxl. Focus о), в этом случае пользователь может изменять установку флажка даже клавишей <Пробел>. Текст метки — ’’Выбери стиль шрифта”, выравнивание метки TextAlign зада- ем посередине и по центру (Middlecenter) относительно всего того места, что предназначено для метки. Задаем шрифт метки Courier New (в этом шрифте все буквы имеют одинаковую ширину) размером 14 пунктов. Изменение состояния флажка соответствует событию CheckedChanged. Чтобы получить пустой обработчик события CheckedChanged, следует дважды щелк- нуть на элементе CheckBoxl вкладки Forml.vb [Design]. Между соответст- вующими строчками следует записать (см. текст программы): если флажок установлен (т. е. содержит ’’галочку”) Checked = True, ТО ДЛЯ метки Labeli устанавливается тот же шрифт Courier New, 14 пунктов, но Bold, т. е. полу- жирный. Заметим, что в операторе условия после оператора присваивания (=) символ продолжения строки (_) необязателен.
Простейшие программы с экранной формой и элементами управления 33 Далее — следующая строчка кода: если флажок не установлен, т. е. CheckBoxl.Checked=False, ТО шрифт устанавливается Regular, Т. е. обычный. Очень часто эту ситуацию программируют, используя ключевое слово Else (Иначе), однако это выражение будет выглядеть более выразительно и понят- но так, как написали мы. Программа написана, нажмите клавишу <F5>. Проверьте работоспособность программы. В рабочем состоянии она должна работать примерно так, как по- казано на рис. 1.13. Рис. 1.13. Фрагмент работы программы управления стилем шрифта Убедиться в работоспособности программы можно, открыв решение CheckBoxl .sin в папке CheckBoxl. Пример 8. Побитовый оператор Хог Несколько изменим предыдущую программу в части обработки события checkedchanged (Изменение состояния флажка). Вместо двух условий if.. .Then напишем один оператор: Label1.Font = New System.Drawing.Font("Courier New", 14.0!, Label1.Font.Style Xor Fontstyle.Bold) Здесь каждый раз при изменении состояния флажка значение параметра Label 1. Font, style сравнивается с одним и тем же значением Font style. Bold. Поскольку между ними стоит побитовый оператор хог (Исключающее ИЛИ), он будет назначать Bold, если текущее состояние Label 1.Font.style ”не Bold”. А если Label 1.Font.style пребывает в состоянии ’’Bold", то хог будет назна- чать состояние "не Bold". Таблица истинности оператора хог такова: А Хог В = С 0 Хог 0=0 1 Хог 0=1 0 Хог 1=1 1 Хог 1=0 2 Зак 145
34 Гпава 1 В нашем случае мы имеем всегда в = 1 (Fontstyle. Bold), а а (Labeli.Font.Style) попеременно ТО Bold, ТО Regular (т. е. "не Bold"). Таким образом, оператор хог всегда будет назначать противоположное тому, что записано В Labeli. Font. Style. Как видно, применение побитового оператора привело к существенному уменьшению количества программного кода. Использование побитовых операторов может значительно упростить написание программ со сложной логикой. Посмотрите, как работает программа, нажав клавишу <F5>. Теперь добавим в форму еще один элемент управления CheckBox. Мы соби- раемся управлять стилем шрифта Fontstyle двумя флажками. Один, как и прежде, задает полужирный стиль Bold или обычный Regular, а второй задает наклонный italic или возвращает в Regular. Текст новой программы приве- ден в листинге 1.8. Ли*, тин? 1 программный код Public Class Forml Private Sub Forml_Load(ByVai sender As System.Object, ByVai e As System.EventArgs) Handles MyBase.Load Me.Text = "Флажок CheckBox" CheckBoxl.Text = "Полужирный" CheckBox2.Text = "Наклонный" Labeli.Text = "Выбери стиль /црифта" Labe11.TextAlign = ContentAlignment.Middlecenter Labeli.Font = New System.Drawing.Font("Courier New", 14.0!) End Sub Private Sub CheckBoxl_CheckedChanged(ByVai sender As System.Object, ByVai e As System.EventArgs) Handles CheckBoxl.CheckedChanged Labeli.Font = New System.Drawing.Font( "Courier New", 14.0!, Labeli.Font.Style Xor Fontstyle.Bold) End Sub Private Sub CheckBox2_CheckedChanged(ByVai sender As System.Object, ByVai e As System.EventArgs) Handles CheckBox2.CheckedChanged Labeli.Font = New System.Drawing.Font( "Courier New", 14.0!, Labeli.Font.Style Xor Fontstyle.Italic) End Sub End Class
Простейшие программы с экранной формой и элементами управления 35 Как видно, здесь принципиально ничего нового нет, только лишь добавлена обработка события изменения состояния флажка checkedchanged для CheckBox2. Фрагмент работы программы можно увидеть на рис. 1.14. Рис. 1.14. Фрагмент работы усовершенствованной программы Убедиться в работоспособности программы можно, открыв решение CheckBox2.sln в папке CheckBox2. Пример 9. Вкладки TabControl и переключатели RadioButton Вкладки используются для организации управления и оптимального распо- ложения экранного пространства. Выразительным примером использования вкладок является диалоговое окно Параметры Microsoft Word. То есть если требуется отобразить большое количество управляемой информации, то весьма уместно использовать вкладки TabControl. Поставим задачу написать программу, позволяющую выбрать текст из двух вариантов, задать цвет и размер шрифта этого текста на трех вкладках TabControl с использованием переключателей RadioButton. Фрагмент работы программы приведен на рис. 1.15. Рис. 1.15. Программа с переключателями и вкладками
36 Гпава 1 Программируя поставленную задачу, создадим новый проект Windows Forms Application, получим стандартную форму. Затем, используя панель Toolbox, в форму перетащим мышью элемент управления TabControl. Пла- нируем, как показано на рисунке, три вкладки. Для этого в свойствах (окно Properties) элемента управления TabControii выбираем свойство TabPages, в результате попадаем в диалоговое окно TabPage Collection Edit, где добав- ляем (кнопка Add) третью вкладку (первые две присутствуют по умолча- нию). Эти вкладки нумеруются от нуля, т. е. третья вкладка будет распозна- ваться как TabPages (2). Название каждой вкладки укажем при обработке со- бытия формы. Далее для каждой вкладки выбираем из панели Toolbox по два переключате- ля RadioButton, а в форму перетаскиваем метку Label. В свойстве AutoSize метки Label 1 указываем False. Теперь через щелчок правой кнопкой мыши в пределах формы переключаемся на редактирование программного кода. Текст программы приведен в листинге 1.9. Листинг 1.9. Использование вкладок и переключателей. :j ’ Программа, позволяющая выбрать текст из двух вариантов, задать ' цвет и размер шрифта для этого текста на трех вкладках TabControl ' с использованием переключателей RadioButton Public Class Forml Private Sub Forml_Load(ByVai sender As System.Object, ByVai e As System.EventArgs) Handles MyBase.Load ' Выбирайте улыбки, которые вам ближе MyBase.Text = ’’Какая улыбка Вам ближе" TabControii.TabPages(0).Text = "Текст" TabControii.TabPages(1).Text = "Цвет" TabControii.TabPages(2).Text = "Размер" RadioButtonl.Text = "Восхищенная, сочувственная, " & " скромно-смущенная " RadioButton2.Text = "Нежная улыбка, ехидная, " & "бесстыжая, подленькая, снисходительная" RadioButton3.Text = "Красный" RadioButton4.Text = "Синий" RadioButton5.Text = "11 пунктов" RadioButton6.Text = "13 пунктов" Label1.Text = RadioButtonl.Text End Sub
Простейшие программы с экранной формой и элементами управления 37 ’ Ниже обработки событий изменения состояния шести переключателей Private Sub RadioButtonl_CheсkedChanged(ByVai sender _ As System.Object, ByVai e As System.EventArgs) _ Handles RadioButtonl.CheckedChanged Labeli.Text = RadioButtonl.Text End Sub Private Sub RadioButton2_CheckedChanged(ByVai sender _ As System.Object, ByVai e As System.EventArgs) _ Handles RadioButton2.CheckedChanged Labeli.Text = RadioButton2.Text End Sub Private Sub RadioButton3_CheckedChanged(ByVai sender _ As System.Object, ByVai e As System.EventArgs) _ Handles RadioButton3.CheckedChanged Labeli.ForeColor = Color.Red End Sub Private Sub RadioButton4_CheckedChanged(ByVai sender _ As System.Object, ByVai e As System.EventArgs) _ Handles RadioButton4.CheckedChanged Labeli.ForeColor = Color.Blue End Sub Private Sub RadioButton5_CheckedChanged(ByVai sender _ As System.Object, ByVai e As System.EventArgs) _ Handles RadioButton5.CheckedChanged Labeli.Font = New Font(Labeli.Font.Name, 11) End Sub Private Sub RadioButton6_CheckedChanged(ByVai sender _ As System.Object, ByVai e As System.EventArgs) _ Handles RadioButton6.CheckedChanged Labeli.Font = New Font(Labeli.Font.Name, 13) End Sub End Class Как видно из текста программы, при обработке события загрузки формы Formi Load указываем название каждой из вкладок и тексты, связанные с каждым переключателем RadioButton. Далее при обработке события изме- нения СОСТОЯНИЯ переключателей CheckedChanged Задаем текст метки Labeli, цвет текста метки и размер шрифта.
38 Гпава 1 Убедиться в работоспособности программы можно, открыв решение Vkladki.sln в папке Vkladki. Пример 10. Свойство Visible и всплывающая подсказка ToolTip Продемонстрируем возможности свойства visible (Видимый). Программа пишет в метку Labeli некоторый текст, а пользователь с помощью командной кнопки делает этот текст невидимым, а затем опять видимым и т. д. При за- висании мыши над кнопкой появляется подсказка ’’Нажми меня”. Запускаем VB2010, далее выбираем пункты меню File | New Project] Windows Forms Application и нажимаем кнопку ОК. Затем из панели эле- ментов управления Toolbox в форму перетаскиваем метку Label, кнопку Button и всплывающую подсказку ToolTip. Только в этом случае каждый элемент управления в форме (включая форму) получает свойство ToolTip on Tip. Убедитесь в этом, посмотрев свойства (окно Properties) элементов управления. Для кнопки Buttonl напротив свойства ToolTip on Tip мы могли бы написать ’’Нажми меня”. Однако я предлагаю написать это непосредственно в про- граммном коде. В этом случае программист не будет долго искать соответст- вующее свойство, когда станет применять данный фрагмент в своей новой программе! Далее — щелчок правой кнопкой мыши в пределах формы и выбор команды View Code. Окончательный текст программы представлен в листинге 1.10. I Листинг 1.10. Свойство visible и всплывающая подсказка ToolTip ' : ’ Программа пишет в метку Label некоторый текст, а пользователь ’ с помощью командной кнопки делает этот текст либо видимым, либо ’ невидимым. Здесь использовано свойство Visible. При зависании мыши ’ над кнопкой появляется подсказка "Нажми меня" (свойство ToolTip). Public Class Forml Private Sub Forml_Load(ByVai sender As System.Object, ByVai e As System.EventArgs) Handles MyBase.Load Me.Text = "Житейская мудрость" Labeli.Text = "Сколько ребенка не учи хорошим манерам," & vbCrLf & "он будет поступать так, как папа с мамой"
Простейшие программы с экранной формой и элементами управления 39 Labeli.TextAlign = ContentAlignment.MiddleCenter Buttoni.Text = "Кнопка" ToolTipl.SetToolTip(Buttoni, "Нажми меня") End Sub ’ Обработка события "щелчок на кнопке": Private Sub Buttonl_Click(ByVai sender As System.Object, ByVai e As System.EventArgs) Handles Buttoni.Click 'If Labeli.Visible = True Then ' Labeli.Visible = False 'Else ' Labeli.Visible = True 'End If 'Labeli.Visible = Labeli.Visible Xor True Labeli.Visible = Not Labeli.Visible End Sub End Class При обработке события Formi Load свойству метки Text присваиваем некото- рый текст, ’’склеивая” его с помощью амперсанда (&) из отдельных фрагмен- тов. Системная константа vbCrLf начинает текст с новой строки (это так на- зываемый перевод каретки). Эту константу удобно также вызывать из пере- числения controlchars. В этом перечислении можно выбрать и другие управляющие символы. Свойство метки TextAlign располагает текст метки по центру и посередине (Middlecenter). Выражение, содержащее ToolTipl, уста- навливает (set) текст всплывающей подсказки для кнопки Buttoni при ’’зави- сании” над ней указателя мыши (рис. 1.16). Рис. 1.16. Фрагмент работы программы Еще одно событие— Buttoni ciick, щелчок мышью на кнопке. Здесь, как видно, закомментированы пять строчек, в которых записана логика включе- ния видимости метки или ее выключение. Логика абсолютно понятна: если
40 Гпава 1 свойство видимости (visible) включено (True), то его следует выключить (False); иначе (Else) — включить. Несколько путано, но разобраться можно. И все работает. Проверьте! Кнопку можно нажимать мышью, клавишей <Enter> и клавишей <Пробел>. Однако можно пойти другим путем. Именно поэтому пять строчек этой сложной логики переведены в комментарий. Мы уже встречались с побито- вым оператором хог (Исключающее ИЛИ). Напоминаю, что этот оператор, говоря кратко, выбирает "да" (True), сравнивая "нет" и "да", и выбирает "нет" (False), сравнивая "да" и "да". Однако можно еще более упростить написание программного кода: Labell.Visible = Not Labell.Visible To есть при очередной передаче управления на эту строчку свойство Labell.visible будет принимать противоположное значение. Вы убедились, что можно по-разному программировать подобные ситуации. На рис. 1.16 приведен фрагмент работы этой программы. Текст программы можно посмотреть, открыв решение Xor.sln в папке Хог. Пример 11. Калькулятор на основе использования комбинированного списка ComboBox Элемент управления СотЬоЁох используется для отображения вариантов выбора в выпадающем списке. Продемонстрируем работу этого элемента управления на примере программы, реализующей функции калькулятора. Здесь для отображения вариантов выбора арифметических операций исполь- зуется комбинированный список ComboBox. После запуска VB2010 и выбора шаблона Windows Forms Application из панели Toolbox перетащим в форму два текстовых поля TextBox, метку Label и комбинированный список ComboBox. Текст программы представлен в листинге 1.11. Листинг 1Л1, Суперкалькулятор . ’ Программа, реализующая функции калькулятора. Здесь для отображения ’ вариантов выбора арифметических действий используется комбинированный ’ список ComboBox Public Class Forml Private Sub Forml_Load(ByVai sender As System.Object, ByVai e As System.EventArgs) Handles MyBase.Load
Простейшие программы с экранной формой и элементами управления 41 ComboBoxl.Text = "Выбери операцию" ComboBoxl.Items.AddRange(New Object() {"Прибавить", "Отнять", "Умножить", "Разделить", "Очистить"}) ComboBoxl.Tabindex = 2 TextBoxl.Clear() : TextBox2.Clear() TextBoxl.Tabindex = 0 : TextBox2.Tabindex = 1 Me.Text = "Суперкалькулятор" Labe11.Text = "Равно: " End Sub ’ Обработка события изменения индекса выбранного элемента Private Sub ComboBoxl_SelectedIndexChanged(ByVai sender As System. Object, ByVai e As System.EventArgs) Handles ComboBoxl. SelectedlndexChanged Labe11.Text = "Равно: " If Not IsNumeric(TextBoxl.Text) Or Not IsNumeric(TextBox2.Text) Then MessageBox.Show("Следует вводить числа!",' "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error) Exit Sub End If Dim result As Single Select Case ComboBoxl.Selectedlndex ' Выбор арифмет. операции: Case 0 ’ Выбрали "Прибавить": result = СТуре(TextBoxl.Text, Double) + СТуре(TextBox2.Text, Double) ’ или result = CDbl(TextBoxl.Text) + CDbl(TextBox2.Text) Case 1 ’ Выбрали "Отнять": result = СТуре(TextBoxl.Text, Double) - СТуре(TextBox2.Text, Double) Case 2 ’ Выбрали "Умножить": result = СТуре(TextBoxl.Text, Double) * СТуре(TextBox2.Text, Double) Case 3 ' Выбрали "Разделить": result = СТуре(TextBoxl.Text, Double) / СТуре(TextBox2.Text, Double) Case 4 ’ Выбрали "Очистить": TextBoxl.Clear() : TextBox2.Clear() Labeli.Text = "Равно: " : Exit Sub End Select Labeli.Text = Labeli.Text + result.ToString End Sub End Class
42 Гпава 1 В этой программе обрабатываем два события: загрузка формы Formi Load и изменение индекса выбранного элемента ComboBoxl_SelectedIndexChanged. При загрузке формы присваиваем начальные значения некоторым свойствам, в том числе задаем коллекцию элементов комбинированного списка: "Приба- вить", "Отнять" и т. д. Здесь также задаем табличные индексы для текстовых полей и комбинированного списка Tabindex. Табличный индекс определяет порядок обхода элементов. Так, при старте программы фокус будет находиться в первом текстовом поле, поскольку мы назначили TextBoxl.Tabindex = о. Далее при использовании пользователем клавиши <ТаЬ> будет происходить переход от элемента к элементу соответственно табличным индексам (рис. 1.17). Рис. 1.17. Переход от одного текстового поля к другому При обработке события изменение индекса выбранного элемента ComboBoxl_Selected!ndexChanged С ПОМОЩЬЮ функции IsNumeric проверяем, можно ли текстовые поля преобразовать в число. Если хотя бы одно поле не- возможно преобразовать в число, то программируем сообщение ’’Следует вводить числа!” и выход из процедуры обработки события с помощью Exit Sub. Далее оператор select case осуществляет множественный выбор ариф- метической операции в зависимости от индекса выбранного элемента списка Seiectedindex. Для преобразования значений строковых переменных в число- вой тип Double автором использована функция стуре. В комментарии показа- на возможность использования функции CDbi для этой же цели. Заметьте, в этом примере даже не пришлось программировать событие деле- ния на ноль. Система Visual Basic сделала это за нас (см. рис. 1.17). Убедиться в работоспособности программы можно, открыв решение ComboBox_Calc.sln в папке ComboBox Calc.
Простейшие программы с экранной формой и элементами управления 43 Пример 12. Ссылка на другие ресурсы LinkLabel Элемент управления LinkLabel позволяет создавать в форме ссылки на Web- страницы, подобно гиперссылкам в HTML-документах, ссылки на открытие файлов какими-либо программами, ссылки на просмотр содержания логиче- ских дисков, папок и проч. Напишем программу, которая с помощью элемента управления LinkLabel обеспечит ссылку для посещения почтового сервера www.mail.ru, ссылку для просмотра папки C:\Windows\ и ссылку для запуска текстового редактора Блокнот. Для программирования этой задачи после запуска VB2010 выберем шаблон Windows Forms Application, затем из панели Toolbox перетащим в форму три элемента управления LinkLabel. Равномерно разместим их в форме. Да- лее, следуя нашим традициям, не задаем никаких свойств этим элементам в окне Properties. Все начальные значения свойств укажем в программном ко- де при обработке события загрузки формы Fomi Load (листинг 1.12). ? Листинг 1.12. Ссылки на ресурсы \ ’ Программа обеспечивает ссылку для посещения почтового сервера ’ www.mail.ru, ссылку для просмотра папки C:\Windows\ и ссылку для ' запуска текстового редактора Блокнот с помощью элемента управления ’ LinkLabel Public Class Forml Private Sub Forml_Load(ByVai sender As System.Object, ByVai e As System.EventArgs) Handles MyBase.Load Me.Text = "Щелкните по ссылке:" LinkLabell.Text = "www.mail.ru" LinkLabel2.Text = "Папка C:\Windows\" LinkLabel3.Text = "Вызвать " & ChrW(34) & "Блокнот" & ChrW(34) Me.Font = New System.Drawing.Font("Courier New", 12.0!) LinkLabell.LinkVisited = True LinkLabel2.LinkVisited = True LinkLabel3.LinkVisited = True End Sub ’ Обработка события "щелчок на какой-либо ссылке" Private Sub Link_Clicked(ByVai sender As System.Object, ByVai e As _ System.Windows.Forms.LinkLabelLinkClickedEventArgs) _ Handles LinkLabell.LinkClicked, LinkLabel2.LinkClicked, LinkLabel3.LinkClicked
44 Гпава 1 Dim s As String = sender.ToString.Substring(38, 1) ’ -или ...Ctype(sender, Button).Text... Select Case s ’ Выбор ссылки: Case "w" System.Diagnostics.Process.Start( "IExplore.exe", "http://www.mail.ru") Case "П" System.Diagnostics.Process.Start("C:\Windows\") Case "B" System.Diagnostics.Process.Start("Notepad", "text.txt") End Select End Sub End Class Как видно из программного кода, в свойстве Text каждой из ссылки LinkLabel задаем текст, из которого пользователь поймет назначение каждой ссылки. В задании свойства Text ссылки LinkLabei3 для того, чтобы слово ’’Блокнот” было в двойных кавычках, используем функцию ChrW(34). Эта функция возвращает символ, соответствующий указанному коду (34) символа в кодировке Unicode. В данном случае функция chrw(34) возвращает символ ’’двойная кавычка” ("). Для большей выразительности задаем шрифт Courier New, 12 пунктов. Поскольку свойство Linkvisited = True, то соответствую- щая ссылка отображается как уже посещавшаяся (изменяется цвет). Чтобы обрабатывать событие Click по каждой из ссылок, создадим один пус- той обработчик, например, на вкладке Design дважды щелкнув на любой из ссылок. Вообще говоря, здесь требуется программировать три таких обработ- чика, но в этом случае программный код будет выглядеть слишком громозд- ким (хотя структура кода будет простой). Поступим следующим образом, бу- дем обрабатывать эти три события одной процедурой. Назовем эту процедуру (см. ЛИСТИНГ 1.12) Link ClickedO, а ПОСЛе ключевого слова Handles перечис- лим через запятую все три события, которые мы хотим обрабатывать в этой процедуре. Далее, так же как и в программе о трех кнопках и калькуляторе, в зависимо- сти ОТ объекта (ссылки), создающего события (LinkLabel 1, LinkLabel2, LinkLabel?), мы вызываем одну из трех программ: либо Internet Explorer, либо Windows Explorer, либо Блокнот. Информация об объекте, создающем собы- тие Click, записана в объектную переменную sender. Она позволяет распо- знавать объекты (ссылки), создающие события. Чтобы ’’вытащить” эту информацию из sender, в строковом представлении (ToString) объектной переменной sender с помощью функции Substring выделим подстроку с па- раметрами (38, 1). Указанные параметры означают, что следует выделить в подстроку один символ, начиная с 38-й позиции.
Простейшие программы с экранной формой и элементами управления 45 Рис. 1.18. Ссылки на ресурсы На 38-м месте находится первая буква свойства Text каждой из ссылок, на- пример, для первой ссылки www.mail.ru, на 38-м месте находится буква "w". По первым буквам каждой из ссылок идентифицируем ссылку и с помощью метода start вызываем либо Internet Explorer, либо Windows Explorer, либо Блокнот. Вторым параметром метода start является имя ресурса, подлежа- щее открытию. Именем ресурса может быть или название Web-страницы, или имя текстового файла. Вызов (запуск) исполняемых файлов помимо метода start может быть осу- ществлен также командой shell, например, таким образом: Shell("notepad C:\textl.txt", AppWinStуle.MaximizedFocus) Фрагмент работы обсуждаемой программы приведен на рис. 1.18. Убедиться в ее работоспособности можно, открыв решение Link.sln в папке Link. Пример 13. Греческие буквы, математические операторы. Символы Unicode Немного ликбеза. Хранение текстовых данных в памяти ЭВМ предполагает кодирование символов по какому-либо принципу. Таких кодировок несколько. Каждой кодировке соответствует своя таблица символов. В этой таблице каждой ячейке соответствует номер в таблице и символ. Мы упомянем такие кодовые таблицы: ASCII, ANSI Cyrillic (другое название этой таблицы Windows 1251), а также Unicode. Первые две таблицы являются однобайтовыми, т. е. каждому символу соот- ветствует I байт данных. Поскольку в 1 байте — 8 битов, байт может прини- мать 28 = 256 различных состояний, этим состояниям можно поставить в соответствие 256 различных символов. Так в таблице ASCII от 0 до 127 — базовая таблица — есть английские буквы, цифры, знаки препинания, управ- ляющие символы. От 128 до 255 — это расширенная таблица, в ней находят-
46 Гпава 1 ся русские буквы и символы псевдографики. Некоторые из этих символов соответствуют клавишам IBM. Еще эту таблицу называют ’’ДОСовской” по имени операционной системы DOS, где она используется. Эта кодировка ис- пользуется также в Интернете. В операционной системе Windows используется преимущественно ANSI (Windows 1251). Базовые символы с кодами от 0 до 127 в этих таблицах сов- падают, а расширенные— нет. То есть русские буквы в этих таблицах нахо- дятся в разных местах таблицы. Из-за этого бывают недоразумения. В ANSI нет символов псевдографики. ANSI Cyrillic — другое название кодовой таб- лицы Windows 1251. Существует также двухбайтовый стандарт Unicode. Здесь один символ ко- дируется двумя байтами. Размер такой таблицы кодирования— 2|6 = = 65 536 ячеек. Unicode включает в себя практически все современные пись- менности. Разве что здесь нет старославянских букв. Когда в текстовом ре- дакторе MS Word мы выполняем команду Вставка | Символа, то вставляем символ из таблицы Unicode. Также в Блокноте можно сохранять файлы в ко- дировке Unicode: Сохранить как | Кодировка Юникод. В этом случае в Блокноте будут, например, греческие буквы, математические операторы П, А, У и др. Кстати, греческая буква S и математический оператор Е занимают разные ячейки в. Unicode. Размер файла при сохранении в Блокноте будет в два раза больше. Напишем программу, которая приглашает пользователя ввести радиус Л, чтобы вычислить длину окружности. При программировании этой задачи длину окружности в метке Label называем греческой буквой Р, приводим формулу для вычислений с греческой буквой тс = 3.14. Результат вычислений выведем в диалоговое окно MessageBox также с греческой буквой. После традиционного запуска VB2010 и выбора шаблона Windows Forms Application перетащим в форму метку Label и текстовое поле TextBox. По- смотрите на рис. 1.19, так должна выглядеть форма после программирования этой задачи. Кстати, поскольку на метке Labeli мы располагаем несколько строчек текста, в свойстве AutoSize метки Labeli укажем False. Вывод греческих букв на метку Labeli и в диалоговое окно MessageBox можно осуществить, например, таким путем. В текст программы через буфер обмена вставляем греческие буквы из текстового редактора MS Word. В этом случае VB.NET требовал ’’Save with UNICODE encoding”, т. e. записи файла Froml.vb в кодировке Unicode. Однако VB2010 сохраняет файлы vb-файлы в формате Unicode по умолчанию. Заметьте, что такой возможности в VB6 не было. Более технологично пойти другим путем, а именно вставлять подобные сим- волы с помощью функции chrw, а на вход этой функции подать номер симво-
Простейшие программы с экранной формой и элементами управления 47 ла в таблице Unicode. Этот номер легко выяснить, выбрав в редакторе MS Word пункты меню Вставка | Символ. Здесь в таблице следует найти этот символ и соответствующий ему код знака в шестнадцатеричном представле- нии. Чтобы перевести шестнадцатеричное представление в десятичное, сле- дует перед шестнадцатеричным числом поставить &н. Например, после вы- полнения оператора n = &НЗВ2 в переменной п будет записано десятичное число 946. На этом месте в таблице Unicode расположена греческая буква 0. Рис. 1.19. Фрагмент работы программы, использующей символы Unicode Именно таким образом мы программировали данную задачу (листинг 1.13). Листинг 1.13, Использование символов Unicode ’ Программа демонстрирует возможность вывода в форму, а также в ’ диалоговое окно MessageBox греческих букв. Программа приглашает ’ пользователя ввести радиус R, чтобы вычислить длину окружности Public Class Forml Private Sub Forml_Load(ByVai sender As System.Object, ByVai e As System.EventArgs) Handles MyBase.Load Me.Font = New System.Drawing.Font("Times New Roman", 12.0!) Me.Text = "Греческие буквы'
48 Гпава 1 Labeli.Text = "Найдем длину окружности:" & vbCrLf & ChrW(&H3B2) & " = 2" & ChrW(&H2219) & ChrW(&H3C0) & ChrW(&H2219) & "R," & vbCrLf & "где " & ChrW(&H3C0) & " = " & Math.PI & vbCrLf & vbCrLf & " Введите радиус R:" TextBoxi.Clear() End Sub Private Sub TextBoxl_KeyDown(ByVai sender As Object, ByVai e As _ System.Windows.Forms.KeyEventArgs) Handles TextBoxi.KeyDown Dim beta As Decimal ’ Если пользователь нажал клавишу <Enter>: ’ If e.KeyCode = Keys.Return Then If e.KeyData = Keys.Return Then ' Проверка — число ли введено: If IsNumeric(TextBoxi.Text) = False Then _ MessageBox.Show("Вводите число") : Exit Sub beta = 2 * Math.PI * CType(TextBoxi.Text, Decimal) ' ChrW(&H3B2) — греческая буква бета MessageBox.Show("Длина окружности " & ChrW(&H3B2) & " = " & String.Format("{0:F4}", beta)) ’ или просто Format(beta, "##0.000") End If End Sub End Class Обрабатывая событие Fomi Load, мы задали шрифт Times New Roman, 12 пунктов, и инициализировали свойство Text длинной метки Labeli. Раз- личные шестнадцатеричные номера соответствуют греческим буквам и арифметической операции ’’умножить”, в инициализации строки участвует также константа тс= 3.14. Ее более точное значение получаем из Math.pi. Константа vbCrLf означает переход на новую строку, ее можно вызвать из перечисления controlchars, здесь она называется CrLf. Обрабатывая событие TextBoxijKeyDown (генерируется в момент первоначаль- ного нажатия клавиши), мы отслеживаем нажатие клавиши <Enter>, сравни- вая данные о нажатой клавише e.KeyData с кодом клавиши <Enter> Keys.Return. Пользователь вводит в текстовое поле значение радиуса и после
Простейшие программы с экранной формой и элементами управления 49 того как нажимает клавишу <Enter>, мы проверяем с помощью функции isNumeric, число ли введено в текстовое поле. Если число (True), то вычисля- ем значение beta, при этом выполняем преобразование строковой перемен- ной TextBoxl.Text в переменную типа Decimal (десятичный тип) с помощью функции стуре. Заметим, что тип Decimal появился в Visual Basic, начиная с версии VB.NET, он сменил тип Currency (типа Currency теперь нет). Деся- тичный тип представляет восьмибайтовое число (как Double), которое может иметь до 28 десятичных знаков. После вычисления длины окружности beta выводим ее значение вместе с греческой буквой Р— ChrW(&H3B2) В ДИЗЛОГОВОв ОКНО MessageBox. Здесь ис- пользуем функцию string. Format, выражение "{0:F4}" означает, что значение переменной beta следует выводить по фиксированному формату с четырьмя знаками после запятой. В комментарии показано, как можно было бы вос- пользоваться функцией Format для той же цели. Функция Format существова- ла еще в VB6. Убедиться в работоспособности программы можно, открыв решение Unico.sln в папке Unico.

ГЛАВА 2 Инициирование и обработка событий мыши и клавиатуры Пример 14. Инициирование события в создаваемом классе Мы знаем, что объекты содержат в себе (инкапсулируют) методы (т. е. процедуры), свойства (т. е. переменные) и события, которыми эти объекты управляются. Цель данной программы — выразительно (не запутывая чита- теля) показать, как создать собственный класс, содержащий процедуру оцен- ки введенной пользователем строки. Оценка отвечает на вопрос: может ли данное выражение рассматриваться как число? Свой негативный ответ про- цедура сообщает, вызывая событие "плохой ввод" (Badinput). Эта программа должна иметь минимум программного кода, поэтому напи- шем ее как консольное приложение. Для этого запускаем VB2010, в окне New Project выбираем шаблон Console Application. Кроме того, чтобы система не показывала нам черный DOS-экран, выполним команду ConsoleApplicationl Properties в меню Project и на вкладке Application в раскрывающемся спи- ске Application type выберем Windows Forms Application. Затем на вкладке Modulel.vb набираем текст программы, представленный в листинге 2.1. Г Листинг 2.1. Инициирование события в создаваемом классе ’ Программа создает собственный класс, содержащий процедуру оценки ’ введенной пользователем строки: может ли данное выражение • рассматриваться как число. Свой негативный ответ процедура сообщает, * вызывая событие ’’плохой ввод” (Badinput) Module Modulel ’ Объявляем, что объект Vvodl является экземпляром ' класса Vvod и содержит события Private WithEvents Vvodl As Vvod = New Vvod
52 Гпава 2 Class Vvod Public Event Badlnput(ByVai Текст As String) Sub start() Do ’ Вечный цикл: Dim say As String = InputBox("Введите число:") If IsNumeric(say) = True Then МздВох("Вы хорошо справились с заданием!") Exit Sub Else ’ Вызов события: RaiseEvent Badlnput("Следует вводить числа!") End If Loop End Sub End Class Private Sub Vvodl_BadInput(ByVai Текст As String) _ Handles Vvodl.Badlnput ’ Обработчик события "плохой ввод" MsgBox(Текст) End Sub Sub main() Vvodl.start() End Sub End Module В данном модуле выражение: Private WithEvents Vvodl As Vvod = New Vvod является объявлением нового объекта vvodl, которое является экземпляром класса vvod и содержит события (withEvents). Как видно, в начале класса объ- явлена процедура обработки события с ключевым словом Event, с указанием имени события Badlnput И его строковым (типа String) параметром Текст. Обычно принято в качестве параметров процедуры обработки события ука- зать объект-источник Sender и информацию о событии (аргументы EventArgs). Однако для данного самого простого примера одного строкового параметра достаточно. Стартовая точка модуля main о вызывает метод (процедуру) start о объекта vvodl. Здесь задан вечный цикл Do...Loop, в котором пользователю через функцию InputBox (эта функция из VB6) предлагается ввести число. Введен- ная пользователем строка say с помощью функции isNumeric подвергается
Инициирование и обработка событий мыши и клавиатуры 53 проверке, может ли она рассматриваться как число. Если может, то происхо- дит ВЫХОД ИЗ программы Exit Sub. Если нет, ТО вызывается (RaiseEvent) со- бытие ’’плохой ввод" Badlnput. Не стоит читателю вручную набирать процедуру обработки события vvodi Badinput. Вместо этого в левом раскрывающемся списке выбираем объект Vvodi, а в правом — событие Badlnput. Это действие сгенерирует вне класса пустой обработчик события. В нем ключевое слово Handles сообщает исполнительной среде, какое событие обрабатывается этой процедурой. Ме- жду двумя сгенерированными строчками добавляем MsgBox (Текст). Критично посмотрев на данную программу, читатель может возразить, стои- ло ли "городить огород" с инициированием события, если можно вывести сообщение через MsgBox или написать не процедуру обработки события, а просто обычную процедуру? Не забывайте, что мы здесь стремились мини- мальным количеством строк программного кода продемонстрировать воз- можность инициирования событий. Кроме того, очень удобно (иногда более естественно) назвать нечто в программе событием. Убедиться в работоспособности программы можно, открыв решение Sobytie.sln в папке Sobytie. Пример 15. Создание элемента управления Button программным способом и подключение события для него Мы знаем, как, используя панель элементов управления, в форму перенести мышью нужный элемент. Чтобы сделать разработку программы более управ- ляемой, в данной программе научимся создавать элементы управления в форме "программным" способом, т. е. с помощью написания непосредствен- но программного кода, не используя при этом панель элементов управления Toolbox. Понятно, что название "программным" является более чем услов- ным, поскольку в описываемой нами среде трудно назвать что-либо, что "программным" не является. Итак, данная программа создаст командную кнопку в форме "программным" способом, задаст свойства кнопки: ее видимость, размеры, положение, надпись на кнопке и подключит событие "щелчок на кнопке". Для этого создаем новый проект с формой. При этом, как обычно, запускаем VB2010, в окне New Project выбираем шаблон Windows Forms Application. Далее вводим программный код, представленный в листинге 2.2.
54 Гпава 2 Листинг 2.2. Создание кнопки программным способом . / . ' ? ’ Программа создает командную кнопку в форме программным способом, ’ т. е. с помощью написания непосредственно программного кода, не ’ используя при этом панель элементов управления Toolbox. Программа ’ задает свойства кнопки: ее видимость, размеры, положение, надпись ’ на кнопке и подключает событие "щелчок на кнопке" Public Class Forml Private Sub Forml_Load(ByVai sender As System.Object, ByVai e As System.EventArgs) Handles MyBase.Load ’ Создание кнопки без панели элементов управления: Dim Buttonl As New System.Windows.Forms.Button ’ Задаем свойства кнопки: With Buttonl .Visible = True .Size = New Size (100, 30) .Location = New Point(100, 80) .Text = "Новая кнопка" End With Me.Controls.Add(Buttonl) ’ Добавление события Click для кнопки: AddHandler Buttonl.Click, AddressOf Me.Buttonl_Click End Sub Public Sub Buttonl_Click(ByVai sender As System.Object, ByVai e As System.EventArgs) MessageBox.Show("Нажата новая кнопка") End Sub End Class Как видно, при обработке события загрузки формы Forml Load создаем новый объект Buttonl стандартного класса кнопок. Задаем свойства кнопки: ее ви- димость (visible), размеры (size), положение (Location) относительно левого нижнего угла формы, надпись на кнопке ’’Новая кнопка”. Запись with сокра- щает полные имена. Далее команда AddHandler подключает событие Buttonl.Click. В процедуре обработки события Buttonl.Click выводим сообщение "Нажата новая кноп- ка". На рис. 2.1 приведен фрагмент работы программы.
Инициирование и обработка событий мыши и клавиатуры 55 Рис. 2.1. Создание кнопки программным способом Убедиться в работоспособности программы можно, открыв решение NewButton.sln папки NewButton. Пример 16. Координаты курсора мыши относительно экрана и элемента управления Напишем программу, которая условно называется мониторингом положения мыши. Имеем форму, список элементов ListBox и два текстовых поля. Они расположены в форме так, как показано на рис. 2.2. Рис. 2.2. Фрагмент работы программы определения координат курсора мыши Программа заполняет список ListBoxi данными о местоположении и измене- нии положения курсора мыши. Кроме того, в текстовых полях отображаются координаты положения курсора мыши относительно экрана, а также относи- тельно элемента управления ListBox. Для программирования этой задачи после запуска VB2010 и выбора шаблона Windows Forms Application из панели элементов управления Toolbox пере-
56 Гпава 2 тащим в форму элемент управления ListBox и два текстовых поля. Про- граммный код приведен в листинге 2.3. Листинг 2.3. Координаты курсора мыши относительно экрана ’ Программа отображает координаты курсора мыши относительно экрана ' и элемента управления. Программа содержит форму, список элементов ’ ListBox и два текстовых поля. Программа заполняет список ListBox ’ данными о местоположении и изменении положения курсора мыши. Кроме ’ того, в текстовых полях отображаются координаты положения курсора ' мыши относительно экрана и элемента управления ListBox. Public Class Forml Private Sub Forml_Load(ByVai sender As System.Object, ByVai e As System.EventArgs) Handles MyBase.Load Me.Text = "Мониторинг движения мыши" End Sub Private Sub ListBoxl_MouseEnter(ByVai sender As Object, ByVai e As System.EventArgs) Handles ListBoxl.MouseEnter ’ Добавляем в список элементов новую запись ListBoxl.Items.Add("Курсор мыши вошел в область ListBox") End Sub Private Sub ListBoxl_MouseLeave(ByVai sender As Object, ByVai e As System.EventArgs) Handles ListBoxl.MouseLeave ListBoxl.Items.Add("Курсор мыши вышел из области ListBox") End Sub Private Sub ListBoxl_MouseMove(ByVai sender As Object, ByVai e As System.Windows.Forms.MouseEventArgs) _ Handles ListBoxl.MouseMove ’ Свойство объекта Control MousePosition возвращает точку, ’ соответствующую текущему положению мыши ’ относительно левого верхнего угла монитора TextBoxi.Text = "X = " & Forml.MousePosition.X.ToString & " или " & e.X.ToString TextBox2.Text = "Y = " & Forml.MousePosition.Y.ToString & " или " & e.Y.ToString End Sub End Class Как видно, при обработке события мыши MouseEnter, когда курсор мыши входит в границы элемента управления, в список ListBoxl добавляется (ме-
Инициирование и обработка событий мыши и клавиатуры 57 тод Add) запись "Курсор мыши вошел в область ListBox". При обработке со- бытия мыши MouseLeave, когда курсор мыши выходит за пределы элемента управления, в список ListBox добавляется запись "Курсор мыши вышел из области ListBox". Таким образом, отслеживая поведение мыши, заполняется список ListBoxl. При обработке события MouseMove, когда курсор мыши перемещается в пре- делах элемента управления ListBoxl, в текстовые поля записываем координа- ты X И Y курсора МЫШИ, пользуясь СВОЙСТВОМ объекта Control Mouseposition. Метод ToString преобразует координаты в строковое представление. Здесь мы получаем координаты положения курсора мыши в системе координат экрана, когда начало координат расположено в левом верхнем углу экрана, ось х направлена вправо, а ось у — вниз. Заметим, что аргументы события мыши е также содержат в себе текущие ко- ординаты курсора мыши, но в системе координат элемента управления, в данном случае ListBoxl. Начало координат этой системы расположено в левом верхнем углу элемента управления ListBoxl, ось х также направлена вправо, ось у— вниз. Эти координаты получаем из аргумента события е.х и е. Y, и выводим их в текстовое поле, отделяя от предыдущих координат сло- вом "или". Таким образом, добиваемся контроля положения курсора мыши, обрабаты- вая события мыши. Убедиться в работоспособности программы можно, от- крыв решение Monitoring.sln папки Monitoring. Пример 17. Ассоциация нескольких элементов управления с одним событием с помощью Handles Для того чтобы события от нескольких элементов управления обрабатыва- лись одной процедурой обработки события, в VB6 было предусмотрено соз- дание массива элементов управления. Начиная с VB.NET, элементы не могут быть сгруппированы в массивы. Однако одна и та же процедура обработки одного и того же события (например, Click) может использоваться для не- скольких элементов управления. Как это сделать, покажем на примере, когда в форме имеем три командные кнопки, и при нажатии указателем мыши на любую из них получаем одина- ковое сообщение со сведением о нажатой кнопке. Суть решения задачи состоит в том, что, например, путем двойного щелчка на одной из кнопок получить пустой обработчик события Click (как обычно). Однако после ключевого слова Handles через запятую перечислим все собы-
58 Гпава 2 тия, которые мы хотим обрабатывать в этой процедуре. Программный код программы приведен в листинге 2.4. Лислир? ^скольких элеиентов упоэвлсния с одним событием с помощью Handles . . . ’ Public Class Forml Private Sub button_Click(ByVai sender As System.Object, ByVai e As System.EventArgs) _ Handles Buttonl.Click, Button2.Click, Button3.Click MessageBox.Show(sender.ToString) End Sub End Class Обратите внимание, автор назвал процедуру обработки события button_ciick() — без номера кнопки (название процедуры может быть со- вершенно произвольным), а после Handles перечислил все события, которые необходимо было одинаково обработать. Кроме того, хотелось бы все-таки знать, какой объект из трех (Buttonl, Button2 или Buttons) создал событие Click. Информация об этом записана в объекте sender. Объектная переменная sender содержит ссылку на объект- источник события, т. е. кнопку, нажатую пользователем. Поэтому в нашей программе предусмотрен вывод строкового представления объекта sender В диалоговое ОКНО через MessageBox (рис. 2.3). Рис. 2.3. Вывод строкового представления объекта sender Как видно, пользователь нажал Button2, причем после "Text:" выводится зна- чение свойства кнопки Text = ”Button2”. Заметим, что в строковом представ- лении объекта sender подстрока "Button2" находится, начиная с 35-го символа. То есть очевидно, что в данном случае надпись на кнопке можно всегда по- лучить, начиная с 35-й позиции и до конца строки sender.Tostring. Для этого, например, можно воспользоваться функцией Substring (к), которая выделяет подстроку из строки, начиная с k-го символа: sender.ToString.Substring(35)
Инициирование и обработка событий мыши и клавиатуры 59 Чтобы показать более выразительно суть проблемы, добавим в программу несколько элементарных операций со строками. В результате получим про- граммный код, представленный в листинге 2.5. 5 Листинг 2.5. Готовый код ’ Ассоциация нескольких элементов управления с одним событием с помощью ’ Handles. В форме имеем три командные кнопки, и при нажатии указателем ' мыши любой из них получаем номер нажатой кнопки. При этом в ’ программе предусмотрена только одна процедура обработки событий. Public Class Forml ’ Процедура обработки сразу трех событий: Private Sub button_Click(ByVai sender As System.Object, ByVai e As System.EventArgs) Handles _ Buttonl.Click, Button2.Click, Button3.Click Dim S As String ' = sender.ToString & vbCrLf S = ’’Нажата кнопка ” & sender.ToString.Substring(35) MessageBox.Show(S) Dim Name As String = СТуре(sender, Button).Name End Sub End Class На рис. 2.4 приведен пример работы написанной программы. Рис. 2.4. Фрагмент работы программы, определяющей нажатую кнопку Какую бы кнопку не нажал пользователь, он получит одно и то же диалого- вое окно с указанием нажатой кнопки. Мы убедились в этом разделе, что сведения об объекте, который создал со- бытие, находятся в объектной переменной sender. На самом деле, можно го- раздо проще получать эти сведения. Так, чтобы получить имя (Name) объек- та— кнопки, генерирующего событие Click, достаточно написать такое вы- ражение: Dim Name As String = СТуре(sender, Button).Name
60 Гпава 2 А получить текст, отображаемый на кнопке, можно таким образом: Dim Text As String = CType(sender, Button).Text Здесь функция стуре возвращает результат преобразования объектной пере- менной sender в объект типа Button, и таким образом мы можем получить все текущие свойства объекта Button после точки, в том числе Name и Text. Зна- чит, совсем не обязательно пользоваться функцией Substring, чтобы распо- знать нажатую кнопку. Работу этой программы можно исследовать, открыв решение Handles.sln в папке Handles. Пример 18. Калькулятор Обработка нескольких событий от разных объектов одной процедурой ока- зывается весьма полезной при программировании данного приложения. На- пишем программу Калькулятор с кнопками-цифрами, выполняющую только арифметические операции, причем управление Калькулятором возможно только мышью. Запустив VB2010 и выбрав шаблон Windows Forms Application, перетащим из окна Toolbox в форму 16 командных кнопок для ввода цифр, арифметиче- ских операций, знака ’’равно” (=) и операции Очистить, а также текстовое поле. Вкладка Forml.vb [Design] будет иметь примерно такой вид, как пока- зано на рис. 2.5. Рис. 2.5. Вкладка конструктора формы
Инициирование и обработка событий мыши и клавиатуры 61 В листинге 2.6 приведен программный код данного приложения. : Листинг 2.6, Калькулятор ’ Программа Калькулятор с кнопками цифр. Управление калькулятором ’ возможно только мышью. Данный калькулятор выполняет лишь ’ арифметические операции. Public Class Forml Dim Znak As String ’ Знак арифметической операции Dim Начало_Ввода As Boolean = True Dim valuel, value2 As Double Private Sub Forml_Load(ByVai sender As System.Object, ByVai e As System.EventArgs) Handles MyBase.Load Buttonl.Text = "I" : Button2.Text = "2" : Button3.Text = "3” Button4.Text = "4” : Button5.Text = "5” : Button6.Text = ”6” Button?.Text = ”7” : Buttons.Text = "8” : Button9.Text = ’’9” ButtonlO.Text = "0” : Buttonll.Text = "=" : Buttonl2.Text = "+" Buttonl3.Text = "-" : Buttonl4.Text = "*" : Buttonl5.Text '= "/" Buttonl6.Text = "Очистить" : Me.Text = "Калькулятор" TextBoxl.Text = "0" TextBoxl.TextAlign = HorizontalAlignment.Right End Sub Private Sub Digit_Click(ByVai sender As System.Object, ByVai e As System.EventArgs) Handles ButtonlO.Click, Buttonl.Click, Button2.Click, Button3.Click, Button4.Click, Buttons.Click, Button6.Click, Button?.Click, Buttons.Click, Button9.Click ’ Обработка события нажатия кнопки-цифры: Dim Digit As String = СТуре(sender, Button).Text ’ или Dim Digit As String = sender.ToString.Substring(35) If Начало_Ввода = True Then TextBoxl.Text = Digit _ : Начало_Ввода = False : Exit Sub If Начало_Ввода = False Then TextBoxl.Text = TextBoxl.Text & Digit End Sub Private Sub Операция_СИск (ByVai sender As System.Object, ByVai e As System.EventArgs) Handles Buttonl2.Click, Buttonl3.Click, Buttonl4.Click, ButtonlS.Click
62 Гпава 2 ' Обработка события нажатия клавиши арифметической операции: valuel = Double.Parse(TextBoxi.Text) ' или valuel = CDbl(TextBoxi.Text) Znak = CType(sender, Button).Text ' или Znak = sender.ToString.Substring(35) Начало_Ввода = True End Sub Private Sub Равно_СИск(ByVai sender As System.Object, ByVai e As System.EventArgs) Handles Buttoni1.Click ' Обработка события нажатия клавиши "равно" Dim result As Double value2 = Double.Parse(TextBoxi.Text) ' или value2 = CDbl(TextBoxi.Text) If Znak = "+" Then result = valuel + value2 If Znak = "-" Then result = valuel — value2 If Znak = "*" Then result = valuel * value2 If Znak = "/" Then result = valuel / value2 TextBoxi.Text = result.ToString ' или = CStr(result) valuel = result : Начало_Ввода = True End Sub Private Sub Очистить_СИск (ByVai sender As System.Object, ByVai e As System.EventArgs) Handles Buttoni6.Click ' Обработка события нажатия клавиши "Очистить" TextBoxi.Text = "О" : Znak = "" : Начало_Ввода = True End Sub End Class Как видно, здесь автор запрограммировал 5 событий. Событие загрузки фор- мы Formi Load обычно используется для инициализации (т. е. для присвоения начальных значений). В этой книге мы принципиально отказались от задания свойств элементов управления и формы в окне Properties, чтобы не поте- ряться в огромном количестве этих свойств и не забывать, какое свойство мы изменили, а какое нет. Исходя из этих соображений, автор задал все свойства объектов при загрузке формы. Именно здесь заданы надписи на кнопках, ноль в текстовом поле, причем этот ноль прижат к правому краю поля: TextBoxi.TextAlign = HorizontalAlignment.Right. Процедура обработки события Digit click отслеживает нажатия кнопок- цифр указателем мыши на калькуляторе. Здесь очень пригодилось возмож-
Инициирование и обработка событий мыши и клавиатуры 63 ность обработки нескольких событий от разных кнопок одной процедурой, подробно рассмотренная нами в предыдущем примере о трех кнопках. Пус- той обработчик этого события мы получили обычным путем, т. е. двойной щелчок по любой из кнопок цифр на вкладке Forml.vb [Design]. Название процедуры обработки события автор переименовал в sub Digit click, а после ключевого слова Handles перечислил через запятую все события, которые хотел бы отслеживать в этой процедуре. Как видно, этими событиями явля- ются все щелчки указателем мыши на кнопках-цифрах калькулятора. Далее в процедуре Digit click строковой переменной Digit присваиваем значение надписи на кнопке так же, как мы делали это в предыдущем приме- ре, используя функцию стурео. Выражение стуре(sender, button) .Text воз- вращает свойство Text нажатой кнопки. (Можно пользоваться также функци- ей Substring(35). Напомню, что значение надписи на кнопке записано с 35-й позиции сорокового представления объекта-источника события sender.) Далее необходимо значение Digit присвоить свойству TextBoxl. Text, но здесь изначально записан ноль. Если пользователь вводит первую цифру, то вместо нуля нужно записать эту цифру, а если пользователь вводит последующие цифры, то их надо ’’сцепить” вместе. Для управления такой ситуацией мы ввели булеву (логическую) переменную Начало_ввода. Мы сознательно назва- ли эту переменную по-русски, чтобы она выделялась среди прочих перемен- ных. ведь она играет ключевую роль в программе и участвует в обработке практически всех событий. Поскольку мы ввели ее в начале программы, об- ласть действия этой переменной — весь класс Forml, т. е. эта переменная "видна" в процедурах обработки всех событий. Таким образом, различаем начало ввода числа начало_ввода = True, когда ноль следует менять на вводимую цифру, и последующий ввод нача- ло ввода = False, когда очередную цифру следует добавлять справа. Для большей выразительности оба условия If Начало_ввода = True И False мы записали в одну строку (использовали однострочный оператор условия (:)). При обработке событий ’’щелчок указателем мыши по кнопкам” арифметиче- ских операций +, / в процедуре Операция СИск также после Handles пере- числены четыре соответствующих события. Строковой переменной znak при- сваивается символьное представление арифметической операции. Поскольку пользователь нажал кнопку арифметической операции, ожидаем, что сле- дующим действием пользователя будет ввод очередного числа, поэтому при- сваиваем булевой переменной начало ввода значение True. Заметьте, что об- рабатывая два других события: нажатие кнопки = (Равно СИск) и нажатие кнопки Очистить (очистить сиск), мы также устанавливаем логическую переменную начало ввода в состояние True (т. е. начинаем ввод числа).
64 Гпава 2 После того как пользователь получит результат, например, result = vaiuel + value2, возможно, он захочет с этим результатом выполнить еще какое-либо действие, поэтому этот результат записываем в первую переменную vaiuel. Заметьте, что в этой программе мы сознательно не предусмотрели обработку исключительной ситуации деления на ноль, поскольку среда VB2010 (впро- чем, как и предыдущие версии VB) взяла на себя обработку этой ситуации. Когда в строковую переменную попадает очень большое число, в эту пере- менную система пишет слово "NaN" (рис. 2.6). Рис. 2.6. Фрагмент работы калькулятора Убедиться в работоспособности программы можно, открыв решение Ca my.sln в папке Са_ту. Пример 19. Обработка событий клавиатуры События клавиатуры (клавишные события) создаются в момент нажатия или отпускания ее клавиш. Различают событие Keypress, которое генерируется в момент нажатия клавиши. При удержании клавиши в нажатом состоянии оно генерируется непрерывно с некоторой частотой. С помощью этого собы- тия можно распознать нажатую клавишу, если только она не является так на- зываемой модифицирующей, т. е. <Alt>, <Shift> и <Ctrl>. А вот для того что- бы распознать, нажата ли модифицирующая клавиша <Alt>, <Shift> или <Ctrl>, следует обработать или событие KeyDown, или событие кеуир. Событие KeyDown генерируется в первоначальный момент нажатия клавиши, а событие Кеуир — в момент отпускания клавиши. Напишем программу, информирующую пользователя о тех клавишах и ком- бинациях клавиш, которые нажал пользователь. Эта программа состоит из
Инициирование и обработка событий мыши и клавиатуры 65 формы и двух меток: Labeli и Labei2. Текст программы приведен в листин- ге 2.7. Листинг 2.7. Обработка событий клавиатуры : ' Программа, информирующая пользователя о тех клавишах и ' комбинациях клавиш, которые нажал пользователь Public Class Forml Private Sub Forml_Load(ByVai sender As System.Object, ByVai e As System.EventArgs) Handles MyBase.Load Me.Font = New System.Drawing.Font("Courier New", 14) Me.Text = "Какие клавиши нажаты сейчас:" Labeli.Text = "" : Label2.Text = "" End Sub Private Sub Forml_KeyPress(ByVai sender As Object, ByVai e As System. Windows. Forms. KeyPressEventArgs) Handles Me.KeyPress ’ Здесь событие нажатия клавиши: при удержании ' клавиши генерируется непрерывно Labeli.Text = "Нажатая клавиша: " & е.KeyChar End Sub Private Sub Forml_KeyDown(ByVai sender As Object, ByVai e As System.Windows.Forms. KeyEventArgs) Handles MyBase.KeyDown ' Здесь мгновенное событие первоначального нажатия клавиши Label2.Text = "" ’ Если нажата клавиша <Alt> If e.Alt = True Then Label2.Text &= "Alt: Yes" & vbCrLf Else Label2.Text &= "Alt: No" & vbCrLf End If ' Если нажата клавиша <Shift> If e.Shift = True Then Label2.Text &= "Shift: Yes" & vbCrLf 3 Зак 145
66 Гпава 2 Else Label2.Text &= "Shift: No" & vbCrLf End If ’ Если нажата клавиша <Ctrl> If e.Control = True Then Label2.Text &= "Ctrl: Yes" & vbCrLf Else Label2.Text &= "Ctrl: No" & vbCrLf End If Label2.Text &= "Код клавиши: " & e.KeyCode.ToString & vbCrLf '& "KeyData: " & e.KeyData.ToString & vbCrLf & "KeyValue: " & e.KeyValue End Sub Private Sub Forml_KeyUp(ByVai sender As Object, ByVai e As System.Windows.Forms.KeyEventArgs) _ Handles MyBase.KeyUp ' Очистка меток при освобождении клавиши Labell.Text = "" : Label2.Text = "" End Sub End Class В первую метку Labell записываем сведения о нажатой обычной клавише при обработке события Keypress. Во вторую метку из аргумента события е (e.Ait, е.shift и е.Control) получаем сведения, была ли нажата какая-либо (либо их комбинация) модифицирующая клавиша. Обработчик события Кеуир очищает обе метки при освобождении клавиш. На рис. 2.7 приведен фрагмент работы программы. Рис. 2.7. Фрагмент работы программы, определяющей нажатую клавишу
Инициирование и обработка событий мыши и клавиатуры 67 Убедиться в работоспособности программы можно, открыв решение Key.sln в папке Key. Пример 20. Контроль вводимых пользователем числовых данных при обработке события нажатия клавиши Обычно для диагностики вводимых числовых данных мы пользовались функцией isNumeric. Эта функция возвращает True, если на ее вход подаются числовые данные, и False в противном случае. Покажем, как можно совер- шенно по-другому решить данную задачу. Можно вообще не давать возмож- ность пользователю вводить не числовые данные. Продемонстрируем такое решение на следующем примере. Данная программа анализирует каждый символ, вводимый пользователем в текстовое поле формы. Если символ не является числовым, то текстовое поле получает запрет на ввод такого символа. Таким образом, программа не дает возможность пользователю ввода нечисловых данных. Запустим систему VB2010, в окне New Project выберем шаблон Windows Forms Application. На панели инструментов Toolbox найдем текстовое поле TextBox и перетащим его в форму. Текст программы показан в лис- тинге 2.8. ? Листинг 2.8. Контроль вводимых пользователем числовых данных ' Программа анализирует каждый символ, вводимый пользователем в текстовое ' поле формы. Если символ не является числовым, то текстовое поле ' получает запрет на ввод такого символа. Public Class Forml Private Sub Forml_Load(ByVai sender As System.Object, ByVai e As System.EventArgs) Handles MyBase.Load Me.Text = "Введите число" : TextBoxl.Clear() End Sub ' Обработка события нажатия клавиши в текстовом поле: Private Sub TextBoxl_KeyPress(ByVai sender As Object, ByVai e As System.Windows.Forms. KeyPressEventArgs) Handles TextBoxl.KeyPress ' Кроме стрелок, клавишей <Delete>, <Home>, <End>, <Page Up>, ' <Page Down>, <Tab>, <F1>, ... , <F12>, ... :
68 Гпава 2 ’ Если клавиша не является цифровой, то запретить (True) ’ получение этого события клавиатуры текстовым полем If Char.IsDigit(е.KeyChar) = False Then e.Handled = True ' Если клавиша является цифровой, то снять этот запрет If Char.IsDigit(е.KeyChar) = True Then e.Handled = False ' Если нажата клавиша <Backspace>, то снять запрет If е.KeyChar = ChrW(Keys.Back) Then e.Handled = False ’ e.Handled = True — запрет получения этого события ' е.Handled = False — снятие запрета получать это событие End Sub End Class Как видно из программного кода, при обработке события загрузки формы задаем текст строки заголовка ’’Введите число” и очищаем текстовое поле TextBoxi. clear о. Самое интересное начинается при обработке события на- жатия клавиши в текстовом поле TextBoxi KeyPress. Здесь программа может определить, какую клавишу нажал пользователь, из аргумента события е. Символ, соответствующий нажатой клавише, содержится в свойстве аргу- мента е.KeyChar. На вход функции isDigitai подаем это свойство (т. е. иссле- дуемый символ), а на выходе получаем заключение, является ли исследуемый символ цифрой (True или False). Как видно из первого условного оператора, если введенный пользователем символ не является цифрой, то свойству е.Handled присваивается True, что означает запрет получения этого события клавиатуры текстовым полем. При этом данное событие получает только форма. Таким образом, мы добиваемся игнорирования текстовым полем не цифровых символов. Второй условный оператор, наоборот, снимает такой запрет е.Handled = False, если введенный символ является цифрой. Далее, если пользователь нажал клавишу <Backspace>, то запрет получения такого события текстовым полем также снимается. Интерфейс рассматриваемого приложения показан, на рис. 2.8. Убедиться в работоспособности программы можно, открыв решение Numbers.sin в папке Numbers. Рис. 2.8. Проверка введенных данных
ГЛАВА 3 Чтение,запись текстовых и бинарных файлов, текстовый редактор Пример 21. Чтение/запись текстового файла в кодировке Unicode. Блоки Try...Catch Очень распространенной задачей является сохранение данных на диске в тек- стовом формате (не в двоичном). В этом случае сохраненные данные можно читать, редактировать любым текстовым редактором, например БлЬкнотом или TextEdit. Читать текстовые данные также можно и в своей программе. Казалось бы, это очень простая задача. Например, чтение текстового файла сводится буквально к нескольким строчкам: ’ Объявление экземпляра StreamReader для чтения из файла Dim Reader As New System.IO.StreamReader("С:\Textl.txt") ’ Считывание содержимого текстового файла в строку Dim Stroka As String = Reader.ReadToEnd() Reader.Close() Однако есть некоторые серьезные нюансы. Напишем программу, способную читать и писать данные в текстовом формате. Запустим среду VB2010 и закажем новый проект шаблона Windows Forms Application. Далее в форму перенесем текстовое поле и две командные кнопки. Для текстового поля в окне Properties сразу укажем для свойства Multiline значение True, чтобы текстовое поле имело не одну строку, а столько, сколько поместится в растянутом указателем мыши поле. Одна кнопка предназначена для открытия файла, а другая — для сохранения файла на машинном носителе. В листинге 3.1 приведен текст данной программы.
70 Гпава 3 ; Листинг 3.1 Чтение/запись текстового файла в кодировке Unicode . < ' Программа для чтения/записи текстового файла в кодировке Unicode Public Class Forml Dim filename As String Private Sub Forml_Load(ByVai sender As System.Object, ByVai e As System.EventArgs) Handles MyBase.Load TextBoxi.Multiline = True : TextBoxi.Clear() Buttoni.Text = "Открыть" : Buttoni.Tabindex = 0 Button2.Text = "Сохранить как..." Me.Text = "Здесь кодировка Unicode" End Sub Private Sub Buttonl_Click(ByVai sender As System.Object, ByVai e As System.EventArgs) Handles Buttoni.Click ' Русские буквы будут нормально читаться, ' если файл в кодировке UNICODE: filename = InputBox("Введите полное имя файла", , "C:\Textl.txt") Try ’ Создание объекта StreamReader для чтения из файла: Dim Читатель As New 10.StreamReader(filename) TextBoxi.Text = Читатель.ReadToEnd() Читатель.Close() Catch Exc As System.10.FileNotFoundException MessageBox.Show("Нет такого файла", "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Exclamation) Catch Exc As Exception ’ Отчет о других ошибках: MessageBox.Show(Exc.Message, "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Exclamation) End Try End Sub Private Sub Button2_Click(ByVai sender As System.Object, ByVai e As System.EventArgs) Handles Button2.Click
Чтение, запись текстовых и бинарных файлов, текстовый редактор 71 filename = InputBox("Введите полное имя файла", , "C:\Textl.txt") Try ' Создание объекта StreamWriter для записи в файл: Dim Писатель As New 10.StreamWriter(filename, False) Писатель.Write(TextBoxl.Text) Писатель.Close() Catch Exc As Exception ' Отчет о всех возможных ошибках: MessageBox.Show(Exc.Message, "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Exclamation) End Try End Sub End Class Несколько слов о блоках Try, которые, как видно, используются в данном программном коде. Логика использования Try следующая: попытаться (Try) выполнить некоторую задачу, например, прочитать файл. Если задача решена некорректно (например, файл не найден), то "перехватить" (Catch) управле- ние и обработать возникшую (исключительную, Exception) ситуацию. Как видно из текста программы, обработка исключительной ситуации свелась к информированию пользователя о недоразумении. При обработке события ’’щелчок на кнопке” Открыть организован ввод име- ни файла через функцию InputBox. Обычно в этой ситуации пользуются эле- ментом управления openFiieDiaiog для выбора файла. Мы не стали использо- вать этот элемент управления для того, чтобы не "заговорить" проблему, а также свести к минимуму программный код. Далее создаем объект (поток) читатель для чтения из файла. Для большей вы- разительности операций с данным объектом мы назвали его русскими буква- ми. Затем следует чтение файла filename методом ReadToEndo в текстовое поле TextBoxl.Text и закрытие файла методом close (). При обработке события ’’щелчок на кнопке” Сохранить как организована запись файла на диск аналогично через объект писатель. При создании объек- та Писатель первый аргумент filename получаем через функцию InputBox. Второй аргумент False указывает, что данные следует не добавить (append) к содержимому файла (если он уже существует), а перезаписать (overwrite). Запись на диск производится с помощью метода write о из текстовой пере- менной Text элемента управления TextBoxl. На рис. 3.1 приведен фрагмент работы программы.
72 Гпава 3 Сделаем очень важное примечание. Запись текстового файла с помощью дан- ной программы будет происходить в формате (кодировке) Unicode, как и чтение из файла. То есть вы сможете читать эти файлы Блокнотом, редакти- ровать их, но каждый раз при сохранении файлов следить, чтобы кодировка была Unicode. Ес пи бы нашли девушку своей мечты, то вам прийдется отказаться от из 'охранить | Рис. 3.1. Чтение/запись текстового файла в кодировке Unicode Однако по умолчанию в редакторах используется кодировка ANSI. Кодиров- ку ANSI с русскими буквами называют Windows 1251. Некоторые редакторы, например, RPad (’’русский” Блокнот) вообще не работают с Unicode. Таким образом, на сегодняшний день пока что записывать в кодировке Unicode — это как бы эксклюзив. Возможно, даже наверняка, в ближайшее время многое изменится в пользу Unicode, поскольку информационные технологии меня- ются очень быстро. Если в Блокноте подготовить текстовый файл в обычной кодировке ANSI, то прочитать русские буквы данной программой не получится, хотя английские буквы отобразятся в текстовом поле без проблем. Почему? Дело в том, что приведенная в тексте данной программы технология описана в учеб- ных пособиях по Visual Basic, в MSDN, на сайтах, подобных http://msdn.microsoft.com/library/rus/. Однако это все англоязычные источ- ники, а для английских текстов переход от одной кодировке к другой оказы- вается практически незаметным. Например, английские буквы кодировок Windows 1251, ASCII и Unicode совпадают, а с русскими буквами всегда воз- никают недоразумения. Об этом говорят программисты на различных фору- мах в Интернете. Программистам эти недоразумения следует учитывать. Разрешению этого недоразумения посвящена следующая программа. Убедиться в работоспособности данной программы можно, открыв решение TXT Unicode.sln в папке TXT Unicode.
Чтение, запись текстовых и бинарных файлов, текстовый редактор 73 Пример 22. Чтение/запись текстового файла в кодировке Windows 1251 Структура данной программы аналогична предыдущей, поэтому сразу обра- тимся к ее коду в листинге 3.2. Листинг 3.2. Чтение/запись текстового файла в кодировке Windows 1251 ’ Программа для чтения/записи текстового файла в кодировке Windows 1251 Public Class Forml Dim filename As String Private Sub Forml_Load(ByVai sender As System.Object, ByVai e As System.EventArgs) Handles MyBase.Load TextBoxl.Multiline = True : TextBoxl.Clear() Buttonl.Text = "Открыть" : Buttonl.Tabindex = 0 Button2.Text = "Сохранить как..." Me.Text = "Здесь кодировка Windows1251" End Sub Private Sub Buttonl_Click(ByVai sender As System.Object, ByVai e As System.EventArgs) Handles Buttonl.Click filename = InputBox("Введите полное имя файла", , "C:\Text2.txt") Try ’ Чтобы русские буквы читались нормально, ’ объявляем объект Кодировка Dim Кодировка As System.Text.Encoding = System.Text.Encoding.GetEncoding(1251) ’ Создание экземпляра StreamReader для чтения из файла Dim Читатель As New IO.StreamReader(filename, Кодировка) чTextBoxl.Text = Читатель.ReadToEnd() Читатель.Close() Catch Exc As System.10.FileNotFoundException MessageBox.Show("Нет такого файла", "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Exclamation) Catch Exc As Exception ’ Отчет о других ошибках MessageBox.Show(Exc.Message, "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Exclamation)
74 Гпава 3 End Try End Sub Private Sub Button2_Click(ByVai sender As System.Object, ByVai e As System.EventArgs) Handles Button2.Click filename = InputBox("Введите полное имя файла", , "C:\Text2.txt") Try Dim Кодировка As System.Text.Encoding = System.Text.Encoding.GetEncoding(1251) ’ Создание экземпляра Streamwriter для записи в файл: Dim Писатель As New 10.StreamWriter(filename, False, Кодировка) Писатель.Write(TextBoxi.Text) Писатель.Close() Catch exc As Exception ’ Отчет о всех возможных ошибках: MessageBox.Show(exc.Message, "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Exclamation) End Try End Sub End Class Этот текст программы отличается от предыдущего лишь тем, что здесь вве- ден новый объект— Кодировка. Метод GetEncoding (1251) устанавливает ко- довую страницу Windows 1251 ДЛЯ объекта Кодировка. Можно убедиться В ЭТОМ, если распечатать СВОЙСТВО Кодировка.HeaderName. При создании объекта читатель используются уже два аргумента: имя файла filename И объект Кодировка, указывающий, В какой кодировке (ДЛЯ какой КО- ДОВОЙ страницы) читать данные из текстового файла. А при создании объекта Писатель ИСПОЛЬЗуюТСЯ три аргумента: ИМЯ файла filename, установка False (для случая, если файл уже существует, нужно будет не добавлять новые данные, а создавать НОВЫЙ файл) И объект Кодировка, указывающий, в какой кодировке писать данные в файл. Убедиться в работоспособности программы можно, открыв решение TXTJ 251 .sin в папке ТХТ_1251. Пример 23. Простой текстовый редактор. Открытие и сохранение файла. Событие формы Closing Итак, мы уже знаем, что существуют технологии чтения/записи текстового файла для нужной кодовой страницы. Таким образом, мы имеем основные
Чтение, запись текстовых и бинарных файлов, текстовый редактор 75 компоненты для написания текстового редактора. Запустив систему VB2010, перенесем из панели элементов управления Toolbox в форму текстовое поле TextBox и меню MenuStrip (в прежних версиях VB элемент управления для программирования меню назывался MainMenu). Используя элемент управ- ления MenuStrip, создадим один пункт меню Файл и три пункта подменю: Открыть..., Сохранить как... и Выход (рис. 3.2). Рис. 3.2. Простой текстовый редактор Из панели Toolbox нам понадобятся еще элементы управления OpenFileDialog и SaveFileDialog, также перенесем их в форму, хотя их очень легко объявить и использовать непосредственно в программном коде. Итого- вый текст программы Простой текстовый редактор представлен в листин- ге 3.3, и автор заранее приносит свои извинения за слишком длинный про- граммный код, однако короче уже нельзя! | Листинг 3.3. Простой текстовый.редактор' ; ’ Простой текстовый редактор Public Class Forml Private Sub Forml_Load(ByVai sender As Object, ByVai e As System.EventArgs) Handles Me.Load TextBoxl.Multiline = True TextBoxl.Clear() Me.Text = "Простой текстовый редактор" OpenFileDialogl.FileName = Nothing OpenFileDialogl.Filter = "Текстовые файлы (*.txt)I *.txt IAll files (*.*)!*.*" SaveFileDialogl.Filter = "Текстовые файлы (*.txt)I *.txt I All files (*.*)|*.*" End Sub
76 Гпава 3 Private Sub Открыть(ByVai sender As System.Object, ByVai e As System.EventArgs) Handles _ OTKpbrrbToolStripMenuItem. Click ’ Вывести диалог открытия файла OpenFileDialogl.ShowDialog() If OpenFileDialogl.FileName = Nothing Then Exit Sub ’ Чтение Try ’ Создание экземпляра StreamReader для чтения из файла Dim Читатель As New 10.StreamReader(OpenFileDialogl.FileName, System. Text.Encoding.GetEncoding(1251)) ’ — здесь заказ кодовой страницы Winl251 для русских букв TextBoxi.Text = Читатель.ReadToEnd() Читатель.Close() Catch Exc As System.10.FileNotFoundException MessageBox.Show("Нет такого файла", "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Exclamation) Catch Exc As Exception ' Отчет о других ошибках MessageBox.Show(Exc.Message, "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Exclamation) End Try End Sub Private Sub СохранитьКак(ByVai sender As System.Object, ByVai e As System.EventArgs) Handles _ CoxpaHHTbKaKToolStripMenuItem. Click SaveFileDialogl.FileName = OpenFileDialogl.FileName If SaveFileDialogl.ShowDialog = DialogResult.OK Then Запись() End Sub Sub Запись() Try ’ Создание экземпляра Streamwriter для записи в файл: Dim Писатель As New 10.Streamwriter _ (SaveFileDialogl.FileName, False, System. Text.Encoding.GetEncoding(1251)) ’ — здесь заказ кодовой страницы Winl251 для русских букв
Чтение, запись текстовых и бинарных файлов, текстовый редактор 77 Писатель.Write(TextBoxl.Text) Писатель.Close() : TextBoxl.Modified = False Catch Exc As Exception ’ Отчет обо всех возможных ошибках MessageBox.Show(Exc.Message, "Ошибка”, MessageBoxButtons.OK, MessageBoxIcon.Exclamation) End Try End Sub Private Sub Выход(ByVai sender As System.Object, ByVai e As System.EventArgs) Handles _ BbixoflToolStripMenuItem. Click Me.Close () End Sub Private Sub Forml_Closing(ByVai sender As Object, ByVai e As System.ComponentModel.CancelEventArgs) _ Handles MyBase.Closing If TextBoxl.Modified = False Then Exit Sub ' Если текст модифицирован, то спросить, записывать ли файл? Dim МВох As DialogResult = MessageBox.Show( "Текст был изменен." & vbCrLf & "Сохранить изменения?", "Простой редактор", MessageBoxButtons.YesNoCancel, MessageBoxIcon.Exclamation) ’ YES - диалог; NO - выход; CANCEL — редактировать If MBox = DialogResult.No Then Exit Sub If MBox = DialogResult.Cancel Then e.Cancel = True If MBox = DialogResult.Yes Then If SaveFileDialogl.ShowDialog = DialogResult.OK Then Запись() : Exit Sub Else e.Cancel = True ’ Передумал выходить из ПГМ End If End If ' DialogResult.Yes End Sub End Class При загрузке формы Formi Load присваиваем начальные значения некоторым переменным. В частности, для открытия (open) и сохранения (save) файлов
78 Гпава 3 заказываем фильтр (Filter) для текстовых файлов *.txt, а также для всех фай- лов *.*. При обработке события ’’щелчок на пункте меню” Открыть... выводим стан- дартный диалог открытия файлов openFileDialog, и если полученное в ре- зультате диалога имя файла не пусто (Nothing), то организовываем чтение текстового файла. Эта процедура в точности соответствует процедуре чтения файла из предыдущего раздела, разве что упрощен заказ на чтение в коди- ровке Windows 1251. Аналогично написана обработка события ’’щелчок на пункте меню” Сохра- нить как... (см. рис. 3.2). Выводится стандартный диалог saveFiieDiaiog со- хранения файла, и если пользователь щелкнул на кнопке ОК (или Сохра- нить), то вызывается процедура ЗапцсьО. Если нет, то пользователь отправ- ляется редактировать текст. Процедура Запись () также в точности соответствует процедуре записи текстового файла из предыдущего раздела. Как видно, в процедуре Запись о попытка (Try) записи заканчивается опера- тором TextBoxi.Modified = False. СВОЙСТВО Modified Отслеживает изменения в тестовом поле. Понятно, что сразу после записи в файл следует это свойст- во перевести в состояние False. На мой взгляд наибольший интерес представляет организация выхода из про- граммы. Выйти из программы можно либо через пункт меню Выход (см. процедуру обработки события выход в листинге 3.3), либо закрывая програм- му традиционными методами Windows, т. е. нажатием комбинации клавиш <Alt>+<F4>, кнопки Закрыть приложение или кнопки системного меню (слева вверху) (обработка события закрытия формы closing). Момент закрытия формы отслеживаем с помощью события формы closing, которое происходит во время закрытия формы. Обратите внимание, выход по пункту меню Выход организован не через метод Application.Exit о, а через закрытие формы me. close о. Почему? Потому что метод Application. Exit о не вызывает событие формы closing. Обычно выход из любого редактора (текстового, графического, табличного и т. д.) реализуется по следующему алгоритму. Если пользователь не сделал никаких изменений в редактируемом файле, то нужно выйти из программы. Изменения В теКСТОВОМ ПОЛе регистрируются СВОЙСТВОМ TextBoxi.Modified. Если в документе имеются несохраненные изменения (TextBoxi.Modified = True), а пользователь хочет выйти из программы, то выводят диалоговое окно (рис. 3.3). В программе следует обработать каждый из возможных ответов пользователя по алгоритму, представленному на рис. 3.4.
Чтение, запись текстовых и бинарных файлов, текстовый редактор 79 Рис. 3.3. Диалоговое окно при выходе из программы Рис. 3.4. Алгоритм обработки ответа пользователя программы Обращаем внимание читателя на ветвь алгоритма "Отмена” (Cancel). Это случай, когда пользователь передумал выходить из программы и желает вер- нуться к редактированию файла. Для реализации этого случая (см. лис- тинг 3.3) обработка события closing предусматривает булево свойство е.Cancel, которому можно присвоить значение True, означающее отказ от за- крытия программы (пользователь передумал), т. е. в этом случае процедура Formi ciosing не закончится выходом из программы. Аналогично, если пользователь согласился сохранить данные, то он попадает в стандартный диалог сохранения файла, и если при этом он передумал (диа- лог сохранения закрыт кнопкой Отмена или комбинацией клавиш <Alt>+<F4>), то следует предложить пользователю продолжить редактирова- ние файла: е.Cancel = True. Как ВИДНО, В Процедуре Formi ciosing, к сожале- нию, не удается избежать вложенных операторов условия. Убедиться в работоспособности программы можно, открыв решение TXT_edit.sln в папке TXT_edit.
80 Гпава 3 Пример 24. Простой RTF-редактор Читателю, вероятно, известно, что VB2010 имеет элемент управления RichTextBox (форматированное текстовое поле), так же как и предыдущие версии VB, включая VB6. Этот элемент управления позволяет осуществлять форматирование текста в популярном стандарте RTF (один из форматов MS Word). В формате RTF в текст вводятся специальные коды форматирования, несущие информацию о гарнитуре, размерах шрифтов, стилях символов и абзацев, выравнивании и других возможностях форматирования. Напишем очень простой RTF-редактор, который читает как RTF-файлы, так и обычные текстовые файлы в кодировке Windows 1251, но сохраняет файлы на диск в любом случае в формате RTF. Для этой цели перенесем из панели элементов управления Toolbox элементы управления RichTextBox, меню MenuStrip (в прежних версиях VB элемент управления для программирова- ния меню назывался MainMenu), SaveFileDialog и OpenFileDialog. В выпа- дающем меню Файл предусмотрим такие пункты меню, как показано на рис. 3.5: Открыть в формате RTF..., Открыть в формате Winl251..., Со- хранить в формате RTF... и Выход. Текст программы приведен в листин- ге 3.4. Листинг 3,4« Простой RTF-редактор - ’ Программа простейшего RTF-редактора Public Class Forml Private Sub Forml_Load(ByVai sender As System.Object, ByVai e As System.EventArgs) Handles MyBase.Load Me.Text = "Простой RTF-редактор" RichTextBoxl.Clear() OpenFileDialogl.FileName = Nothing SaveFileDialogl.Filter = "Файлы RTF (*.RTF)|*.RTF" End Sub ’ Процедура обработки двух событий Private Sub Открыть(ByVai sender As System.Object, ByVai e As System.EventArgs) Handles _ ОткрытьВФорматеИТЕТоо!St ripMenuItem .Click, OткpытьBФopмaтeWinl251ToolStripMenuItern.Click ’ Выясняем, в каком формате открыть файл Dim format As String = CType(sender, ToolStripMenuItem).Text
Чтение, запись текстовых и бинарных файлов, текстовый редактор 81 Try ’ Открыть в каком-либо формате If format = "Открыть в формате RTF..." Then OpenFileDialogl.Filter = "Файлы RTF (*.RTF)I*.RTF" OpenFileDialogl.ShowDialog() If OpenFileDialogl.FileName = Nothing Then Exit Sub RichTextBoxl.LoadFile(OpenFileDialogl.FileName) End If If format = "Открыть в формате Winl251..." Then OpenFileDialogl.Filter = "Текстовые файлы (*.txt)I*.txt" OpenFileDialogl.ShowDialog() If OpenFileDialogl.FileName = Nothing Then Exit Sub RichTextBoxl.LoadFile(OpenFileDialogl.FileName, RichTextBoxStreamType.PlainText) End If RichTextBoxl.Modified = False Catch Exc As System.10.FileNotFoundException MessageBox.Show("Нет такого файла", "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Exclamation) Catch Exc As Exception ’ Отчет о других ошибках MessageBox.Show(Exc.Message, "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Exclamation) End Try End Sub Private Sub Сохранить(ByVai sender As System.Object, ByVai e As System.EventArgs) Handles _ CoxpaHHTbBOopMaTeRTFToolStripMenuItem.Click SaveFileDialogl.FileName = OpenFileDialogl.FileName If SaveFileDialogl.ShowDialog = DialogResult.OK Then Запись() End Sub Sub Запись () Try RichTextBoxl.SaveFile(SaveFileDialogl.FileName) RichTextBoxl.Modified = False Catch Exc As Exception ’ Отчет о всех возможных ошибках: MessageBox.Show(Exc.Message, "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Exclamation)
82 Гпава 3 End Try End Sub Private Sub Выход(ByVai sender As System.Object, ByVai _ e As System.EventArgs) Handles BbixoflToolStripMenuItem.Click Me.Close() End Sub Private Sub Forml_Closing(ByVai sender As Object, ByVai e As System.ComponentModel.CancelEventArgs) _ Handles MyBase.Closing If RichTextBoxl.Modified = False Then Exit Sub ' Если текст модифицирован, то выясняем, записывать ли файл? Dim MBox As DialogResult = MessageBox.Show( "Текст был изменен." & vbCrLf & "Сохранить изменения?", "Простой редактор", MessageBoxButtons.YesNoCancel, MessageBoxIcon.Exclamation) ' YES - диалог; NO - выход; CANCEL — редактирование If MBox = DialogResult.No Then Exit Sub If MBox = DialogResult.Cancel Then e.Cancel = True If MBox = DialogResult.Yes Then If SaveFileDialogl.ShowDialog = DialogResult.OK Then Запись() : Exit Sub Else e.Cancel = True ' Передумал выходить из ПГМ End If End If ' — DialogResult.Yes End Sub End Class Структура программы аналогична программе простого текстового редактора, описанного в предыдущем разделе. При загрузке формы задаем начальные значения некоторым переменным (см. текст программы). Два события — вы- бор пунктов меню Открыть в формате RTF и Открыть в формате Winl251 — обрабатываются ОДНОЙ процедурой Открыть. Подробно особенно- сти обработки событий, создаваемых разными объектами, обсуждены нами в примерах 17, 18 и др. (см. главу 2). Из этих примеров читатели знают, что сведения об объекте, создавшем событие, находятся в объектной переменной
Чтение, запись текстовых и бинарных файлов, текстовый редактор 83 sender. Какой пункт меню указал пользователь, можно узнать, получив СВОЙСТВО Text ИЗ выражения СТуре (sender, ToolStripMenuItem) .Text (см. листинг 3.4). Таким образом, в строковую переменную format попадает или строка "Открыть в формате RTF...", или строка "Открыть в формате Win 1251...". Метод LoadFile объекта RichTextBoxl загружает либо файл В формате RTF, либо файл в обычном текстовом формате. Перехват ошибок Catch сообщает пользователю либо о том, что такого файла нет, либо если пользователь использует пункт меню Открыть в формате RTF... для от- крытия текстового файла, он получает сообщение ’’Недопустимый формат файла”. Сохранение файла (рис. 3.5) выполняется также с использованием стандарт- ного диалога SaveFiieDiaiog. Непосредственное сохранение файла удобнее всего ВЫПОЛНЯТЬ В отдельной процедуре Запись о, поскольку эту процедуру необходимо вызывать также при выходе из программы, когда в документе имеются несохраненные изменения RichTextBoxl.Modified = True. ..-.—...-..-же столько Рис. 3.5. Простой RTF-редактор В основе процедуры запись о также лежит блок Try.. .Catch: выполнить по- пытку Try сохранения SaveFile файла, при этом перехватить (catch) возмож- ные недоразумения и сообщить о них пользователю в диалоговом окне MessageBox. Выход из программы организован абсолютно так же, как и в программе из примера 23. К тому же обработаны два события — пункт меню Выход и все- возможные закрытия программы традиционными способами Windows. Пре- дусмотрен диалог с пользователем в случае имеющих место несохраненных данных. Замечу, для закрытия приложения следует осторожно пользоваться методом Exit объекта Application (можно сказать, с оглядкой). Этот метод подготав- ливает приложение к закрытию. Да, метод Application.Exit о не вызывает события формы closing. Но попробуйте проследить за поведением програм- мы после команды Application.Exit с помощью отладчика (клавиша <F11>). Вы убедитесь, что после команды Application.Exit управление перейдет на
84 Гпава 3 следующий оператор, затем на следующий и так до конца процедуры. Если на пути встретится функция MessageBox, то программа выдаст это диалоговое окно, и это несмотря на то, что уже давно была команда Application.Exit. Аналогично ведет себя метод close элемента Form (если вы работаете с проек- том Windows Application), который вызывается таким образом: Me.cioset). Да, Me.close вызывает событие формы closing. Этот метод закрывает форму и освобождает все ресурсы. Но для освобождения ресурсов после команды Me.close управление также пройдет все операторы процедуры. Таким обра- зом, для немедленного выхода из процедуры следует комбинировать назван- ные методы с Exit Sub. В VB2010 сохранилась возможность использования оператора End, как это было в VB6. Однако пользоваться им не стоит, по- скольку он не предусматривает освобождения ресурсов. Убедиться в работоспособности программы можно, открыв решение RTFedit.sIn в папке RTFedit. Пример 25. Печать текстового документа Любой текстовый редактор (и не только текстовый) должен иметь возмож- ность печати на принтере. Мы сознательно не добавляли такую возможность в текстовые редакторы, приведенные в предыдущих разделах, чтобы не запу- тать читателя. Понятно, что чем больше возможностей имеет программа, тем сложнее ее программный код, тем труднее текст программы для понимания. А наша задача — выразительно и ярко демонстрировать технологии в макси- мально простой форме. Программа, представленная в данном разделе, имеет такие скромные воз- можности: открыть в стандартном диалоге Windows текстовый файл, про- смотреть его в окне программы (в текстовом поле) без возможности измене- ния текста (Readonly) и при желании пользователя вывести этот текст на принтер. Таким образом, чтобы создать данную программу, следует в форму перене- сти следующие элементы управления: текстовое поле TextBox, меню MenuStrip с пунктами меню: Открыть..., Печатать... и Выход, а также эле- менты управления OpenFileDialog и PrintDocument. Текст программы пред- ставлен в листинге 3.5. Листинг 3.5. Печать текстового документа ' Программа позволяет открыть в стандартном диалоге текстовый файл, ' просмотреть его в текстовом поле без возможности изменения текста ' (Readonly) и при желании пользователя вывести этот текст на принтер. Public Class Forml Dim Читатель As IO.StreamReader
Чтение, запись текстовых и бинарных файлов, текстовый редактор 85 Private Sub Forml_Load(ByVai sender As System.Object, ByVai e As System.EventArgs) Handles MyBase.Load Me.Text = "Открытие текстового файла и его печать" TextBoxl.Multiline = True TextBoxl.ScrollBars = ScrollBars.Vertical TextBoxl.Readonly = True TextBoxl.Clear() ' До тех пор, пока файл не прочитан в текстовое поле, ' не должен быть виден пункт меню "Печать..." ne4aTbToolStripMenu!tem.Visible = False OpenFileDialogl.FileName = Nothing End Sub Private Sub Открыть(ByVai sender As System.Object, ByVai e As System.EventArgs) _ Handles OTKpbribToolStripMenuItern.Click ' Пункт меню "Открыть..." OpenFileDialogl.Filter = "Текстовые файлы (*.txt) I *.txt I All files (*.*)|*.*" OpenFileDialogl.ShowDialog() If OpenFileDialogl.FileName = Nothing Then Exit Sub Try ' Создание потока StreamReader для чтения из файла Читатель = New 10.StreamReader(OpenFileDialogl.FileName, System. Text.Encoding.GetEncoding(1251)) ' — здесь заказ кодовой страницы Winl251 для русских букв TextBoxl.Text = Читатель.ReadToEnd() Читатель.Close() ne4aTbToolStripMenu!tem.Visible = True Catch Exc As System.10.FileNotFoundException MessageBox.Show("Нет такого файла", "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Exclamation) Catch Exc As Exception ' Отчет о других ошибках: MessageBox.Show(Exc.Message, "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Exclamation)
86 Гпава 3 End Try End Sub Private Sub Печать(ByVai sender As System.Object, ByVai e As System.EventArgs) _ Handles neuaTbToolStripMenuLtem.Click ' Пункт меню "Печать..." Try Читатель = New 10.StreamReader(OpenFileDialogl.FileName, System. Text.Encoding.GetEncoding(1251)) ' — здесь заказ кодовой страницы Winl251 для русских букв Try PrintDocument1.Print() Finally Читатель.Close() End Try Catch ex As Exception MessageBox.Show(ex.Message) End Try End Sub Private Sub PrintPage(ByVai sender As Object, ByVai e _ t As System.Drawing.Printing.PrintPageEventArgs) _ Handles PrintDocumentl.PrintPage Dim linesPerPage As Single = 0 Dim yPos As Single = 0 Dim count As Integer = 0 Dim leftMargin As Single = e.MarginBounds.Left Dim topMargin As Single = e.MarginBounds.Top Dim line As String = Nothing Dim printFont = New Font("Times New Roman", 12.0!) ’ Вычисляем количество строк на одной странице linesPerPage = e.MarginBounds.Height / printFont.GetHeight(e.Graphics) 1 Печатаем каждую строку файла While count < linesPerPage line = Читатель.ReadLine() If line Is Nothing Then Exit While End If
Чтение, запись текстовых и бинарных файлов, текстовый редактор 87 yPos = topMargin + count * printFont.GetHeight(е.Graphics) ' Печать строки e.Graphics.Drawstring(line, printFont, Brushes.Black, leftMargin, yPos, New StringFormat) count += 1 End While ' Печать след страницы, если есть еще строки файла If Not (line Is Nothing) Then e.HasMorePages = True Else e.HasMorePages = False End If End Sub Private Sub Выход(ByVai sender As System.Object, ByVai e As System.EventArgs) Handles ВыходТоо1StripMenuItern.Click ’ Выход из программы Me.Close() End Sub End Class Здесь при обработке события загрузки формы Formi Load запрещаем пользо- вателю редактировать текстовое поле: Readonly = True. Также назначаем СВОЙСТВУ He4aTbToolStripMenuItem.Visible = False (пункт меню Печать...), т. е. в начале работы программы пункт меню Печать... пользователю не ви- ден (поскольку пока распечатывать нечего, необходимо вначале открыть тек- стовый файл). Остальные присваивания при обработке события Formi Load очевидны. При обработке события ’’щелчок на пункте меню” Открыть... вызываем стандартный диалог openFiieDiaiog и организуем чтение файла через созда- ние потока StreamReader. Эти процедуры мы уже рассматривали подробно в разделах о текстовых редакторах, поэтому оставим их без комментария. За- мечу только, что после чтения файла в текстовое поле назначаем видимость пункту меню Печать...: ne4aTbToolStripMenuItem.Visible = True, поскольку уже есть, что печатать на принтере (файл открыт). Представляет интерес обработка события ’’щелчок на пункте меню” Пе- чать..., Этот пункт написан автором по технологии, приведенной в справоч- ной системе по Visual Basic (MSDN). Здесь во вложенных блоках Try.. .Finally.. .Catch программа еще раз создает поток StreamReader, а затем
88 Гпава 3 запускает процесс печати документа PrintDocument 1. Print. Если ничего более не программировать, только метод PrintDocumenti.Print, то принтер распеча- тает только пустую страницу. Чтобы принтер распечатал текст, необходимо обработать событие PrintPage (см. текст программы), которое создает объект PrintDocument. То еСТЬ рОЛЬ метода Print — ЭТО создать событие PrintPage. Обратите внимание на обработку события PrintDocumenti.PrintPage. Пример обработки этого события приведен в MSDN. Вначале перечислены объявле- ния переменных, значения некоторых из них получаем из аргументов собы- тия е, например, leftMargin— значецие отступа от левого края, и т. д. Назна- чаем шрифт печати — Times New Roman, 12 пунктов. Далее в цикле while программа читает каждую строку line из файла— чита- тель . ReadLine о, а затем распечатывает ее командой (методом) Drawstring. Здесь используется графический объект Graphics, который получаем из аргу- мента события е. В переменной count происходит счет строк. Если количество строк оказыва- ется большим, чем число строк на странице linesPerPage, то происходит вы- ход из цикла, поскольку страница распечатана. Если есть еще страницы, а программа выясняет это, анализируя переменную line— if Not (line is Nothing), TO аргументной переменной e.HasMorePages назначаем True, что инициирует ОПЯТЬ событие PrintPage И подпрограмма PrintDocumenti. Print начинает свою работу вновь. И так, пока не закончатся все страницы e.HasMorePages = False ДЛЯ печати на принтере. На рис. 3.6 показан интерфейс приложения. Рис. 3.6. Фрагмент работы программы печати текстового файла Убедиться в работоспособности программы можно, открыв решение TXT print.sln в папке TXT print.
Чтение, запись текстовых и бинарных файлов, текстовый редактор 89 Пример 26. Чтение/запись бинарных файлов с использованием потока данных Обычно программа либо что-то читает с диска в оперативную память, либо что-то пишет на диск. Писать, читать можно либо в бинарный (двоичный) файл, либо в текстовый (литерный, строковый) файл. Разница между ними состоит в том, что текстовый файл можно прочитать текстовым редактором, например Блокнотом, а бинарный— нет. Название ’’бинарный” (двоич- ный)— условное, поскольку, по сути, и текстовый, и бинарный файлы явля- ются двоичными файлами. Операции с двоичным файлом гораздо более скоростные, и такой файл зани- мает существенно меньшее пространство на диске. Зато текстовый файл можно читать и редактировать любым текстовым редактором. Обычно про- граммист выбирает компромисс между этими двумя преимуществами. Приведем пример самого простейшего случая записи на диск бинарного фай- ла с данными об успеваемости одного студента. Понятно, что эта программа может быть маленькой частью большой программы по обработке успеваемо- сти студентов в вузе. Данная программа принимает от пользователя сведения только об одном студенте в текстовые поля формы. При нажатии кнопки Со- хранить программа записывает введенные сведения в двоичный файл, а при нажатии кнопки Читать читает эти сведения из двоичного файла в текстовые поля формы. Итак, в форме имеем три текстовых поля, куда пользователь может записать соответственно номер студента по порядку, фамилию студента и его средний балл успеваемости. Поэтому в форму из панели Toolbox перенесем три тек- стовых поля TextBox, три метки Label и две командные кнопки: Читать и Сохранить. Таким образом, получим пользовательский интерфейс, показан- ный на рис. 3.7. Текст программы приведен в листинге 3.6. ' Листинг 3.6. Чтение/запись бинарных файлов ' Программа для чтения/записи бинарных файлов ’ с использованием потока данных Public Class Forml Private Sub Forml_Load(ByVai sender As System.Object, ByVai e As System.EventArgs) Handles MyBase.Load Labeli.Text = "Номер п/п" Label2.Text = "Фамилия И.О." Label3.Text = "Средний балл" MyBase.Text = "Успеваемость студента"
90 Гпава 3 TextBoxl.Clear() : TextBox2.Clear() : TextBox3.Clear() Buttonl.Text = "Читать" : Button2.Text = "Сохранить" End Sub Private Sub Чтение(ByVai sender As System.Object, ByVai e As System.EventArgs) Handles Buttonl.Click 1 ЧТЕНИЕ ' Если такого файла нет If 10.File.Exists("С:\student.usp") = False Then Exit Sub ' Создание потока Читатель Dim Читатель As New 10.BinaryReader( 10.File.OpenRead("C:\student.usp")) Try Dim nomer As Integer = Читатель.Readlnt32 Dim FIO As String = Читатель.Readstring Dim Ball As Single = Читатель.ReadSingle TextBoxl.Text = Convert.ToString(nomer) TextBox2.Text = Convert.ToString(FIO) TextBox3.Text = Convert.ToString(Ball) Finally Читатель.Close() End Try End Sub Private Sub Запись(ByVai sender As System.Object, ByVai e As System.EventArgs) Handles Button2.Click 1 ЗАПИСЬ ’ Создаем поток Писатель для записи байтов в файл Dim Писатель As New 10.Binarywriter( 10.File.Open("С:\student.usp", 10.FileMode.Create)) Try Dim nomer As Integer = Convert.Tolnt32(TextBoxl.Text) Dim FIO As String = Convert.ToString(TextBox2.Text) Dim Ball As Single = Convert.ToSingle(TextBox3.Text) Писатель.Write(nomer) Писатель.Write(FIO) Писатель.Write(Ball) Finally Писатель.Close()
Чтение, запись текстовых и бинарных файлов, текстовый редактор 91 End Try End Sub End Class Как видно, при обработке события Formi Load организована инициализация (присвоение начальных значений) элементам формы: текстовых полей, меток и кнопок. Запись файла на диск происходит при обработке события Button2. Click, т. е. щелчок мышью на кнопке Сохранить (рис. 3.7). Для этого создаем поток байтов писатель для открытия файла student.usp. При этом если такого файла не существует, то он создается (create), а если такой файл уже есть, то он пе- резаписывается. Как видно, для упрощения программы мы не использовали элемент управления OpenFiieDiaiog для открытия файла в диалоге. Рис. 3.7. Фрагмент работы программы чтения/записи бинарных файлов Далее преобразуем записанное в текстовых полях в более естественные типы данных. Номер по порядку nomer — это тип integer, преобразование в целый тип может быть реализовано операцией convert.Toint32 (можно использовать другие функции преобразования), для переменной Ball (средний балл) боль- ше всего подходит тип с плавающей точкой single, при этом преобразование осуществляется операцией convert.ToSingie. Преобразование для строковой переменной fio является необязательным и приведено для симметрии запи- сей. Операторы писатель.write записывают эти данные в файл. После блока Finally происходит закрытие (close) файла. Чтение файла происходит при обработке события ’’щелчок мышью на кноп- ке” Читать. Как уже упоминалось, для максимального упрощения в данной программе не предусмотрено открытие файла через стандартный диалог, по- этому в начале процедуры выясняем, существует ли такой файл. Если файла C:\student.usp нет, то программируем выход (Exit sub) из обработчика данно-
Гпава 3 го события. Заметьте, чтобы программисту было максимально легко отсле- живать ветви оператора if, мы написали: "Если файла нет, то Exit Sub". При этом длинная ветвь логики "если файл есть" не включена непосредственно в оператор if. Поэтому этот фрагмент программного кода читается (восприни- мается) программистом легко. Далее создается поток байтов читатель из файла student.usp, открытого для чтения. Чтение из потока в каждую переменную реализовано с помощью функции Readlnt32 — читать ИЗ потока Читатель В переменную типа Integer, аналогично функциям Readstring и Readsingle. Далее осуществлено конвер- тирование этих переменных в строковый тип convert.ToString. Как видно, можно было изначально все текстовые поля записывать в файл без конверти- рования, но при дальнейшем развитии этой программы значения полей все равно пришлось бы преобразовывать в соответствующий тип. После блока Finally происходит закрытие (close) файла. Блок Finally выполнится всегда, даже если перед ним была команда Exit sub. Дальнейшее развитие данной программы может быть по пути добавления в файл сведений о других студентах. В таком случае при чтении файла будет неопределенность количества студентов. Тогда следует обработать ситуацию достижения конца файла: Catch Exc As lO.EndOfStreamException а затем закрыть файл. Убедиться в работоспособности программы можно, открыв решение Read_Write_bin.sln в папке Read_Write_bin.
ГЛАВА 4 Редактирование графических данных Пример 27. Простейший вывод отображения графического файла в форму Поставим задачу вывода в форму какого-нибудь изображения растрового графического файла формата BMP, JPEG, PNG или других форматов. Для решения этой задачи запустим VB2010, выберем шаблон Windows Forms Application. Двойной щелчок на проекте формы приведет нас на вкладку программного кода. Работать с графикой в форме можно по-разному. Пока- жем работу с графикой через переопределение метода OnPaint. Метод OnPaint является членом класса Form. Этот метод можно увидеть, на- брав Forml внутри какой-нибудь процедуры, в выпадающем списке методов и свойств объекта Forml (рис. 4.1). ^узазе Ena Sub OnPawtt OnPaddingChanged OnPa»ntBackg round & OnParen^ckCdorCKanged OnParentBackgroundlniageChanged OnPafent&ndtngContextChafnged OnParen^Changed Рис. 4.1. Часть списка методов и свойств объекта Forml Метод OnPaint можно переопределить, т. е. добавить к уже существующим функциям собственные. Для этого в окне программного кода напишем: Protected Overrides sub
94 Гпава 4 и в появившемся выпадающем списке выберем OnPaint, система сама сгене- рирует необходимые строчки процедуры, подлежащей переопределению: Public Class Forml Protected Overrides Sub OnPaint( ByVai e As System.Windows.Forms.PaintEventArgs) MyBase.OnPaint(e) End Sub End Class Теперь этот программный код следует дополнить командами для вывода в форму изображения из растрового файла poryv.png (листинг 4.1). Листинг 4.1. Вывод растрового изображения в форму (вариант 1) : ' Программа выводит в форму растровое изображение из графического файла Public Class Forml Protected Overrides Sub OnPaint( ByVai e As System.Windows.Forms.PaintEventArgs) MyBase.OnPaint(e) MyBase. Text = ’’Рисунок” ' Размеры формы Me.Width = 200 : Me.Height = 200 ' Создаем объект для работы с изображением Dim Рисунок As Image = New Bitmap("С:Wporyv.png”) ' или Dim Рисунок As Bitmap = New Bitmap(”C:Wporyv.png") ' Вывод изображения в форму е.Graphics.Drawlmage(Рисунок, х:=5, у:=5) ' х:=5, у:=5 — это координаты левого верхнего угла рисунка в ' системе координат формы: ось х — вниз, ось у — вправо End Sub End Class Как видно из текста программы, вначале указываем размеры формы с по- мощью свойств width и Height, хотя размеры формы удобно регулировать на вкладке конструктора формы ’’визуально”. Далее создаем объект Рисунок для работы с изображением с указанием пути к файлу рисунка. Затем обращаемся непосредственно к методу рисования изображения в форме Drawimage, извле- кая графический объект Graphics из аргумента е процедуры OnPaint. Фрагмент работы программы показан на рис. 4.2.
Редактирование графических данных 95 Рис. 4.2. Вывод растрового изображения в форму Заметим, что это не единственный способ работы с графикой. Другой спо- соб— это вызвать тот же метод OnPaint косвенно через событие формы onPaint. Такой способ работы с графикой представлен в листинге 4.2. I Листинг 4.2. Вывод растрового изображения в форму (вариант 2) Public Class Forml ' Простейший вывод изображения в форму Private Sub Forml_Load(ByVai sender As System.Object, ByVai e As System.EventArgs) Handles MyBase.Load MyBase.Text = ’’Рисунок" End Sub Private Sub Forml_Paint(ByVai sender As Object, ByVai e As System. Windows.Forms.PaintEventArgs) Handles Me.Paint ’ Событие рисования формы ' Создаем объект для работы с изображением Dim Рисунок As Image = New Bitmap("С:Wporyv.png") ’ Вывод изображения в форму е.Graphics.Drawlmage(Рисунок, х:=5, у:=5) End Sub End Class Покажем еще один способ вывода графики в форму. В этом способе при щелчке на командной кнопке происходит непосредственное создание объекта класса Graphics. Программный код показан в листинге 4.3.
96 Гпава 4 Листинг 4.3. Вывод растрового-изображения.в форму (вариант 3) Public Class Forml Private Sub Forml_Load(ByVal sender As System.Object, ByVai e As System.EventArgs) Handles MyBase.Load MyBase.Text = "Рисунок" Buttonl.Text = "Показать рисунок" End Sub Private Sub Buttonl_Click(ByVai sender As System.Object, ByVai e As System.EventArgs) Handles Buttonl.Click 1 Событие "щелчок на кнопке" Dim Рисунок As Bitmap = New Bitmap("C:Wporyv.png") Dim Графика As Graphics = CreateGraphics() Графика.Drawlmage(Рисунок, x:=5, y:=5) End Sub End Class Убедиться в работоспособности данных программ можно, открыв соответст- вующие решения в папках Simple_Imagel, Simple_Image2 и Simple_lmage3. В заключение заметим, что рассмотренными в данном разделе методами можно работать не только для вывода изображений графических файлов в форму, но и для многих других задач, связанных с графикой. Пример 28. Рисование в форме указателем мыши В данном примере покажем, как можно рисовать мышью в форме. То есть задача состоит в том, чтобы написать программу, позволяющую при нажатой левой или правой кнопке мыши рисовать в форме. Если пользователь отпус- тит кнопку мыши, то рисование прекращается. В проектируемой форме сле- дует предусмотреть кнопку Стереть, которая предназначена для очистки формы. Вначале надо создать форму с командной кнопкой, как мы это делали преж- де. Текст программы представлен в листинге 4.4. [ Листинг 4.4. Рисование на форме указателем мыши ...— ........ * Программа позволяет при нажатой левой или * правой кнопке мыши рисовать в форме Public Class Forml Dim ris As Boolean = False * He рисовать
Редактирование графических данных 97 Private Sub Forml_Load (ByVai sender As System.Object, ByVai e As System.EventArgs) Handles MyBase.Load Me.Text = "Рисую мышью в форме" Buttonl.Text = "Стереть" End Sub Private Sub Forml_MouseDown(ByVai sender As Object, ByVai e As System.Windows.Forms.MouseEventArgs) _ Handles MyBase.MouseDown ' Если нажата кнопка мыши — MouseDown, то рисовать ris = True End Sub Private Sub Forml_MouseUp(ByVai sender As Object, ByVai e As System.Windows.Forms.MouseEventArgs) _ Handles MyBase.MouseUp ’ Если кнопку мыши отпустили, то НЕ рисовать ris = False End Sub Private Sub Forml_MouseMove(ByVai sender As Object, ByVai e As System.Windows.Forms.MouseEventArgs) _ Handles MyBase.MouseMove ' Рисование прямоугольника, если нажата кнопка мыши If ris = True Then ' Рисовать прямоугольник в точке е.Х, e.Y Dim gra As Graphics = CreateGraphics() gra.FillRectangle(New SolidBrush(Color.Red), e.X, e.Y, 10, 10) ' 10x10 пикселов — размер сплошного прямоугольника ' е.Х, e.Y — координаты указателя мыши End If End Sub Private Sub СТЕРЕТЬ(ByVai sender As System.Object, ByVai e As System.EventArgs) Handles Buttonl.Click ' Dim gra As Graphics = CreateGraphics() ’ gra.Clear(ColorTranslator.FromHtml("#EFEBDE")) ’ gra.Clear(Color. FromName("Control")) ' gra.Clear(Color.FromKnownColor(KnownColor.Control)) Me.RefreshO ’ Этот метод перерисовывает форму End Sub End Class 4 Зак 145
98 Гпава 4 Здесь в начале программы объявлена переменная ris логического типа (Boolean) со значением False. Эта переменная либо позволяет (ris =True) ри- совать в форме при перемещении мыши (событие MouseMove), либо не позво- ляет (ris = False). Область действия переменной ris весь КЛаСС Forml, т. е. изменить или выяснить ее значение можно в любой процедуре (sub) этого класса. Значение переменной ris может изменить либо событие Mouseup (кнопку МЫШИ отпустили, рисовать нельзя, ris = False), либо событие MouseDown (кнопку мыши нажали, рисовать можно, ris = True). При перемещении мы- ши с нажатой кнопкой программа создает графический объект Graphics про- странства имен System. Drawing, ИСПОЛЬЗуя метод CreateGraphics (), И рисует прямоугольник gra.FiiiRectangleO, заполненный красным цветом, размером 10x10 пикселов, е.х, e.Y— координаты указателя мыши, которые так же яв- ляются координатами левого верхнего угла прямоугольника. На рис. 4.3 приведен пример рисования в форме. Чтобы стереть все нарисо- ванное в форме, следует нажать кнопку Стереть. При этом вызывается метод Refresho, предназначенный для перерисовывания формы. Здесь в коммента- рии приведены варианты реализации очистки формы от всего нарисованного на ней пользователем. Например, путем создания графического объекта CreateGraphics () и закрашивания формы в ее первоначальный цвет KnownColor.Control. Рис. 4.3. Рисование мышью на форме Заметим, что можно было бы очистить область рисования более короткой командой clear (Color, white), т. е. закрасить форму белым цветом (white) ли- бо выбрать другой цвет из списка 146 цветов после ввода точки после слова color. Однако ни один из 146 цветов не является первоначальным цветом формы (BackCoior). Поэтому задаем этот цвет через другие константы цвета,
Редактирование графических данных 99 представленные в перечислении Color.FromKnownColor. Также можно задать цвет как Color. FromName ("Control"). МОЖНО ИСПОЛЬЗОвать функцию перевода шестнадцатеричного кода цвета ColorTranslator.FromHtmlo. Оба эти вариан- та представлены в комментарии. Цвет #efebde является шестнадцатеричным представлением нужного нам цвета. Очистить форму от всего нарисованного на ней можно так же, свернув ее, а затем восстановив. Рисовать в форме можно как левой, так и правой кноп- ками мыши. Убедиться в работоспособности программы можно, открыв решение RisForm.sln в папке RisForm. Пример 29. Рисование в форме графических примитивов (фигур) В векторных чертежах графическим примитивом называют элементарные составляющие чертежа: отрезок, дуга, символ, окружность и др. Здесь мы имеем дело с растровой графикой, но в данном случае подход тот же — по координатам рисуем те же фигуры. Система координат такая: начало коорди- нат— это левый верхний угол формы, ось Ох направлена вправо, а Оу — вниз. Наша задача состоит в том, чтобы рисовать в форме окружность, отрезок, прямоугольник, сектор, текст, эллипс и закрашенный сектор. Выбор того или иного графического примитива осуществить через элемент управления ListBox. Причем при рисовании очередного графического примитива нужно ’’стереть” предыдущий рисунок. Для решения этой задачи создадим форму и перетащим в нее из окна Toolbox элемент управления ListBox. Далее — двойной щелчок в пределах формы, где в пустом обработчике события Formi_Load создадим список графических примитивов, заполняя коллекцию (items) элементов списка ListBoxi (лис- тинг 4.5). Листинг 4.5. Рисование на форме графических примитивов ' Программа позволяет рисовать в форме графические примитивы: ' окружность, отрезок, прямоугольник, сектор, текст, эллипс и ' закрашенный сектор. Выбор того или иного графического примитива ' осуществляется с помощью элемента управления ListBox Public Class Forml Private Sub Forml_Load(ByVai sender As System.Object, ByVai e As System.EventArgs) Handles MyBase.Load
100 Гпава 4 ListBoxl.Items. AddRange(New Object() {"Окружность”, "Отрезок”, "Прямоугольник", "Сектор", "Текст", "Эллипс", "Закрашенный сектор"}) ' Font = New Font("Times New.Roman", 14) Me.Text = "Выбери графический примитив" End Sub Private Sub ListBoxl_Click(ByVai sender As Object, ByVai e As System.EventArgs) Handles ListBoxl.Click ' Создание графического объекта Dim graph As Graphics = MyBase.CreateGraphics ' Создание пера для рисования им фигур Dim penl As New Pen(Color.Red) ' Создание кисти для "закрашивания" фигур Dim brushl As New SolidBrush(Color.Red) ' Очистка области рисунка путем ее окрашивания в ' первоначальный цвет формы graph.Clear(Color.FromName("Control")) ' graph.Clear(ColorTranslator.FromHtml("#EFEBDE")) Select Case ListBoxl.Selectedlndex Case 0 ' — выбрана окружность: graph.DrawEllipse(penl, 50, 50, 150, 150) Case 1 ' — выбран отрезок: graph.DrawLine(penl, 50, 50, 200, 200) Case 2 ’ — выбран прямоугольник: graph.DrawRectangle(penl, 50, 30, 150, 180) Case 3 ' — выбран сектор: graph.DrawPie(penl, 40, 50, 200, 200, 180, 225) Case 4 ' — выбран текст: Dim s As String s = "Каждый во что-то верит, но" & vbCrLf & " жизнь преподносит сюрпризы." graph.Drawstring(s, Font, brushl, 10, 100) Case 5 ' — выбран эллипс: graph.DrawEllipse(penl, 30, 30, 150, 200) Case 6 ' — выбран закрашенный сектор: graph.FillPie(brushl, 20, 50, 150, 150, 0, 45) End Select End Sub End Class
Редактирование графических данных 101 В программе, обрабатывая событие Click по выбранному элементу списка, создаем: графический объект graph, перо peni для рисования им фигур, кисть brushi для "закрашивания" ею фигур. Далее очищаем область рисования пу- тем окрашивания формы в первоначальный цвет "Control" или #efebde (как записано в комментарии), используя метод clear о объекта graph: graph.Clear(Color.FromName("Control”)) Процедура окрашивания формы в какой-либо цвет выглядела бы менее гро- моздко, если бы мы использовали какую-либо константу, означающую цвет, например, white или любую другую из списка 146 констант цвета. Тогда мы бы написали: graph.Clear(Color.White) В таком случае пришлось бы при инициализации переменных при загрузке формы задать другой цвет формы: Me.BackColor = System.Drawing.Color.White Однако хотелось бы, чтобы цвет формы оставался первоначальным — ’’Control". Кстати, этот цвет можно назвать цветом Microsoft: это цвет Windows Explorer, Internet Explorer и пр. После очистки формы, используя свойство seiectindex, которое указывает на номер выбранного пользователем элемента списка (от 0 до 6), рисуем вы- бранную фигуру. На рис. 4.4 представлен фрагмент работы программы. Рис. 4.4. Рисование графического примитива на форме Убедиться в работоспособности программы можно, открыв решение Ris_Figur.sln в папке Ris Figur.
102 Гпава 4 Пример 30. Выбор цвета с использованием ListBox В этом разделе мы ставим задачу написать программу, которая меняет цвет фона формы BackCoior, перебирая константы цвета, предусмотренные в Visual Basic 2010, с помощью элемента управления ListBox. Мы будем управлять константами Color.FromKnownCoior, поскольку к ним можно обращаться по номеру, например: Me.BackCoior = Color.FromKnownCoior(5) Под пятым номером находится цвет control ("умалчиваемый" цвет формы), который является базовым цветом во многих программах Microsoft, в том числе Windows Explorer, Internet Explorer, VB2010 и пр. Кроме того, здесь цветов больше, чем в константах цветов (структуре) Color (в структуре color нет цвета control). Текст программы представлен в листинге 4.6. Листинг 4.6. Выбор цвета с использованием элемента управления ListBox ’ Программа меняет цвет фона формы.BackCoior, перебирая константы ' цвета, предусмотренные в VB, с помощью элемента управления ListBox Public Class Forml Private Sub Forml_Load(ByVai sender As System.Object, ByVai e As System.EventArgs) Handles MyBase.Load Dim i As Integer For i = 1 To 167 ' Если цвет не "Transparent” If i <> 27 Then ListBoxl.Items.Add(Color.FromKnownCoior(i)) Next ' Сортировать записи в алфавитном порядке ListBoxl.Sorted = True End Sub Private Sub ListBoxl_SelectedIndexChanged(ByVai sender As Object, ByVai e As System.EventArgs) _ Handles ListBoxl.SelectedlndexChanged Me.BackCoior = ListBoxl.Selectedltem End Sub End Class
Редактирование графических данных 103 Как видно, при обработке события загрузки формы Formi Load организован цикл For.. .Next для заполнения списка (коллекции) ListBoxi с помощью ме- тода Add (добавить в коллекцию). Количество констант цвета — 167, причем один из цветов "Transparent", находящийся под номером 27, является "про- зрачным", и для фона формы он не поддерживается, поэтому в цикле он не включается В СПИСОК ListBoxi. Далее, для того чтобы названия цветов в списке ListBoxi были расположены в алфавитном порядке, подана команда (метод) Sorted = True (сортировать список). При обработке события "изменение выбранного индекса" SeiectindexChanged (), т. е. при выборе другого цвета из списка ListBoxi, из- меняется цвет формы: Me.BackColor = ListBoxi.Selectedltem На рис. 4.5 приведен пример работы программы. Как видно, пользователь выбрал цвет Control, который соответствует цвету формы по умолчанию. Рис. 4.5. Закраска формы выбранным цветом Эту программу можно написать более элегантно с использованием цикла For Each при заполнении цветов (листинг 4.7). } Листинг 4.7. Выбор цвета с использованием элемента управления ListBox Public Class Forml Private Sub Forml_Load(ByVai sender As System.Object, ByVai e As System.EventArgs) Handles MyBase.Load Список_цветов() End Sub Private Sub Список_цветов() Dim C As System.Drawing.Color
104 Гпава 4 For Each С In _ System.ComponentModel.TypeDescriptor.GetConverter( GetType(Color)).GetStandardvalues Me.ListBoxl.Items.Add(C.ToKnownColor) Next End Sub Private Sub ListBoxl_SelectedIndexChanged( ByVai sender As System.Object, ByVai e As System.EventArgs) _ Handles ListBoxl.SelectedlndexChanged Me.BackColor = Color.FromKnownColor(ListBoxl.Selectedltem) End Sub End Class Список цветов формируется здесь в процедуре Список_цветов(). Программ- ный код этой новой программы выглядит короче, но понятнее ли? Мы упомянули 167 констант или 146 цветов из структуры color. Вообще го- воря, в VB можно управлять гораздо большим количеством цветов. Система программирования VB работает с так называемой RGB-моделью управления цветом. Согласно этой модели любой цвет может быть представлен как ком- бинация красного (Red), зеленого (Green) и синего (Blue) цветов. Долю каж- дого цвета записывают в один байт: 0 означает отсутствие доли этого цвета, а максимум (255)— максимальное присутствие этого цвета в общей сумме, т. е. в результирующем цвете. Например, функция color.FromArgb(red as Integer, green as Integer, blue as Integer) возвращает Цвет, базируясь на этой модели (или функция rgb с аналогичными параметрами, которой поль- зовались еще в VB6). Информация о цвете элементарной точки (пиксела) мо- жет быть записана в три байта, т. е. 24 бита. При этом говорят, что глубина цвета равна 24 разрядам. Максимальное число, которое можно записать в 24 бита, равно 224- 1 = 16 777 215 или приблизительно 17 миллионов. Это означает, что при глубине цвета, равной 24, можно управлять 17 млн цветов (цветовых оттенков). Предлагаю следующую технологию использования любого цвета при разра- ботке программ. Вначале выбираем цвет, который нам хотелось бы использо- вать (при запуске каких-либо программ или в Интернете на каком-либо сай- те). Существуют программы, которые сообщают цвет пиксела, на котором находится курсор мыши, в нескольких принятых кодировках. Одну такую очень маленькую бесплатную программку Pixie вы можете скачать из Интер- нета по адресу: http://natty.port5.com или http://www.nattyware.com. Про- грамма сообщает вам цвет пиксела в нескольких форматах, в том числе в формате HTML, например, #efebde (этот цвет соответствует цвету control).
Редактирование графических данных 105 Этот цвет подаете на вход функции ColorTranslator.FromHtmlO для перевода этого цвета в цвет, понятный той или иной процедуре (методу) VB. Убедиться в работоспособности этих программ можно, открыв соответст- вующие решения в папках SelectColor_myl и SelectColor_my2. Пример 31. Печать графических примитивов В данном разделе приведен пример вывода на печать (на принтер) изображе- ния эллипса. Понятно, что таким же образом можно распечатывать и другие графические примитивы: прямоугольники, отрезки, дуги и т. д. (см. методы объекта Graphics). Для написания данной программы из панели элементов Toolbox в форму перенесем элемент управления PrintDocument. Текст про- граммы приведен в листинге 4.8. | Листинг 4.8. Печать графических примитивов ; ’ Программа выводит на печать (на принтер) изображение эллипса. Public Class Forml Private Sub Forml_Load(ByVai sender As System.Object, ByVai e As System.EventArgs) Handles MyBase.Load PrintDocumenti.Print() End Sub Private Sub ПЕЧАТЬ(ByVai sender As Object, ByVai e As System.Drawing.Printing.PrintPageEventArgs) _ Handles PrintDocumenti.PrintPage ' Выводится на печать эллипс красного цвета внутри ' ограничивающего прямоугольника с вершиной в точке (200, 250), ' шириной 300 и высотой 200 Dim р As New Pen(Color.Red) e.Graphics.DrawEllipse(p, New Rectangle(200, 250, 300, 200)) ' e.Graphics.DrawEllipse(p, 50, 50, 150, 150) End Sub End Class Как видно, с целью максимального упрощения программы использовано со- бытие загрузки формы Fomi Load ДЛЯ генерации события PrintPage путем вызова метода PrintDocumenti.Print. В обработчике события PrintPage вызы- ваем метод DrawEllipse для построения эллипса без заливки. В комментарии приведен вариант построения эллипса другим способом.
106 Гпава 4 Убедиться в работоспособности программы можно, открыв решение PrintGra.sIn в папке PrintGra. Пример 32. Печать ВМР-файла В данном разделе программа выводит на печать графический файл формата BMP. На логическом диске С: заранее подготовим графический файл форма- та BMP и назовем его C:\pic.bmp. Этот файл будет распечатываться на прин- тере программой, которую мы напишем. Для этого запустим VB2010, выбе- рем шаблон Windows Forms Application. Затем добавим в форму из панели элементов Toolbox командную кнопку Button и объект PrintDocument. Про- граммный код представлен в листинге 4.9. Public Class Forml ’ Эта программа выводит на печать файл с расширением bmp I Private Sub Forml_Load(ByVai sender As System.Object, ByVai e As System.EventArgs) Handles MyBase.Load Me.Text = "Печать файла C:\pic.bmp" Buttonl.Text = "Печать" End Sub ' Пользователь щелкнул на кнопке Private Sub КНОПКА(ByVai sender As System.Object, ByVai e As System.EventArgs) Handles Buttonl.Click Try PrintDocument1.Print() Catch ex As Exception MessageBox.Show("Ошибка печати на принтере", ex.ToString()) End Try End Sub ’ Это событие возникает, когда вызывают метод Print() Private Sub ПРИНТ(ByVai sender As Object, ByVai e As System.Drawing.Printing.PrintPageEventArgs) _ Handles PrintDocumentl.PrintPage ' Рисование содержимого ВМР-файла e.Graphics.Drawlmage(Image.FromFile("C:\pic.bmp"), e.Graphics.VisibleClipBounds)
Редактирование графических данных 107 ' Следует ли распечатывать следующую страницу? e.HasMorePages = False End Sub End Class Как видно, при нажатии пользователем кнопки вызывается метод Print Document 1. Print. Этот метод создает событие PrintPage, которое обраба- тывается в обработчике PrintDocumentl. PrintPage. Для вывода на принтер вызывается метод рисования содержимого BMP-файла Drawimage. Убедиться в работоспособности программы можно, открыв решение printBMP.sln в папке printJBMP.

ГЛАВА 5 Управление буфером обмена с данными в текстовом и графическом форматах Пример 33. Буфер обмена с данными в текстовом формате Напишем программу для управления буфером обмена с данными в текстовом формате. Эта программа будет позволять записывать какой-либо текст в бу- фер обмена (БО), а затем извлекать этот текст из БО. Для этой цели в форме создадим два текстовых поля, а также две командные кнопки под этими по- лями. Одну кнопку назовем Записать в БО, а другую — Извлечь из БО. Чтобы записать какой-либо текст в БО, нужно записать его в верхнее поле, выделить (с помощью клавиш управления курсором при нажатой клавише <Shift>), а затем нажать кнопку Записать в БО. Нажимая кнопку Записать в БО, мы как бы моделируем комбинацию клавиш <Ctrl>+<C>. Далее записанный в БО текст можно читать в каком-либо текстовом редакто- ре или вывести в нижнее текстовое поле прямо в нашей форме. Для этого на- жимаем кнопку Извлечь из БО (см. рис. 5.1). Текст данной программы при- веден в листинге 5.1. ; Листинг 5Л. Запись текстовых данных' » буфер обмена й их чтение : • • Эта программа имеет возможность записи какого-либо текста • в буфер обмена, а затем извлечения этого текста из буфера обмена Public Class Forml Private Sub Forml_Load (ByVai sender As System.Object, ByVai e As System.EventArgs) Handles MyBase.Load
110 Гпаеа 5 Me.Text = ’’Введите текст в верхнее поле” TextBoxl.Clear() : TextBox2.Clear() Buttonl.Text = "Записать в ВО" Button2.Text = "Извлечь из Б0" End Sub Private Sub Записать_в_Б0(ByVai sender As Object, ByVai e As System.EventArgs) Handles Buttonl.Click ' Записать выделенный в верхнем поле текст в ВО If TextBoxl.SelectedText о ’”’ Then Clipboard.SetDataObject(TextBoxl.SelectedText) TextBox2.Text = Nothing Else TextBox2.Text = "В верхнем поле текст не выделен" End If End Sub ’ Записать_в_Б0 Private Sub Извлечь_из_Б0(ByVai sender As Object, ByVai e As System.EventArgs) Handles Button2.Click ’ Объявление объекта-получателя из BO Dim Получатель As IDataObject = Clipboard.GetDataObject() ' Если данные в БО представлены в текстовом формате... If Получатель.GetDataPresent(DataFormats.Text) = True Then ’ то записать их в Text тоже в текстовом формате TextBox2.Text = СТуре(Получатель.GetData(DataFormats.Text), String) Else TextBox2.Text = "Запишите что-либо в буфер обмена" End If End Sub ' Извлечь из БО End Class В программном коде имеем обработку трех событий. Первое событие — это загрузка формы Formi Load(). Здесь задаем надпись в заголовке формы: "Введите текст в верхнее поле". Далее очищаем оба текстовых поля: TextBoxl и TextBox2. Назначаем надписи на кнопках Buttonl и Button2. Обрабатываем второе событие— щелчок на верхней кнопке. При этом если текст в верхнем поле выделен, то записываем его (SelectedText) в буфер об- мена (clipboard) командой (методом) SetDataObject, иначе (Else) сообщаем в нижнем поле TextBox2 о том, что в верхнем поле текст не выделен.
Управление буфером обмена с данными в текстовом и графическом форматах 111 Третье событие— щелчок на нижней кнопке. Напоминаю, что, нажимая кнопку Извлечь из БО, в нижнем поле пользователь нашей программы дол- жен увидеть содержимое буфера обмена. Для этого объявляем объектную переменную получатель. Это объект-получатель из буфера обмена. Эта пере- менная сознательно названа по-русски для большей выразительности. Далее следует проверка: в текстовом ли формате (DataFormat.Text) данные, пред- ставленные в буфере обмена. Если формат текстовый, то в текстовое поле TextBox2 записываем содержимое буфера обмена, используя функцию стуре. Эта функция конвертирует строковую часть объекта в строковую перемен- ную. Пример работы программы показан на рис. 5.1. Рис. 5.1. Запись текстовых данных в буфер обмена и их чтение Убедиться в работоспособности программы можно, открыв решение Clipboard.sin в папке Clipboard. Пример 34. Элемент управления PictureBox. Буфер обмена с растровыми данными Обсудим программу, которая оперирует буфером обмена, когда тот содержит изображение. Здесь мы будем использовать элемент управления PictureBox (графическое окно), который способен отображать в своем поле растровые файлы различных форматов, в том числе BMP, JPEG, PNG, GIF и др. Воз- можность отображения в PictureBox GIF-файлов позволяет просматривать анимацию, т. е. движущееся изображение, в экранной форме вашей програм- мы. Пример отображения такой GIF-анимации вы можете посмотреть, открыв решение PictureBox_myl .sin в папке PictureBox myl. Однако элемент управ- ления PictureBox не способен отображать Flash-файлы в формате SWF, ко- торые сочетают в себе векторную графику, растровую графику и воспроизве- дение звука. Замечу, что файлы SWF воспроизводят элемент управления Microsoft Web Browser, который мы рассмотрим в главе 7.
112 Гпава 5 Рассматриваемая программа выводит в поле элемента управления PictureBox изображение из растрового файла (например, PNG). При этом изображение записывается в БО. Пользователь может убедиться в этом, например, запус- тив Paint— стандартный графический редактор ОС Windows. Далее пользо- ватель может поместить в БО любое изображение с помощью какого-нибудь графического редактора, например, того же Paint, ACDSee или др. Затем, на- жав кнопку Извлечь из БО нашей программы, получить в форме содержи- мое БО. Для создания данной программы в форму из панели Toolbox перетащим эле- менты управления PictureBox (графическое окно) и кнопку Button. Текст программы приведен в листинге 5.2. Листинг 5 2 Обмен данных через буфер обмена ' Программа оперирует буфером обмена, когда тот содержит изображение Public Class Forml Private Sub Forml_Load(ByVai sender As Object, ByVai e As System.EventArgs) Handles MyBase.Load Me.Text = ’’Содержимое BO:” : Buttonl.Text = ’’Извлечь из ВО" ’ Записать в PictureBox изображение из файла PictureBoxl. Image = Image.FromFile( IO.Directory.GetCurrentDirectory & ’’\poryv.png’’) ’ Записать в БО изображение из графического окна формы Clipboard.SetDataObject(PictureBoxl.Image) End Sub Private Sub Bl_Click(ByVai sender As System.Object, ByVai e As System.EventArgs) Handles Buttonl.Click ’ Объявление объекта-получателя из буфера обмена Dim Получатель As IDataObject = Clipboard.GetDataObject() Dim bmap As Bitmap ’ Если данные в БО представлены в формате Bitmap... If Получатель.GetDataPresent(GetType(System.Drawing.Bitmap)) Then ’ то записать их из БО в bmap в формате Bitmap bmap = СТуре(Получатель.GetData(GetType(Drawing.Bitmap)), Bitmap) PictureBoxl.Image = bmap End If End Sub End Class
Управление буфером обмена с данными в текстовом и графическом форматах 113 Как видно из текста программы, при загрузке формы Formi Load в графиче- ское окно формы PictureBoxl записываем какой-нибудь файл, например, poryv.png. Этот файл необходимо поместить в ту же папку, где расположен ЕХЕ-файл данной программы, т. е. в папку Debug (при отладке приложения). Функция Directory.GetCurrentDirectory возвращает ПОЛНЫЙ путь текущей папки. Данная функция относится к пространству имен system, io. Поэтому, чтобы эта функция вызывалась, следует импортировать (imports) пространст- во имен System, ю. Это необходимо написать перед объявлением класса Public class Forml (см. листинг 5.2). Далее при загрузке формы по команде Clipboard.SetDataObject(PictureBoxl.Image) происходит запись содержимого графического окна в буфер обмена. Теперь пользователь может проверить содержимое БО с помощью какого- либо графического редактора, например, Paint. Далее пользователь может записать что-либо в буфер обмена, опять же используя какой-нибудь графи- ческий редактор. Нажатие кнопки Извлечь из БО нашей программы в форме приведет к появлению изображения, находящегося в буфере обмена. Фраг- мент работы программы представлен на рис. 5.2. Рис. 5.2. Извлечение изображения из буфера обмена В программном коде при обработке события ’’щелчок на кнопке" Извлечь из БО объявляем объектную переменную получатель. Это объект, с помощью которого будем получать изображение, записанное в буфер обмена. Эта пе- ременная сознательно названа по-русски для большей выразительности. Да- лее следует проверка: записаны ли данные, представленные в БО, в формате растровой графики Bitmap. Если да, то записать данные из БО в переменную bmap В формате Bitmap С ПОМОЩЬЮ объвКТНОЙ переменной Получатель, исполь- зуя функцию стуре(объект, Bitmap). Эта функция конвертирует объект в пе- ременную типа Bitmap. Далее, чтобы изображение появилось в элементе управления PictureBoxl в форме, присваиваем свойству image значение пере- менной bmap.
114 Гпава 5 Убедиться в работоспособности программы можно, открыв решение Clip_Picture.sln в папке ClipPicture. Пример 35. Имитация нажатия комбинации клавиш <Alt>+<PrintScreen> Как известно, при нажатии клавиши <PrintScreen> происходит копирование изображения экрана в буфер обмена, т. е. получаем так называемый screen shot— моментальный снимок экрана (другое название— screen capture). После извлечения из БО графической копии экрана в любом графическом редакторе (например, Paint), эту графическую копию можно редактировать. При нажатии комбинации клавиш <Alt>+<PrintScreen> в буфер обмена копи- руется не весь экран, а только активное окно. В VB6 не было возможности имитировать нажатие клавиш какой-либо функцией, поэтому приходилось использовать функцию Microsoft API. Современный Visual Basic в простран- стве имен System. Windows. Forms имеет класс SendKeys, который предоставляет методы для отправки приложению сообщений о нажатиях клавиш. В этом примере мы рассмотрим обе эти возможности. Данная программа сознательно максимально упрощена, чтобы более вырази- тельно показать ее суть. Здесь в форме имеем только две кнопки. При обра- ботке события ’’щелчок на первой кнопке” будем имитировать нажатие ком- бинации клавиш <Alt>+<PrintScreen> с помощью функции Microsoft API, а при обработке события ’’щелчок на второй кнопке” будем имитировать нажа- тие этих же клавиш методом Send класса SendKeys. Результат нажатия любой из кнопок будет совершенно одинаков. При этом форму можно как угодно менять— растягивать по ширине и по высоте, но после нажатия любой из кнопок в форме изображение формы запишется в буфер обмена. Следует убедиться в этом: запустить Paint и извлечь графическую копию формы из буфера обмена. Текст программы представлен в листинге 5.3. I Листинг 5.3. Имитация нажатия комбинации клавиш <Alt>+<PrintScreen> ’ Программная имитация нажатия клавиш <Alt>+<PrintScreen> с помощью ’ функции Microsoft Windows API, а также методом Send класса SendKeys Public Class Forml Private Declare Sub keybd_event Lib "user32.dll" ( ByVai bVk As Byte, ByVai bScan As Byte, ByVai dwFlags As Integer, ByVai dwExtralnfo As Integer) Private Sub Buttonl_Click(ByVai sender As System.Object, ByVai e As System.EventArgs) Handles Buttoni.Click
Управление буфером обмена с данными в текстовом и графическом форматах 115 keybd_event(44, 1, 0, О) End Sub Private Sub Button2_Click(ByVai sender As System.Object, ByVai e As System.EventArgs) Handles Button2.Click ' Посылает сообщение активному приложению о нажатии ’ клавиш <Alt>+<PrintScreen> SendKeys.Send("{PRTSC}”) End Sub End Class В этой программе при обработке события ’’щелчок на первой кнопке” мы воспользовались функцией Microsoft Windows API (Application Programming Interface, интерфейс программирования приложений). Функция keybd_event() позволяет имитировать (эмулировать) йажатие пользователем клавиш. Функция находится в динамической библиотеке user32.dll (см. программный код). Эту библиотеку вы можете увидеть в системном каталоге C:\Windows\System32. В DLL-файлах (dynamic link library) находятся ском- пилированные классы. Как видно, сначала функцию API следует объявить (private Declare) с указа- нием типов аргументов, подаваемых на вход функции keybd event (). Пара- метр "user32" или "user32.dll" определяет имя используемой библиотеки. В скобках записан список аргументов функции keybd event (). Мы можем за- давать любые имена аргументов, но их типы должны соответствовать форма- ту функции API. При обработке события "щелчок на кнопке” Buttoni ciick о мы программи- руем вызов API-функции keybd event () по формату, заданному в объявлении функции. Из четырех аргументов функции keybd event () важным является первый, он задает код клавиши <PrintScreen>. Можно задать шестнадцате- ричный код, равный &H2CS, однако мы задали десятичный код клавиши <PrintScreen>, равный 44. Также представляет интерес второй аргумент функции keybd event (). Второй аргумент, равный единице, эмулирует одновременное нажатие клавиши <Alt> с клавишей <PrintScreen>. Таким образом, вызывая функцию keybd event(44, 1, о, 0), мы эмулируем нажатие комбинации клавиш <Alt>+<PrintScreen>, а при keybd event(4 4, о, о, 0)— нажатие только <PrintScreen>. С помощью API-функции keybd event () можно эмулировать нажатие любых клавиш, подавая на вход функции коды соответствующих клавиш. Обрабатывая событие ’’щелчок на второй кнопке", метод Send класса SendKeys посылает сообщение активному приложению о нажатии комбинации клавиш
116 Гпава 5 <Alt>+<PrintScreen>. Таким образом, результат нажатия обеих клавиш оди- наков. Убедиться в работоспособности программы можно, открыв решение ClipPrint.sln в папке ClipPrint. Пример 36. Запись содержимого буфера обмена в ВМР-файл Напишем программу, которая читает буфер обмена, и если данные в нем представлены в формате растровой графики, то записывает эти данные в ВМР-файл. Текст этой программы приведен в листинге 5.4. Листинг 5.4. Запись содержимого буфера обмена в ВМР-файл • Программа читает буфер обмена, и если данные в нем представлены ’ в формате растровой графики, то записывает их в ВМР-файл Public Class Forml Private Sub Forml_Load(ByVai sender As System.Object, ByVai e As System.EventArgs) Handles MyBase.Load Me.Text = "Копия ВО записана в Clip.BMP" ’ Объявление объекта-получателя из буфера обмена Dim Получатель As IDataObject = Clipboard.GetDataObject() Dim bmap As Bitmap ’ Если данные в буфере обмена представлены в формате Bitmap... If Получатель.GetDataPresent( GetType(System.Drawing.Bitmap)) Then ’ то записать их из ВО в bmap в формате Bitmap bmap = СТуре(Получатель.GetData(GetType(System.Drawing.Bitmap)), Bitmap) ' Сохранить изображение bmap в файле Clip.bmp bmap.Save("C:\Clip.BMP") MessageBox.Show("Изображение из ВО записано в файл C:\Clip.BMP") Else MessageBox.Show("В ВО нет данных в формате изображений") Application. Exit() End If End Sub End Class
Управление буфером обмена с данными в текстовом и графическом форматах 117 В программном коде вся работа происходит при загрузке формы Formi_Load. Объявляем объектную переменную получатель. Это объект-получатель из бу- фера обмена. Далее следует проверка: записаны ли данные, представленные в буфере обмена в формате растровой графики Bitmap. Если да, то записать данные из буфера обмена в bmap в формате Bitmap с помощью объектной пе- ременной Получатель, ИСПОЛЬЗуя функцию СТуре (объект, Bitmap), которая конвертирует объект в переменную типа Bitmap. Сохранить изображение bmap на винчестер очень просто, воспользовавшись методом save о объекта bmap. Чтобы не запутать читателя и упростить программу, я не стал организовывать запись файла в диалоге. При необходимости читатель сделает это самостоя- тельно, воспользовавшись элементом управления saveFiieDiaiog. Фрагмент работы данной программы представлен на рис. 5.3. Рис. 5.3. Запись изображения из буфера обмена в файл Убедиться в работоспособности программы можно, открыв решение Clip_Save.sin в папке Clip_Save. Пример 37. Использование таймера Timer Автор несколько раз встречал задачу записи моментальных снимков экрана (screen shot) в растровые файлы с некоторым промежутком времени, напри- мер, пять секунд. Например, такую задачу я видел, выставленную на тендер на сайте оффшорного программирования (www.rentacoder.com). За ее реше- ние указывалось вознаграждение 100 долларов США. Конечно, сразу появля- ется очень много желающих эту задачу решить, но попробуйте выиграть тендер. Следующая задача является частью упомянутой задачи, ее сформулируем таким образом: после запуска программы должна отображаться форма, а через две секунды— выводиться сообщение: "Время истекло". На этом программа должна заканчивать свою работу. На этой задаче мы освоим тех- нологию работы с таймером. Timer— это невидимый во время работы про- граммы элемент управления, предназначенный для периодического генери- рования СОбыТИЯ Tick. Для реализации программы в форму из панели элементов Toolbox перетащим элемент управления Timer. Программный код приведен в листинге 5.5.
118 Гпава 5 : Листинг 5.5. Использование таймера ’ Демонстрация использования таймера Timer. После запуска программы ’ показывается форма, а через две секунды — сообщение "Время истекло", ’ и на этом программа заканчивает свою работу Public Class Forml Private Sub Forml_Load(ByVai sender As System.Object, ByVai e As System.EventArgs) Handles MyBase.Load Timerl.Enabled = True ’ — время пошло Timerl.Interval = 2000 ’ — 2 секунды End Sub Private Sub Timerl_Tick(ByVai sender As System.Object, ByVai e As System.EventArgs) _ Handles Timerl.Tick MessageBox.Show("Время истекло") Application.Exit () End Sub End Class В ЭТОЙ программе при загрузке формы Formi Load о свойству таймера Enabled задаем значение True, что означает ’’начинать отчет времени”. Здесь мы зада- ем интервал времени interval, равный 2000 миллисекунд (2 секунды). Это интервал времени для таймера. Каждые 2 секунды будет происходить собы- тие Timeri Ticko. В момент наступления такого события мы запрограммиро- вали вывод диалогового окна MessageBox с текстом ’’Время истекло”. Этот текст будет выводиться каждые 2 секунды до тех пор, пока пользователь про- граммы не нажмет кнопку ОК в диалоговом окне. После этого выполнится оператор Application.Exit о, т. е. выход из программы. На рис. 5.4 показан пример работы программы. Рис. 5.4. Вывод сообщения
Управление буфером обмена с данными в текстовом и графическом форматах 119 Убедиться в работоспособности программы можно, открыв решение Timer.sln в папке Timer. Пример 38. Запись в файлы текущих состояний экрана с интервалом 5 секунд Как уже говорилось в предыдущем разделе, работа с таймером — довольно распространенная задача. Напишем данную программу в следующей поста- новке. После запуска программы через каждые 5 секунд снимается текущее состояние экрана и записывается в файлы Picl.BMP,..., Pic5.BMP. Для решения данной задачи мы имеем уже весь инструментарий, он был рас- смотрен в предыдущих задачах. А именно, задание интервала времени 5 се- кунд с помощью элемента управления Timer, эмуляция нажатия клавиш <Alt>+<PrintScreen>, <PrintScreen> для записи текущего состояния экрана в буфер обмена и, наконец, чтение БО и запись изображения в файл BMP. Для решения задачи перетаскиваем в форму элементы управления Timer и ProgressBar. Текст программы приведен в листинге 5.6. ? Листинг 5.6. Запись в файлы текущих состояний экрана с интернзпом 5 секунд ’ Программа после запуска каждые 5 секунд делает снимок текущего ’ состояния экрана и записывает эти состояния в файлы Picl.BMP, Pic2.BMP ’ ит. д. Количество таких записей в файл — пять Public Class Forml Private Declare Sub keybd_event Lib "user32.dll" ( ByVai bVk As Byte, ByVai bScan As Byte, ByVai dwFlags As Integer, ByVai dwExtralnfo As Integer) Dim i As Byte = 0 ' Целое 8-битовое Private Sub Forml_Load(ByVai sender As System.Object, ByVai e As System.EventArgs) _ Handles MyBase.Load Me.Text = "Запись каждые 5 секунд в файл" Timerl.Enabled = True ’ — время пошло Timerl.Interval = 5000 ’ — 5 секунд ProgressBarl.Visible = True ProgressBarl.Minimum = 1 ProgressBarl.Maximum = 5
120 Гпава 5 ProgressBarl.Value = 1 ProgressBarl.Step = 1 End Sub Private Sub Timerl_Tick(ByVai sender As System.Object, ByVai e As System.EventArgs) Handles Timerl.Tick ' Эмулируем нажатие клавиш <Alt>+<PrintScreen> keybd_event(44, 1, 0, 0) ' или ’ SendKeys.Send(”{PRTSC}”) ’ Объявление объекта-получателя из буфера обмена Dim Получатель As IDataObject = Clipboard.GetDataObject() Dim bmap As Bitmap ’ Если данные в буфере обмена представлены в формате Bitmap... If Получатель.GetDataPresent(GetType(Drawing.Bitmap)) Then ’ то записать их из буфера обмена в bmap в формате Bitmap: bmap = СТуре(Получатель.GetData(GetType(Drawing.Bitmap)), Bitmap) ' Сохранить изображение bmap в файле i = i + 1 : Dim filename As String = "C:\Pic" filename = filename & i & ".BMP” bmap.Save(f ilename) ProgressBarl.PerformStep() End If If i >= 5 Then Application.Exit() End Sub End Class Как видно, структура программы включает в себя объявление обращения к API-функции keybd event (), обработку события загрузки формы Forml_Load() И обработку события Timerl.Tick. В начале программы задаем переменную i, которая считает, сколько раз про- грамма сделает запись в буфер обмена, а из буфера обмена — в файл. Эта пе- ременная объявлена нами типа Byte, т. е. как целая однобайтовая без знака; максимальное значение, которое можно записать в такую переменную — 255; в нашей задаче в этой переменной происходит счет до пяти.
Управление буфером обмена с данными в текстовом и графическом форматах 121 При загрузке формы дана команда таймеру начать отсчет времени Timerl.Enabled = True и задан интервал времени interval, равный 5000 мил- лисекунд, т. е. 5 секунд. Через каждые 5 с наступает событие Timeri Ticko, т. е. управление переходит этой процедуре. При обработке события Timerl.Tick вызываем функцию keybd event(), тем самым эмулируем нажа- тие комбинации клавиш <Alt>+<PrintScreen>, и таким образом происходит запись в буфер обмена текущего состояния активного окна. Далее, используя объект получатель, записываем данные из буфера обмена в переменную bmap. Затем наращиваем значение переменной i на единицу и формируем новое название растрового файла filename. Имя этого файла складывается из "C:\Pic", номера текущего состояния экрана i и расширения файла bmp. Записываем растровый файл на диск С: с новым именем — bmap. save (Filename). Далее, если номер текущего состояния экрана i больше или равен 5, то выход (exit) из программы. Несколько слов об элементе управления ProgressBar (индикатор хода вы- полнения программы), который обеспечивает визуальное отслеживание рабо- ты программы и как бы информирует пользователя, что операция продолжает выполняться и компьютер не завис. При обработке загрузки формы мы зада- ли начальные значения для этого элемента управления: сделать шкалу инди- катора видимой (visible = True), минимальное (Minimum) и максимальное (Maximum) значения, которые может иметь индикатор, в условных единицах — в нашем случае это количество записей в файлы BMP. После каждой записи в файл метод Performstep увеличивает значение индикатора на величину step, заданную нами равной I, и обновляет отображение индикатора ProgressBar. На рис. 5.5 приведен фрагмент работы программы. Рис. 5.5. Строка прогресса при записи файлов Убедиться в работоспособности программы можно, открыв решение Clip Save Timer.sln в папке Clip Save Timer.

ГЛАВА 6 Ввод и вывод табличных данных. Решение системы уравнений Пример 39. Формирование таблицы. Функция String.Format При создании инженерных, экономических и других приложений часто зада- ча сводится к вводу данных, расчету (обработке введенных данных), а за- тем — выводу результатов вычислений в таблицу. В данном разделе мы об- судим такую типичную задачу: как оптимально сформировать таблицу, а за- тем вывести ее на экран с возможностью печати на принтере. Чтобы выразительно показать именно процесс формирования таблицы, абст- рагируемся от ввода данных и расчетов и сосредоточимся только на сути. Например, пусть мы имеем информацию о телефонах наших знакомых, и нам хотелось бы представить эту информацию в виде наглядной таблицы. Пред- ставим, что результаты обработки записаны в два массива: массив имен зна- комых imena () и массив телефонов те1 (). Наша программа формирует табли- цу из этих двух массивов в текстовом поле TextBox. Кроме того, в программе участвует элемент управления Menustrip для организации выпадающего ме- ню, с помощью которого пользователь выводит сформированную таблицу в Блокнот (notepad.exe) с целью последующей корректировки (редактирования) и вывода на печать. Таким образом, новый проект будет содержать форму, текстовое поле TextBox СО СВОЙСТВОМ Multiline = True И меню MenuStrip. Текст программы пред- ставлен в листинге 6.1.
124 Глава Листинг 6Л. Формирование таблицы ’ Программа формирует таблицу из двух строковых массивов в текстовом ’ поле, используя функцию String.Format. Кроме того, в программе ’ участвует элемент управления Menustrip для организации выпадающего ’ меню, с помощью которого пользователь выводит сформированную таблицу ’ в Блокнот с целью последующего редактирования и вывода на печать Public Class Forml Private Sub Forml_Load(ByVai sender As System.Object, ByVai e As System.EventArgs) Handles MyBase.Load Me.Text = "Формирование таблицы" Dim ImenaO As String = {"Андрей — раб", "Света-Х", "ЖЭК", "Справка по тел", "Александр Степанович", "Мама — дом", "Карапузова Таня", "Погода сегодня", "Театр Браво"} Dim Tel () As String = {"274-88-17","+38(067)7030356", "22-345-72", "009", "223-67-67 доп 32-67", "570-38-76", "201-72-23-прямой моб", "001", "216-40-22"} TextBoxi.Multiline = True TextBoxi.ScrollBars = ScrollBars.Vertical TextBoxi.Font = New System.Drawing.Font("Courier New", 9.0!) TextBoxi.Text = "ТАБЛИЦА ТЕЛЕФОНОВ" & vbCrLf & vbCrLf For i As Short = 0 To 8 TextBoxi.Text() &= String.Format( "{0,-21} {1,-21}", Imena(i), Tel(i)) & vbCrLf Next TextBoxi.Text &= vbCrLf & "ПРИМЕЧАНИЕ:" & vbCrLf & "для корректного отображения таблицы" & vbCrLf & "в Блокноте укажите шрифт Courier New" ’ Запись таблицы в текстовый файл C:\Table.txt. ’ Создание экземпляра Streamwriter для записи в файл Dim Писатель As New IO.Streamwriter("С:\Table.txt", False, System. Text.Encoding.GetEncoding(1251)) ’ — здесь заказ кодовой страницы Winl251 для русских букв Писатель.Write(TextBoxi.Text) Писатель.Close() End Sub
Ввод и вывод табличных данных. Решение системы уравнений 125 Private Sub ПОКАЗАТЬ(ByVai sender As System.Object, ByVai e As System.EventArgs) Handles _ ПоказатьТаблицуВБлокнотеТоо!St ripMenuItem.Click Try Diagnostics.Process.Start("Notepad", "C:\Table.txt") Catch Exc As Exception ’ Отчет об ошибках MessageBox.Show(Exc.Message, "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Exclamation) End Try End Sub Private Sub ВЫХОД(ByVai sender As System.Object, ByVai e As System.EventArgs) _ Handles BbixoflToolStripMenuItem. Click ’ Выход из программы: Me.Close() End Sub End Class Чтобы в текстовом поле TextBoxl таблица отображалась корректно, мы зака- зали шрифт Courier New. Особенность этого шрифта заключается в том, что каждый символ (буква, точка, запятая и др.) этого шрифта имеет одинаковую ширину, как это было на печатающей машинке. Поэтому, пользуясь шрифтом Courier New, удобно строить таблицы, таким же замечательным свойством обладает, например, шрифт Consolas. Далее в цикле For.. .Next мы использовали оператор &=, он означает: сцепить текущее содержание текстовой переменной TextBoxl.Text с текстом, пред- ставленным справа. Функция string.Format возвращает строку, сформиро- ванную по формату. Формат заключен в кавычки. Ноль в первых фигурных скобках означает: вставить вместо нуля переменную imena(i), а единица во вторых фигурных скобках— вставить вместо единицы строку Tei(i). Число 21 означает, что длина строки в любом случае будет состоять из 21 символа (недостающими символами будут пробелы), причем знак ’’минус” заставляет прижимать текст влево. Константа vbCrLf означает: начать текст с новой строки. Внешний вид таблицы в текстовом поле формы показан на рис. 6.1. После формирования всех строк TextBoxl.Text записываем их в текстовый файл C:\Table.txt через streamwriter с кодовой таблицей Windows 1251. Под- робное обсуждение этого фрагмента программы читатель может посмотреть в примере 22 (см. главу 3). При выборе пользователем пункта меню Показать таблицу в Блокноте сис- тема создает событие, которое обрабатывается в соответствующей процедуре
126 Гпава 6 показать. Здесь вызываем программу операционной системы Блокнот (notepad.exe) для открытия файла C:\Table.txt (см. рис. 6.2). Рис. 6.1. Таблица из двух массивов в текстовом поле Рис. 6.2. Просмотр созданной таблицы в Блокноте Убедиться в работоспособности программы можно, открыв решение Tabl TXT.sln в папке ТаЫ_ТХТ. Пример 40. Форматирование Doub/е-переменных в виде таблицы. Вывод таблицы на печать. Поток StringReader Данная программа решает похожую задачу, однако в результате вычислений имеем не строковые переменные string, а два массива переменных с двойной
Ввод и вывод табличных данных. Решение системы уравнений 127 точностью Double. Например, пусть в результате расчетов получены коорди- наты точек на местности Хи У. Эти координаты необходимо оформить в виде таблицы. Таблицу следует назвать ’’Каталог координат”. Координаты в таб- лице должны быть округлены до 2-х знаков после запятой. Сформированную таблицу следует показать пользователю в текстовом поле TextBox. Далее надо организовать возможность распечатать таблицу на принтере. Заметьте, что в этой задаче мы решаем проблемы без использования Блокнота. Для решения этой задачи, также как и в предыдущем разделе, в форме с по- мощью панели элементов управления Toolbox создадим текстовое поле TextBox, выберем элементы управления Menustip и PrintDocument. На вкладке Design подготовим пункты меню Печать и Выход так, как показано на рис. 6.3. Непосредственно текст программы представлен в листинге 6.2. ' Листинг 6.2. Формирование таблицы и вывод ее на печать ’ Программа формирует таблицу на основании двух массивов переменных ’ с двойной точностью. Данную таблицу программа демонстрирует ’ пользователю в текстовом поле TextBox. Есть возможность распечатать ’ таблицу на принтере Public Class Forml Dim Читатель As IO.StringReader Private Sub Forml_Load(ByVai sender As System.Object, ByVai e As System.EventArgs) Handles MyBase.Load Me.Text = "Формирование таблицы" Dim X() As Double = {5342736.17653, 2345.3333, 234683.853749, 2438454.825368, 3425.72564, 5243.25, 537407.6236, 6354328.9876, 5342.243} Dim Y() As Double = {27488.17, 3806703.356, 22345.72, 54285.34, 2236767.3267, 57038.76, 201722.3, 26434.001, 2164.022} TextBoxl.Multiline = True TextBoxl.ScrollBars = ScrollBars.Vertical TextBoxl.Font = New System.Drawing.Font("Courier New", 9.0!) TextBoxl.Text = "КАТАЛОГ КООРДИНАТ" & vbCrLf TextBoxl.Text &= "---------------------------------’’ & vbCrLf TextBoxl.Text &= "|Пункт| X | Y I" & vbCrLf TextBoxl.Text &= "---------------------------------" & vbCrLf
128 Гпава 6 For i As Integer = 0 To 8 TextBoxl.Text &= String.Format( "I {0,3:D} | {l,10:F2} | {2,10:F2} |", i, X(i), Y(i)) & vbCrLf Next TextBoxl .Text &= "---------------------------------’’ & vbCrLf End Sub Private Sub ПЕЧАТЬ(ByVai sender As System.Object, ByVai e As System.EventArgs) _ Handles ПечатьToolStripMenuItem. Click ’ Пункт меню "Печать" Try ’ Создание потока Читатель для чтения из строки: Читатель = New 10.StringReader(TextBoxl.Text) Try PrintDocument1.Print() Finally Читатель.Close() End Try Catch ex As Exception MessageBox.Show(ex.Message) End Try End Sub Private Sub PrintDocumentl_PrintPage( ByVai sender As System.Object, ByVai e As System.Drawing.Printing.PrintPageEventArgs) _ Handles PrintDocument1.PrintPage Dim linesPerPage As Single = 0 Dim yPos As Single = 0 Dim count As Integer = 0 Dim leftMargin As Single = e.MarginBounds.Left Dim topMargin As Single = e.MarginBounds.Top Dim line As String = Nothing Dim printFont = New Font("Courier New", 12.0!) ’ Вычисляем количество строк на одной странице linesPerPage = e.MarginBounds.Height / printFont.GetHeight(e.Graphics)
Ввод и вывод табличных данных. Решение системы уравнений 129 ' Печатаем каждую строку файла While count < linesPerPage line = Читатель.ReadLine() If line Is Nothing Then Exit While End If yPos = topMargin + count * printFont.GetHeight(e.Graphics) ’ Печать строки e.Graphics.Drawstring(line, printFont, Brushes.Black, leftMargin, yPos, New StringFormat) count += 1 End While ’ Печать следующей страницы, если есть еще строки файла If Not (line Is Nothing) Then e.HasMorePages = True Else e.HasMorePages = False End If End Sub Private Sub ВЫХОД(ByVai sender As System.Object, ByVai e As System.EventArgs) _ Handles BbixoflToolStripMenuI tern. Click ’ Выход из программы Me.Close() End Sub End Class Рис. 6.3. Вывод таблицы в текстовое поле 5 Зак 145
130 Гпава 6 Как видно, формирование таблицы также происходит в цикле For...Next с помощью функции string.Format. В фигурных скобках числа 0, 1 и 2 означа- ют, что вместо фигурных скобок следует вставлять переменные i, х(1), y (i). Выражение "3:D" означает, что переменную i следует размещать в трех сим- волах по формату целых переменных "D". Выражение "10:F2" означает, что переменную x(i) следует размещать в десяти символах по фиксированному формату с двумя знаками после запятой. При обработке события "щелчок на пункте меню" Печать (см. рис. 6.3) в блоках Try.. .Finely.. .Catch создаем поток читатель, однако не для чтения из файла, как это было в примере 25 (см. главу 3), а для чтения из текстовой переменной TextBoxl.Text. В этом случае мы обращаемся с потоком читатель так же, как при операциях с файлами, но совершенно не обращаясь к внеш- ней памяти (диску). Поэтому организация многостраничной печати остается абсолютно такой же, как в примере 25. Как видно из приведенной программы, для того чтобы просмотреть, откор- ректировать и распечатать на принтере таблицу (инженерных или экономиче- ских вычислений), совершенно необязательно записывать эту таблицу в тек- стовый файл и читать его Блокнотом. Убедиться в работоспособности программы можно, открыв решение Tabl TXT print.sln в папке Tabl_TXT_print. Пример 41. Вывод таблицы в Internet Explorer Приведем несколько необычный подход к выводу таблицы для целей ее про- смотра и распечатывания на принтере. Запишем таблицу в текстовый файл в формате HTML, затем прочитаем ее с помощью обозревателя (браузера) Web-страниц Internet Explorer. HTML (HyperText Markup Language, язык ги- пертекстовой разметки)— специальные инструкции браузеру, с помощью которых создаются Web-страницы. То есть Web-страницы — это документы в формате HTML, содержащие текст и специальные теги (дескрипторы) HTML. По большому счету теги HTML необходимы для форматирования текста (т. е. придания ему нужного вида), который ’’понимает” браузер. До- кументы HTML хранятся в виде файлов с расширением htm или html. Теги HTML сообщают браузеру информацию о структуре и особенностях форма- тирования Web-страницы. Каждый тег содержит определенную инструкцию и заключается в угловые скобки (о). Приведем пример простейшей таблицы, записанный на языке HTML (лис- тинг 6.3).
Ввод и вывод табличных данных. Решение системы уравнений 131 : Листинг 6.3. Представление таблицы на языке HTML <title>npHMep таблицы</Т1Т1е> <table border> <capt1оп>Таблица телефонов*: /capt ion> <tr><td>Андрей - pa6<td>274-88-17 <trxtd>CBeTa~X<td>+38 (067) 7030356 <trXtd^3K<td>22-345-72 <trXtd>CnpaBKa по тел<Ьб>009 </table> Вообще говоря, если строго придерживаться правил языка HTML, то сначала следует написать теги <html>, <head>, <title> и т. д. Однако современные браузеры понимают и такую разметку, которая приведена в листинге 6.3. В нашем примере даже не указан ни один закрывающий тег для <tr> (тег, за- дающий строку в таблице) и для <td> (тег, задающий ячейку в таблице). Очень полезно будет читателю набрать приведенный нами пример в Блокно- те, как-нибудь назвать этот файл с расширением htm и открыть его в каком- либо браузере Internet Explorer, Mozilla Firefox или другом обозревателе. Также поучительно открыть этот файл в редакторе HTML Microsoft Office FrontPage и проследить, как меняется HTML-форматирование при тех или иных изменениях, сделанных в таблице. Наша программа имеет данные, уже знакомые читателю из примера 39. Эти данные находятся в двух массивах: imenaO и те1(). На основании этих двух массивов программа формирует таблицу в формате HTML, т. е. создает тек- стовый файл (в нашей программе он называется C:\Tabl_tel.htm), а затем от- крывает этот файл браузером Internet Explorer. Текст программы приведен в листинге 6.4. | Листинг 6.4. Вывод таблицы в Internet Explorer ' . . . • Вывод таблицы в Internet Explorer. Здесь реализован несколько ' необычный подход к выводу таблицы для ее просмотра и печати ' на принтере. Программа записывает таблицу в текстовый файл в формате ’ HTML. Теперь у пользователя появляется возможность прочитать эту ’ таблицу с помощью обозревателя Web-страниц Internet Explorer ’ или другого браузера. Public Class Forml Private Sub Forml_Load(ByVai sender As System.Object, ByVai e As System.EventArgs) Handles MyBase.Load
132 Гпава 6 Me.Text = "Таблица в формате HTML" Dim ImenaO As String = {"Андрей - раб", "Света-Х", "ЖЭК", "Справка по тел", "Александр Степанович", "Мама — дом", "Карапузова Таня", "Погода сегодня", "Театр Браво"} DimTelO As String = {"274-88-17", "+38(067)7030356", "22-345-72", "009", "223-67-67 доп 32-67", "570-38-76", "201-72-23-прямой моб", "001", "216-40-22"} Dim text As String = "<title>npHMep таблицы</^Ь1е>" & "ctable border><caption>" & "Таблица Tene$OHOB</caption>" & vbCrLf For i As Short = 0 To 8 text &= String.Format("<tr><td>{0}<td>{1}", Imena(i), Tel(i)) & vbCrLf Next text &= "</table>" ' Запись таблицы в текстовый файл C:\Tabl_tel.htm. ’ Создание экземпляра Streamwriter для записи в файл Dim Писатель As New IO.Streamwriter("С:\Tabl_tel.htm", False, System.Text.Encoding.GetEncoding(1251)) ' — здесь заказ кодовой страницы Winl251 для русских букв Писатель.Write(text) : Писатель.Close() Try System.Diagnostics.Process.Start("lexplore", "C:\Tabl_tel.htm") ' Файл HTM можно открывать также с помощью MS WORD: ' System.Diagnostics.Process.Start("WinWord", "C:\Tabl_tel.htm") Catch Exc As Exception ' Отчет об ошибках MessageBox.Show(Exc.Message, "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Exclamation) End Try End Sub End Class Как видно, HTML-файл формируется с помощью строковой переменной text. Между тегами <title> и </titie> указано название страницы. Это текст, ко- торый браузер покажет в заголовке окна.
Ввод и вывод табличных данных. Решение системы уравнений 133 Тег <tabie> указывает на начало таблицы, между тегами <caption> и </caption> расположено название таблицы. Далее в цикле For.. .Next фор- мируется каждая строка таблицы. Используется уже известный читателю string.Format, т. е. вместо фигурной скобки {0} подставляется элемент мас- сива Imena(i), а вместо {1}— Tel(i). Затем, создавая поток Писатель, записываем на диск текстовый файл C:\Tabl_tel.htm. Далее в блоке Try.. .Catch открываем этот файл с помощью браузера Internet Explorer. (Помимо метода start исполняемый файл Iexplore.exe можно было бы вызвать командой shell.) Результат работы программы приведен на рис. 6.4. Очень технологично открыть созданный НТМ-файл не Web-браузером, а тек- стовым редактором MS Word, т. е. в программном коде написать: System.Diagnostics.Process.Start("WinWord”, "C:\Tabl_tel.htm") В этом случае пользователь вашей программы будет иметь возможность ре- дактировать полученную таблицу. Убедиться в работоспособности програм- мы можно, открыв решение ТаЫ НТМ my.sln в папке ТаЫ НТМ ту.
134 Гпава 6 Пример 42. Формирование таблицы с помощью элемента управления DataGridView Создадим приложение VB2010, которое заполняет два строковых массива и выводит эти массивы на экран в виде таблицы, используя элемент управления DataGridView (просмотр сетки данных). Элемент управления DataGridView предназначен для просмотра таблиц с возможностью их редактирования. Запускаем VB2010, далее— новый проект и выбираем шаблон Windows Forms Application, при этом получаем стандартную форму. Перенесем в форму элемент управления сетка данных DataGridView из панели Toolbox. В данной программе два уже знакомых читателю массива imena () и Tel () вы- водятся на сетку данных DataGridView. Для максимального упрощения про- граммы формируем таблицу при обработке события загрузки формы Formi Load. Текст программы приведен в листинге 6.5. j Листинг 6Л. Формирование таблицы с помощью элемента управления : ' Программа заполняет два строковых массива и выводит эти массивы на ' экран в виде таблицы, используя элемент управления DataGridView ' (сетка данных). Элемент управления DataGridView предназначен для ' просмотра таблиц с возможностью их редактирования Public Class Forml Private Sub Forml_Load(ByVai sender As System.Object, ByVai e As System.EventArgs) Handles MyBase.Load Me.Text = "Формирование таблицы" Dim Imena() As String = {"Андрей — раб", "Света-Х", "ЖЭК", "Справка по тел", "Александр Степанович", "Мама — дом", "Карапузова Таня", "Погода сегодня", "Театр Браво"} DimTelO As String = {"274-88-17", "+38(067)7030356", "22-345-72", "009", "223-67-67 доп 32-67", "570-38-76", "201-72-23-прямой моб", "001", "216-40-22"} ' Создание объекта "таблица данных" Dim dt As New DataTable ' Заполнение шапки таблицы dt.Columns.Add("Имена") dt.Columns.Add("Номера телефонов")
Ввод и вывод табличных данных. Решение системы уравнений 135 ’ Заполнение клеток (ячеек) таблицы данных For i As Short = 0 To 8 dt.Rows.Add(New String() {Imena(i), Tel(i)}) Next ’ Для сетки данных указываем источник данных DataGridViewl.DataSource = dt End Sub End Class Как видно, в программе используется объект ’’таблица данных” DataTabie. С его помощью сначала заполняем ’’шапку” таблицы данных, используя ме- тод columns.Add, а затем непосредственно ячейки таблицы, используя метод Rows. Add. Чтобы передать построенную таблицу в элемент управления DataGridview, указываем в качестве источника данных Datasource объект dt класса DataTabie. На рис. 6.5 приведен результат работы программы. Заметьте, щелкая мышью на заголовках колонок, получаем сортировку данных в алфавитном порядке полей таблицы. Рис. 6.5. Форматирование таблицы Убедиться в работоспособности программы можно, открыв решение TabGrdWin.sln в папке TabGrdWin.
136 Гпава 6 Пример 43. Табличный ввод данных. DataGridView. DataTable. DataSet. Файл XML Существует множество задач, предполагающих ввод данных в виде таблиц. Конечно, можно эту таблицу программировать как совокупность текстовых полей TextBox, но часто заранее неизвестно, сколько рядов данных будет вво- дить пользователь, необходимо предусмотреть скроллинг этой таблицы и т. д. То есть проблем в организации ввода табличных данных достаточно много. Мы предлагаем для цели ввода табличных данных использовать элемент управления DataGridView (сетка данных). Прежде всего, этот элемент управ- ления предназначен для отображения данных, которые удобно представить в виде таблицы, чаще всего источником этих данных является база данных. Однако кроме отображения DataGridView позволяет также редактировать таб- личные данные. Элемент управления DataGridView поддерживает выделение, изменение, удаление, разбиение на страницы и сортировку. Программа, обсуждаемая в данном разделе, предлагает пользователю запол- нить таблицу телефонов его знакомых, сотрудников, родственников, люби- мых и т. д. После щелчка на кнопке Запись данная таблица записывается на диск в файл в формате XML. Для упрощения текста программы предусмот- рена запись в один и тот же файл C:\tabl.xml. При последующих запусках данной программы таблица будет считываться из файла, и пользователь мо- жет продолжать редактирование таблицы. Поэтому эту программу можно громко назвать табличным редактором. Щелкая мышью на заголовках коло- нок, можно расположить записи в колонках в алфавитном порядке для удоб- ного поиска необходимого телефона. Для написания программы требуется из панели управления Toolbox перене- сти мышью элемент управления DataGridView и кнопку Button. Текст про- граммы приведен в листинге 6.6. Листинг 6.6. Заполнение телефонной книги ' Программа предлагает пользователю заполнить таблицу телефонов ' его знакомых, сотрудников, родственников, любимых и т. д. ' После щелчка на кнопке Запись данная таблица записывается на диск ' в файл в формате XML. Для упрощения текста программы предусмотрена ' запись в один и тот же файл C:\tabl.xml. При последующих запусках ' данной программы таблица будет считываться из этого файла, ' и пользователь может продолжать редактирование таблицы Public Class Forml Dim dt As New DataTable ' Создание объекта "таблица данных" Dim ds As New DataSet ' Создание объекта "набор данных"
Ввод и вывод табличных данных. Решение системы уравнений 137 Private Sub Forml_Load(ByVal sender As System.Object, ByVai e As System.EventArgs) Handles MyBase.Load MyBase.Text = "Почти табличный редактор" Buttonl.Text = "Запись" If IO.File.Exists("C:\tabl.xml") = False Then ' Если XML-файла HET DataGridViewl.Datasource = dt ' Заполнение шапки таблицы dt.Columns.Add("Имена") dt.Columns.Add("Номера телефонов") ' Добавить объект dt в DataSet ds.Tables.Add(dt) Else ' Если XML-файл ЕСТЬ: ds.ReadXml("C:\tabl.xml") DataGridViewl.DataMember = "Название таблицы" DataGridViewl.DataSource = ds End If End Sub Private Sub ЗАПИСЬ(ByVai sender As System.Object, ByVai e As System.EventArgs) Handles Buttonl.Click dt.TableName = "Название таблицы" ds.WriteXml("C:\tabl.xml") End Sub End Class Как видно из текста программы, потребовалось всего лишь несколько строк программного кода для создания такой многофункциональной программы. Это стало возможным благодаря использованию мощной современной техно- логии ADO.NET. В начале класса объявлены два объекта этой технологии: "набор данных" DataSet И "таблица данных" DataTable. Объект DataSet явля- ется основным компонентом архитектуры ADO.NET. DataSet представляет кэш данных, расположенный в оперативной памяти. DataSet состоит из кол- лекции объектов DataTable. То есть в один объект DataSet может входить не- сколько таблиц, а информацию о них мы можем записывать в файл на диск одним оператором writexml, соответственно читать — ReadXML. Таким обра- зом, в этой программе мы имеем дело преимущественно с тремя объектами: DataSet — кэш данных, DataTable — представляет одну таблицу с данными и DataGridView — элемент управления для отображения данных.
138 Гпава 6 При загрузке формы Fomi Load мы обработали две ситуации. Если фай- ла, в который мы пишем информацию о таблице, не существует Exists("C:\tabi.xmi") = False, то назначаем в качестве источника данных Datasource для DataGrid объект класса DataTabie и заполняем "шапку" табли- цы, т. е. указываем названия колонок: "Имена" и "Номера телефонов", а затем добавляем объект DataTabie в объект DataSet. Теперь пользователь видит пустую таблицу с двумя колонками и может ее заполнять. Если файл сущест- вует (ветвь Else), то данные в объект DataSet отправляем из XML-файла (ReadXML). Здесь уже в качестве источника данных для DataGrid указываем объект DataSet. При щелчке мышью на кнопке Запись (рис. 6.6) — событие Buttoni.Click — происходит запись XML-файла на диск (writexml). Рис. 6.6. Почти табличный редактор Здесь используются так называемые XML-файлы. Формат этих файлов по- зволяет легко и надежно передавать данные посредством Интернета даже на компьютеры другой платформы (например, Macintosh). В нашей задаче мы не ставили перед собой цель работать в Интернете, а всего лишь воспользова- лись данной технологией. XML-файл можно просмотреть Блокнотом или с помощью MS Word, поскольку это текстовый файл. Однако следует учесть, что этот файл записан в кодировке UTF-8, поэтому другими текстовыми ре- дакторами, например edit.com или Rpad32.exe (русский Блокнот), его прочи- тать затруднительно. XML-документ открывается Web-браузером, MS Front Page и другими программами, при этом отступы и разные цвета позволяют выразительно увидеть структуру данного файла. XML-файл можно открыть табличным редактором MS Excel, и при этом он может отобразиться в ви- де таблицы. На рис. 6.7 приведен образец представления XML-файла в MS Word. При использовании нами XML-файлов для данной задачи программирования простейшего табличного редактора совсем необязательно вникать в его
Ввод и вывод табличных данных. Решение системы уравнений 139 структуру, тем более что при выборе имени файла при сохранении совер- шенно необязательно устанавливать расширение файла xml, файл с любым расширением будет читаться методом Readxml, как XML-файл. Рис. 6.7. Образец представления XML-файла в MS Word Программист может иметь доступ к полям таблицы. Например, доступ к ле- вой верхней ячейке (полю) таблицы можно получить, используя свойство объекта DataTable: at .Rows. item(O). item(O). Однако запись этого поля, на- пример, в последовательный файл будет некорректной даже при использова- нии дополнительной переменной из-за того, что технология ADO.NET преду- сматривает кэширование данных. Таким образом, чтение и запись данных для подобных таблиц следует организовывать только через методы объекта DataSet. Замечу, что данная программа может также являться инструментом для соз- дания XML-файлов. Убедиться в работоспособности программы можно, от- крыв решение Tabl GRD XML.sIn в папке Tabl GRD XML.
140 Гпава 6 Пример 44. Решение системы линейных уравнений. Ввод коэффициентов через DataGridView В инженерном деле, в экономических, научных расчетах часто встречается задача по решению системы линейных алгебраических уравнений (СЛАУ). Между тем, решение данной задачи последнее время редко приводится в книгах по языкам программирования. В данной программе ввод коэффициен- тов при неизвестных, а также правых частей системы предусмотрен с по- мощью элемента управления DataGridView. Таким образом, пользовательский интерфейс будет состоять (см. рис. 6.8) из формы, элемента управления DataGridView и кнопки Решить. В листинге 6.7 приведен программный код решения задачи. Листинг 6.7. Решение системы линейных уравнений • Программа для решения системы линейных уравнений. Ввод ' коэффициентов предусмотрен через DataGridView Option Strict On Public Class Forml Dim n As Integer ' — размерность СЛАУ Dim dt As New DataTable Private Sub Forml_Load(ByVai sender As System.Object, ByVai e As System.EventArgs) Handles MyBase.Load MyBase.Text = "Решение системы уравнений" Dim say As String Do say = InputBox("Ведите количество неизвестных") If IsNumeric(say) = True Then Exit Do Loop n = Convert.Tolnt32(say) DataGridViewl.DataSource = dt ' DataGridViewl.CaptionText = ' "Введите коэффициенты уравнений и правую часть L:" ' Создаем шапку таблицы For i As Integer = 1 To n say = "X" & Convert.ToString(i)
Ввод и вывод табличных данных. Решение системы уравнений 141 dt.Columns.Add(New DataColumn(say, GetType(String))) Next ' Колонка правой части системы: dt.Columns.Add(New DataColumn("L", GetType(String))) Buttoni.Text = "Решить" End Sub Private Sub РЕШИТЬ(ByVai sender As System.Object, ByVai e As System.EventArgs) Handles Buttoni.Click ' Нажали на кнопку Решить Dim A(n, n), L(n) As Double Dim i, j As Integer ' dt.Rows.Count - количество рядов If dt.Rows.Count <>n Then MessageBox.Show("Количество строк не равно количеству колонок") Exit Sub End If ' Заполнение матрицу коэффициентов системы А(j, i) For j = 0 To n — 1 For i = 0 To n - 1 ' j — номер строки, i — номер столбца A(j, i) = CType(dt.Rows.Item(j).Item(i), Double) Next i ' Правая часть системы В(j, 0) L(j) = CType(dt.Rows.Item(j).Item(i), Double) Next j Call gauss(n, A, L) ' Решение системы методом Гаусса Dim s As String = "Неизвестные равны:" & vbCrLf For j = 1 To n s = s & "X" & j & " = " & L(j - 1) & "; " Next MessageBox.Show(s) End Sub Sub gauss(ByVai n As Integer, ByVai A As Double(,), ByRef LL() As Double)
142 Гпава 6 ’ п — размер матрицы ’ А — матрица коэффициентов линейных уравнений ’ LL — правая часть, сюда возвращаются значения неизвестных Dim i, j, 1 As Integer Dim cl, c2, c3 As Double For i = 0 To n - 1 ’ Цикл по элементам строки cl = О For j = i To n — 1 c2 = A(j, i) If Math.Abs(c2) > Math.Abs(cl) Then 1 = j : cl = c2 End If Next j For j = i To n - 1 c3 = A(l, j) / cl A(l, j) = A(i, j) : A(i, j) = c3 Next j c3 = LL(1) / cl : LL(1) = VL (i) : LL(i) = c3 For j = 0 To n - 1 If j = i Then Continue For For l=i+lTon—1 A(j, 1) = A(j, 1) - A(i, 1) * A(j, i) Next 1 LL(j) = LL(j) - LL(i) * A(j, i) Next j Next i End Sub End Class Как видно, размерность СЛАУ п и объект DataTable объявлены нами вне про- цедур обработок событий с тем, чтобы область их действия распространялась на весь класс. В программе предусмотрена обработка события загрузки фор- мы и обработка события "щелчок на кнопке" Решить. При загрузке формы пользователю поступает запрос "Введите количество неизвестных" через функцию InputBox. Эта функция включена в бесконечный
Ввод и вывод табличных данных. Решение системы уравнений 143 цикл Do...Loop, выйти из которого пользователь может, только введя число (проверка ВВОДа На НебуКВеННЫе СИМВОЛЫ С ПОМОЩЬЮ фуНКЦИИ IsNumeric). То есть здесь предусмотрен несколько недружественный интерфейс, поскольку автор стремился максимально сократить текст программы. Рис. 6.8. Фрагмент табличного ввода данных В данной программе в самом начале программного кода установлено значе- ние option strict в on для контроля преобразования типов, например, кон- вертирования строковой переменной say В Integer: n = Convert .Tolnt32 (say). Далее в качестве источника данных Datasource для DataGrid указан dt, т. е. объект DataTabie. Поскольку мы уже получили от пользователя размерность системы п, мы можем сформировать ’’шапку” таблицы используя метод dt.Column.Add. После того как пользователь ввел коэффициенты системы ли- нейных уравнений и правой части (см. рис. 6.8), обрабатываем событие ’’щелчок на кнопке” Решить Buttoni.Click. Как видно, здесь объявлен дву- мерный массив А(п,п) коэффициентов системы и одномерный массив L(n) размерностью п. Затем происходит проверка, равно ли количество введенных пользователем строк dt.Rows.Count количеству неизвестных п. Затем два вложенных цикла по i и по j заполняют матрицу коэффициентов А и вектор свободных чле- нов (правых частей) L. Как видно, данная программа не предусматривает проверку введения пользователем нечисловых символов. Далее вызывается процедура решения СЛАУ методом Гаусса gauss (n, a, l), т. е. методом последовательного исключения неизвестных. В основе процеду- ры gauss (n, a, L) — цикл For.. .Next i по элементам строки матрицы систе- мы. В этот внешний цикл вложены три внутренних цикла по строкам матри- цы. В третьем вложенном цикле для пропуска итерации предусмотрен опера- тор Continue For (аналог continue в C++), которого, например, в версии VB .NET еще не было, и для пропуска итерации в операторе цикла приходи- лось использовать оператор Go то. Использование оператора Go то нарушает принципы так называемого структурного программирования, согласно кото-
144 Гпава 6 рому в любой программе передача управления должна осуществляться толь- ко тремя типами управляющих структур: простая последовательность (опе- раторы выполняются друг за другом слева направо, сверху вниз), ветвление (выбор ветви по условию) и цикл. Причем, используя эти три структуры управления, следует обходиться без операторов Go То, которые вносят неоп- равданную сложность в запутанные тексты программ. После вызова процедуры gauss формируется строка s для вывода значений неизвестных, которая выводится посредством диалогового окна MessageBox (рис. 6.9). Рис. 6.9. Вывод неизвестных значений в диалоговое окно Данная программа не предусматривает проверку на вырожденность СЛАУ, однако в этом случае в качестве значений неизвестных пользователь получа- ет либо "бесконечность”, либо константу NaN, значение которой является ре- зультатом деления на ноль. Программа не предусматривает ограничение сверху на размерность решаемой системы и должна работать при любой ра- зумной размерности. Работа программы должна быть ограничена лишь раз- мером оперативной памяти. Однако автор не тестировал эту программу на решение систем большой размерности. Если количество неизвестных равно одному, то программа также нормально работает. Убедиться в работоспособности программы можно, открыв решение Gaus_grd.sln в папке Gaus grd.
ГЛАВА 7 Элемент управления WebBrowser Пример 45. Отображение HTML-таблиц В этом разделе воспользуемся элементом управления WebBrowser для ото- бражения таблицы, записанной на языке HTML с помощью элементарных тегов: <tr>, задающего строку в таблице, и <td>, задающего ячейку в таблице. Понятно, что сформировав такой HTML-файл, содержащий таблицу, подле- жащую выводу на экран, можно вывести этот файл в поле элемента управле- ния WebBrowser с помощью метода Navigate объекта. Покажем, как задав на языке HTML какую-нибудь таблицу в строковой пе- ременной, можно вывести эту таблицу в поле элемента управления WebBrowser, при этом не записывая на винчестер HTML-файл. Для этой це- ли воспользуемся простейшей таблицей из примера 41. Приступим к программированию поставленной задачи. Запустим VB2010 и выберем новый проект. В прежних версиях VB, например VB.NET, элемента управления WebBrowser не было на панели элементов Toolbox. Его прихо- дилось добавлять с помощью контекстного меню Add/Remove Items. Панель элементов VB2010 уже содержит в себе элемент WebBrowser, поэтому про- сто перетаскиваем его в форму. Текст программы приведен в листинге 7.1. Листинг 7 Л. Отображение таблиц с помощью элемента управления ’ В программе для отображения таблицы используется элемент управления ’ WebBrowser. Таблица записана на языке HTML с помощью элементарных ’ тегов <tr> (строка в таблице) и <td> (ячейка в таблице) Public Class Forml Private Sub Forml_Load(ByVai sender As System.Object, ByVai e As System.EventArgs) Handles MyBase.Load
146 Гпава 7 ’ WebBrowserl.Navigate("с:\tabl.htm") Dim Str_html As String - "Какой-либо текст до таблицы" & "<table border> " & "<сарГ1оп>Таблица телефонов</сарГ1оп> " & "<tг><td>Андрей — pa6<td>274-88-17 " & "<tr><td>CBeTa-X<td>+38(067)7030356 " & "<trXtd»K3K<td>22-345-72 " & ,r<tr><td>CnpaBKa по тел<бб>009 " & "</table> " & "Какой-либо текст после таблицы" WebBrowserl.Navigate("about:" & Str_html) End Sub End Class Как видно из текста программы, при обработке события загрузки формы Formi Load в строковой переменной str html задаем HTML-представление простейшей таблицы, состоящей из двух столбцов и четырех строк. Эту стро- ку подаем на вход метода Navigate объекта WebBrowserl, сцепляя ее с ключе- вым словом "about:". В комментарии показано, как можно подать на вход метода Navigate таблицу, если она уже записана в файл tabl.html. В результате работы этой программы получаем отображение таблицы в поле элемента управления WebBrowser, как показано на рис. 7.1. Какай-либо текст да табпицы 1 абпи! ta тепе фонов Андрей - раб 274 -33-17 С вет а- X + 38 (067) / 030356 Справка по теп 009 Рис. 7.1. Отображение таблицы в поле элемента управления WebBrowser Теперь очень легко можно распечатать данную таблицу на принтере, для это- го необходимо попасть в контекстное меню, щелкая правой кнопкой мыши в пределах таблицы. Убедиться в работоспособности программы можно, открыв решение Iexplorer_my2.sln в папке Iexplorer_my2.
Элемент управления WebBrowser 147 Пример 46. Отображение Flash-файлов Ранее мы уже обсуждали элемент управления PictureBox, способный ото- бражать растровые файлы различных форматов. Однако PictureBox не умеет отображать Flash-файлы формата SWF. Этот формат очень распространен в Интернете благодаря тому, что удачно сочетает в себе векторную графику, растровую графику, воспроизведение звука и при этом предусматривает ком- пактный код, что позволяет быстро загружать SWF-файлы в браузер. В данном разделе мы создадим программу, которая воспроизводит в поле элемента управления WebBrowser файл SWF. Запустим VB2010, затем выбе- рем новый проект— Windows Forms Application. Перетащим с панели Toolbox элемент управления WebBrowser в форму. Теперь — двойной щел- чок в пределах формы, и мы попадаем в строчки программного кода, обраба- тывающего событие загрузки формы Fomi Load. Далее напишем программ- ный код, приведенный в листинге 7.2. | Листинг 7.2. Отображение Flash-файлов ; ’ Программа использует элемент управления WebBrowser для ’ отображения Flash-файлов 1 Imports System.10 Public Class Forml Private Sub Forml_Load(ByVai sender As System.Object, ByVai e As System.EventArgs) Handles MyBase.Load ’ WebBrowserl.Navigate("www.mail.ru") WebBrowserl.Navigate(System.10.Directory.GetCurrentDirectory & "\Shar.swf”) End Sub End Class Здесь В тексте программы вызываем метод Navigate объекта WebBrowserl. На вход метода подаем полный путь к Flash-файлу Shar.swf. Полный путь к те- кущей папке получаем с помощью функции GetCurrentDirectory. Обращение к этой функции можно было немного сократить, импортируя пространство имен imports System, ю, как показано в комментарии. Также в комментарии показано, как можно вывести Web-страницу из Интернета в поле элемента управления WebBrowser. В результате работы этой программы получаем отображение файла Shar.swf (рис. 7.2).
148 Гпава 7 Рис. 7.2. Отображение Flash-файла в поле элемента управления WebBrowser Из рисунка не видно, что шар вращается. Убедиться в работоспособности программы можно, открыв решение lexplorermy.sln в папке lexplorer my. Пример 47. Отображение Web-страницы и ее HTML-кода Напишем на VB2010 программу, способную в одном окне отображать Web- страницу, а в другом показывать HTML-код загружаемой в браузер страни- цы. Ядром этой программы будет элемент управления обозревателя WebBrowser. Таким образом, экранная форма будет содержать на себе эле- мент управления WebBrowser, два текстовых поля и кнопку. Запустим VB2010, выполним команду New Project из меню File, далее выбе- рем шаблон Windows Forms Application и нажмем кнопку ОК. Используя панель элементов, добавим элемент управления WebBrowser в экранную форму, также добавим два текстовых поля и кнопку. Первое текстовое поле TextBoxl предназначено для ввода URL-адреса желаемой Web-страницы (на- пример, www.latino.ho.ua), а второе поле TextBox2 растянем побольше, по- скольку сюда будет выводиться HTML-код загружаемой в браузер страницы. Чтобы была возможность растянуть второе поле по вертикали, укажем явно в свойствах этого поля (Properties) Multiline = True. Текст программы при- веден в листинге 7.3.
Элемент управления WebBrowser 149 Листинг 7.3. Отображение Web-страницы и ее HTML-кода ’ Эта программа использует элемент управления WebBrowser для ’ отображения Web-страницы и ее HTML-кода Public Class Forml Private Sub Forml_Load(ByVai sender As System.Object, ByVai e As System.EventArgs) Handles MyBase.Load Me.Text = "Web-страница и ее HTML-код" TextBoxi.Text = Nothing : TextBox2.Text = Nothing TextBox2.Multiline = True TextBox2.ScrollBars = ScrollBars.Vertical Buttoni.Text = "ПУСК" End Sub Private Sub ПУСК(Ву7а1 sender As System.Object, ByVai e As System.EventArgs) Handles Buttoni.Click ' Щелчок на кнопке ПУСК: WebBrowserl.Navigate(TextBoxi.Text) ’ WebBrowserl.Navigate("www.latino.ho.ua") ’ WebBrowserl.GoBack() ’ Назад ’ WebBrowserl.GoForward() ' Вперед ' WebBrowserl.GoHome() ’ На домашнюю страницу End Sub Private Sub KOMTUI(ByVal sender As Object, ByVai e As _ System.Windows.Forms.WebBrowserDocumentCompletedEventArgs) _ Handles WebBrowserl.DocumentCompleted ’ Событие документ обозревателя "укомплектован": ' "заполнен" ' Получить HTML-код из документа WebBrowser TextBox2.Text = WebBrowserl.Document.Body.InnerHtml End Sub End Class Как видно из программного кода, при загрузке формы задаем некоторые уже хорошо известные читателю свойства. Свойство ScrollBars, определяющее скроллинг текстового поля, приведено в состояние vertical, означающее раз- решение вертикальной прокрутки. При обработке события ’’щелчок на кнопке” Пуск метод Navigate объекта WebBrowserl вызывает в поле элемента управления обозревателя Web- страницу с адресом, указанным пользователем данной программы в тексте-
150 Гпава 7 вом поле TextBoxl. В комментарии приведены варианты дальнейшего совер- шенствования данной программы. Так метод GoBack возвращает пользователя на предыдущую Web-страницу, метод GoForward — на последующую, а метод GoHome загружает в поле браузера домашнюю Web-страницу. Все эти методы можно было бы развести по разным командным кнопкам, но мы не стали это- го делать, чтобы не загромождать программу, а наоборот показать вырази- тельно главное. Событие Documentcoinpieted подразумевает, что документ обозревателя "укомплектован", т. е. загрузка страницы в браузер завершена. При обработке этого события функция Body. innerHTML возвращает в свойство Text текстового поля TextBox2 HTML-код, соответствующий загруженной в браузер Web- страницы. На рис. 7.3 показан пример работы данной программы. j Клтбные латиноамериканские танцы А | у ; . п ] па этом сайте I j соораны некоторые ' j . ; видео и аудио } латпноамершсанским' ; ? 1Л 1............ШИО! j TaHUbK/FfiNT^;/R></CAPTiON>' ' ' 1|||||||||И 1<тя>. | И | <P align--center><IMG herght=46 src-‘’gimn.qjf' wicHh-46 border=0>\/P>-'/TG> f < T D wid*h=544> j j . < P aiign-center< F0HI sEe=4> 11а этом сайте собраны не»-.от орые видео и аудио Файды по клубным |у.пичным1<$РАЫ lang=en-u$> j i латиноамериканским ганцам.</ЕОНТ>< /Р> I <.MENiJ> | <U iryfe-'LiST $ ГДЕ -IMAGE ИЬШдДПА I ' hroM'ViHp corn иаГ‘> ^Хороший бесплатный хостинг;/А,> <L» ’LiST-STYLE-IMAGE: unihtmi grffxA : hrvb’Hip A-Ywm'.luc;a ho иа/“>_Женская и мужская одежа по оптовым л Рис. 7.3. Загрузка Web-страницы и ее HTML-кода Убедиться в работоспособности программы можно, открыв решение Split.sln в папке Split.
ГЛАВА 8 Использование функций MS Word, MS Excel, AutoCAD Пример 48. Проверка правописания в текстовом поле с помощью обращения к MS Word Пакет приложений Microsoft Office может являться сервером OLE-объектов, и его функции могут использоваться другими приложениями. Продемонстри- руем такое использование. Для этого создадим программу, которая позволяет пользователю ввести какие-либо слова, предложения в текстовое поле и по- сле нажатия соответствующей кнопки проверить орфографию введенного текста. Для непосредственной проверки орфографии воспользуемся функци- ей checkspelling объектной библиотеки MS Word. Запустим VB2010, выберем новый проект Windows Forms Application. Пе- ретащим из панели элементов Toolbox в форму текстовое поле. Чтобы растя- нуть его На ВСЮ форму, В СВОЙСТВе Multiline текстового ПОЛЯ укажем True (разрешим введение множества строк). Также с панели инструментов пере- тащим кнопку Button. Мы должны получить примерно такой дизайн, кото- рый представлен на рис. 8.1. Далее к текущему проекту добавим объектную библиотеку MS Word (биб- лиотеку компонентов). Для этого в пункте меню Project выберем команду Add Reference. Затем, если на вашем компьютере установлен MS Office 2003, на вкладке СОМ дважды щелкнем по ссылке на библиотеку Microsoft Word 11.0 Object Libary. Если же установлен MS Office 2007, то дважды щелкнем на ссылке Microsoft Word 12.0 Object Library. Эта объектная биб- лиотека соответствует файлу, расположенному по адресу: C:\Program Files\Microsoft Office\OFFICEl 1\MSWORD.OLB (или подкаталог OFFICE12 для MS Office 2007).
152 Гпава 8 Рис. 8.1. Фрагмент работы программы проверки орфографии Теперь убедимся в том, что данная ссылка благополучно установлена. Для этого в меню Project выберем пункт WinddowsAppIicationl Properties и на вкладке References мы видим строку Microsoft Word 11.0 Object Library. Кроме того, в папке проекта obj\x86\Debug появился файл Interop.Office.dll. Таким образом, мы подключили библиотеку объектов MS Word. Далее напи- шем программный код, приведенный в листинге 8.1. Листинг 8.1. Проверка орфографии ’ Программа позволяет пользователю ввести какие-либо слова, предложения ’ в текстовое поле и после нажатия соответствующей кнопки проверить ’ орфографию введенного текста. Для непосредственной проверки ’ орфографии воспользуемся функцией Checkspelling ’ объектной библиотеки MS Word. Imports Microsoft.Office.Interop Public Class Forml Private Sub Forml_Load(ByVai sender As System.Object, ByVai e As System.EventArgs) Handles MyBase.Load TextBoxi.Clear() Buttoni.Text = "Проверка орфографии" End Sub Private Sub КНОПКА(ByVai sender As System.Object, ByVai e As System.EventArgs) Handles Buttoni.Click ’ Dim W As Word.Application = New Word.Application, ’ Но можно написать короче Dim W = New Word.Application W.Visible = False W.Documents.Add() ’ Открываем новый документ
Использование функций MS Word, MS Excel, AutoCAD 153 ’ Копируем содержимое текстового окна в документ W.Selection.Text = TextBoxl.Text ’ Проверка орфографии: W.ActiveDocument.Checkspelling() ’ Копируем результат назад в текстовое поле TextBoxl.Text = W.Selection.Text W.ActiveDocument.Close(Word.WdSaveOptions.wdDoNotSaveChanges) W.Quit() W = Nothing End Sub End Class Как видно из текста программы, при загрузке формы Formi Load очищается текстовое поле и инициализируется название кнопки Проверка орфографии. При обработке события ’’щелчок по кнопке” Buttonl.Click создается новый объект word.Application и командой Documents.Add открывается новый доку- мент. Далее весь введенный пользователем текст копируется в этот документ. Затем происходит непосредственная проверка орфографии командой Checkspelling. Далее документ закрываем без сохранения изменений wdDoNotSaveChanges. После нажатия кнопки Проверка орфографии получим диалоговое окно, подобное представленному на рис. 8.2. Рис. 8.2. Проверка правописания в текстовом поле Убедиться в работоспособности программы можно, открыв решение wrd.sln в папке wrd.
154 Гпава 8 Пример 49. Вывод таблицы средствами MS Word В данной книге мы уже рассматривали способы формирования таблицы. Здесь мы обсудим способ создания таблицы, используя функции MS Word. Вообще говоря, программировать взаимодействие программы на VB2010 с различными офисными приложениями (Word, Excel, Access, PowerPoint и т. д.), а также с AutoCAD и CorelDRAW удобно, поскольку во все эти при- ложения встроен язык VBA (Visual Basic for Applications). Причем есть воз- можность записи макроса с последующим просмотром соответствующей VBA-программы. Например, мы хотим посмотреть, как организована вставка таблицы в редакторе MS Word. Для этого запускаем MS Word, далее в меню Сервис выбираем команду 'Макрос | Начать запись, далее в диалоговом ок- не Запись макроса указываем имя макроса и щелкаем на кнопке ОК. Теперь в текст MS Word вставляем таблицу, используя пункты меню Таблица | Вставить | Таблица и т. д. После заполнения таблицы нажимаем кнопку Ос- тановить запись. Далее с помощью комбинации клавиш <Alt>+<F 11 > от- кроем окно Microsoft Visual Basic, здесь мы увидим текст макроса на языке VBA. Из этого текста мы можем понять основной принцип, имена исполь- зуемых объектов, функций, свойств и пр. А теперь рассмотрим уже конечный результат— программу на VB2010, ко- торая, используя функции MS Word, строит таблицу. Итак, запускаем VB2010, выбираем новый проект, указываем шаблон Windows Forms Application. Далее к текущему проекту добавим объектную библиотеку MS Word. Для этого в меню Project укажем команду Add Reference и на по- явившейся вкладке СОМ дважды щелкнем ссылку на библиотеку Microsoft Word 11.0 Object Library (или другая версия MS Word). Далее напишем программный код, приведенный в листинге 8.2. Листинг 8.2. Вывод таблицы средствами MS Word ’ Программа вывода таблицы средствами MS Word: запускается программа, ' пользователь наблюдает, как запускается редактор MS Word ' и автоматически происходит построение таблицы Imports Microsoft.Office.Interop Public Class Forml Private Sub Forml_Load(ByVai sender As System.Object, ByVai e As System.EventArgs) Handles MyBase.Load Me.Text = "Построение таблицы"
Использование функций MS Word, MS Excel, AutoCAD 155 Dim Imena () As String = {"Андрей - раб", "Света-Х", "ЖЭК", "Справка по тел", "Александр Степанович", "Мама — дом", "Карапузова Таня", "Погода сегодня", "Театр Браво"} DimTelO As String = {"274-88-17", "+38(067)7030356", "22-345-72", "009", "223-67-67 доп 32-67", "570-38-76", "201-72-23-прямой моб", "001", "216-40-22"} ' Dim W As Word.Application = New Word.Application Dim W = New Word.Application W.Visible = True W. Documents .Add () ' Открываем новый документ W.Selection.TypeText("ТАБЛИЦА ТЕЛЕФОНОВ") ' Создаем таблицу из 9 строк и 2 столбцов; ' автоподбор ширины столбцов — по ' содержимому ячеек (wdAutoFitContent) W.ActiveDocument.Tables.Add(W.Selection.Range, 9, 2, Word.WdDefaultTableBehavior.wdWord9TableBehavior, Word.WdAutoFitBehavior.wdAutoFitContent) ' Заполнять ячейки таблицы можно так For i As Short = 1 To 9 W.ActiveDocument.Tables(1).Cell( Row:=i, Column:=1).Range.InsertAfter(Imena(i —1)) W.ActiveDocument.Tables(1).Cell( Row:=i, Column:=2).Range.InsertAfter(Tel(i — 1)) Next ' Перевести курсор (Selection) за пределы таблицы W.Selection.MoveDown(Word.WdUnits.wdLine, Count:=9) W.Selection.TypeText(Text:="Какой-либо текст после таблицы") ' Сохранять нет смысла, но это решит пользователь ' W. ActiveDocument.SaveAs("С:\а.doc") End Sub End Class Заметим, что содержимое текстовой таблицы такое же, как и в примере 41 (см. главу 6). То есть наш сюжет меняется, а действующие персонажи оста- ются прежними. Данные находятся в двух массивах: imena () и Tel ().
156 Гпава 8 Далее создаем экземпляр объекта word.Application и открываем новый доку- мент w.Document.Add. Затем демонстрируем, как можно добавлять какие-либо тексты в новый документ из VB2010-программы, например, мы вводим в активный документ текст "ТАБЛИЦА ТЕЛЕФОНОВ". Далее создаем таблицу, состоящую из девяти строк (рядов) и двух столбцов, причем ширина столбцов будет регулироваться в зависимости от содержимого ячеек (wdAutoFitContent). Затем в цикле заполняем ячейки таблицы и выводим кур- сор (Selrction) за пределы таблицы, чтобы написать какой-либо текст. После запуска этой программы очень красиво, прямо на наших глазах в ре- дакторе MS Word сформируется таблица (рис. 8.3), которую при желании можно редактировать, сохранять и распечатывать на принтере. ТАБЛИЦА ТЕЛЕФОНОВ -tiVqien - р.п. (06~ Р 030: жэк......... .. ... 7 ; ? j. О правка по теп ___ ;• i .гкдекодвдр Степанович ИИ 201 П£ЯМШ1 [ j 001 О-40-22 ! Театр ]>рэво К лк от I- ш io о тек < т по с ле т а о ш пды Рис. 8.3. Программно сформированная таблица в редакторе MS Word Убедиться в работоспособности программы можно, открыв решение wrd_table.sln в папке wrd_table. Пример 50. Обращение к функциям MS Excel из Visual Basic 2010 Очень заманчиво обратиться из какой-нибудь вашей VB2010-программы к функциям Microsoft Excel. Табличный редактор MS Excel содержит очень мощные средства для сложных вычислений и анализа данных, которые могут значительно расширить возможности ваших программ.
Использование функций MS Word, MS Excel, AutoCAD 757 В данной программе мы продемонстрируем буквально в трех строчках про- граммного кода обращение к одной простой функции MS Excel, а именно по- лучение значения числа л = 3,14. Цель данной программы— показать лег- кость доступа к функциям MS Excel. Как обычно запустим VB2010, далее в окне New Project выберем шаблон Windows Forms Application и щелкнем на кнопке ОК. Проектируемую эк- ранную форму сделаем совсем маленькой, поскольку число л будем выво- дить в строку заголовка формы. Чтобы добавить в текущий проект возможности MS Excel, следует подклю- чить библиотеку объектов MS Excel. Для этого в пункте меню Project выбе- рем команду Add Reference. Затем, если на вашем компьютере установлен MS Office 2003, то на вкладке СОМ дважды щелкнем по ссылке на библиоте- ку Microsoft Excel 11.0 Object Library. Если же установлен MS Office 2007, то дважды щелкнем на ссылке Microsoft Excel 12.0 Object Library. To есть процедура добавления новой библиотеки объектов такая же, как и в примерах об использовании возможностей MS Word, а названия пунктов меню сохра- нились почти такими же, как в предыдущих версиях VB. Подключить новую библиотеку объектов в текущий проект можно также через контекстное меню окна Solution Explorer (Обозреватель решений), щелкнув на пункте Add Reference. Таким образом, мы подключили библиотеку объектов MS Excel. В окне Solution Explorer (чтобы его добавить, следует щелкнуть на значке Solution Explorer) щелкните на значке Show All Files, а затем раскройте дерево References. Одной из ветвей дерева будет ветвь Excel. Щелкнув правой кноп- кой мыши на значке этой ветви и выбрав пункт View in Object Browser, мы увидим объекты данной ветви в окне Object Browser (Обозреватель объек- тов). Найдем объект worksheetFunction, при этом в окне Members of ’WorksheetFunction1 увидим доступные нам функции MS Excel для объекта worksheetFunction. Теперь в программном коде обратимся к одной из этих функций, а именно функции Pi (). Для этого в обработчике события Formi Load напишем программный код, приведенный в листинге 8.3. j Листинг 8.3. Обращение к функциям MS Excel ' Программа обращается к одной простой функции объектной библиотеки ' MS Excel для получения значения числа Пи = 3,14 Public Class Forml Private Sub Forml_Load(ByVai sender As System.Object, ByVai e As System.EventArgs) Handles MyBase.Load
158 Гпава 8 ' Создание экземпляра класса Excel.Application Dim xl As Microsoft.Office.Interop.Excel.Application xl = CreateObject("Excel.Application") Dim PI As Double = xl.WorksheetFunction.Pi() ' Выводим значение ПИ в строку заголовка формы Me.Text = "PI = " & PI End Sub End Class Как видно, при обработке события загрузки формы создается объект Excel.Application, с помощью которого имеем доступ, для одной из функций MS Excel, возвращающей число п = 3,14. Результат работы программы показан на рис. 8.4. Рис. 8.4. Вывод числа я в заголовок формы Убедиться в работоспособности программы можно, открыв решение Excel.sln в папке Excel. Пользоваться функциями MS Excel в вашей VB2010-программе очень пер- спективно. Например, оцените возможность решать сложнейшие в математи- ческом смысле оптимизационные задачи (т. е. задачи нахождения максиму- ма/минимума с набором ограничений), доступные в MS Excel через Сервис | Поиск решения. Пример 51. Использование финансовой функции MS Excel Приведем еще один пример обращения к функциям MS Excel из программы на VB2010. Допустим, вы взяли кредит на покупку квартиры 100 тыс. долла- ров под 15% годовых, срок погашения кредита— 10 лет. Требуется узнать, какую сумму вы вынуждены будете платить ежемесячно. В русскоязычном MS Excel для подобных расчетов есть функция пято, на вход которой следу- ет подать месячную процентную ставку (т. е. в нашем случае 0.15/12), срок погашения кредита в месяцах (120 месяцев) и размер кредита ($100 тыс.). Аналогом функции плт (} является объект worksheetFunction, который содер-
Использование функций MS Word, MS Excel, AutoCAD 159 жит функцию Pmt О с такими же аргументами. Таким образом, мы можем на- писать VB2010-программу с обращением к функции Pmt о и проверить ре- зультат в русскоязычной версии MS Excel. Список всех методов (функций) объекта WorksheetFunction с описанием аргументов можно найти по адресу: http://msdn.microsoft.com/en-us/library/bb225774.aspx. Для программирования обращений к этим функциям из VB2010-программы важно найти соответствие русскоязычных функций MS Excel и их аналогов в объекте worksheetFunction для отладки на текстовых примерах. Запустим VB2010, далее закажем новый проект из шаблона Windows Forms Application. В проектируемую экранную форму из панели Toolbox перенесем три метки, три текстовых поля (для ввода трех вышеперечисленных аргумен- тов функции Pmtо) и кнопку. В текущий проект подключаем библиотеку объектов MS Excel. Для этого в меню Project выберем команду Add Reference, затем на вкладке СОМ дважды щелкнем на ссылке Microsoft Excel 11.0 Object Library. Теперь можно перейти к программному коду, при- веденному в листинге 8.4. Листинг 8.4. Использование финансовой функции MS Excel ' Программа использует финансовую функцию Pmt объектной библиотеки ' MS Excel для вычисления суммы периодического платежа на основе ' постоянства сумм платежей и постоянства процентной ставки. ' Добавить пространство имен Imports Microsoft.Office.Interop Public Class Forml Private Sub Forml_Load(ByVai sender As System.Object, ByVai e As System.EventArgs) Handles MyBase.Load Labeli.Text = "Год. ставка в %" Label2.Text = "Срок в месяцах" Label3.Text - "Размер кредита" TextBoxl.Clear () TextBox2.Clear() TextBox3.Clear() Me.TextO = "Расчет ежемесячных платежей" Buttonl.Text() = "Расчет" End Sub Private Sub КНОПКА(ByVai sender As System.Object, ByVai e As System.EventArgs) Handles Buttonl.Click
160 Гпава 8 Try ’ Если проект — Windows Application (не Console ' Application), то создать объект можно так: ' Dim XL As Excel.Application = New Excel.Application ' или коротко: Dim XL = New Excel.Application ' В этом случае CreateObject — не нужно: ' XL = CreateObject("Excel.Application") Dim pay As Double = XL.WorksheetFunction.Pmt( (Convert.ToDouble(TextBoxl.Text)) / 1200, Convert.ToDouble(TextBox2.Text), Convert.ToDouble(TextBox3.Text)) ' ИЛИ ' Dim pay2 As Double = Financial.Pmt( ' (Convert.ToDouble(TextBoxl.Text)) / 1200, ' Convert.ToDouble(TextBox2.Text), ' Convert.ToDouble(TextBox3.Text)) MessageBox.Show("Каждый месяц следует платить " & Format(Math.Abs(pay), "$#.##") & " долларов") Catch ex As Exception MessageBox.Show(ex.Message, "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Exclamation) End Try End Sub End Class Как видно из текста программы, при обработке события загрузки формы Formi Load очищаются (clear) текстовые поля, а также подписываются назва- ния этих полей с помощью меток Label и присваивается название кнопки Buttonl. При обработке события ’’щелчок на кнопке” Расчет создается объект Excel.Application. Замечу, что если мы имеем проект Windows Application, то этот объект можно создать через выражение "New". Объект Excel.Application обеспечивает доступ к функциям MS Excel, в частности к функции Pmtо. На вход функции Pmto подаем значения текстовых полей, конвертированных из строкового типа в тип Double. При этом первый аргу- мент функции переводим из годовой процентной ставки в месячную ставку в сотых долях единицы, поэтому делим на 1200. На выходе функции Pmto по- лучаем размер месячного платежа, который выводим, используя функцию MessageBox.Show.
Использование функций MS Word, MS Excel, AutoCAD 161 Обращение к функциям MS Excel оформляем в блоке Try.. .catch для обра- ботки исключительных ситуаций (Exception). Замечу, что в данной програм- ме мы не предусмотрели диагностику обязательного заполнения всех полей, а также диагностику ввода только числовых данных, чтобы не перегружать текст программы. Интерфейс программы показан на рис. 8.5. 1 К-зт'Дшм следует п.язтить $1613,35 дся-арое Рис. 8.5. Расчет ежемесячных платежей Убедиться в работоспособности программы можно, открыв решение Ехсе13.sin в папке Ехсе13. В данном разделе на простом примере мы рассмотрели, как легко подклю- читься к библиотеке объектов MS Excel и пользоваться ее функциями. Одна- ко функция pmto имеется и в VB2010-классе Financial точно с такими же параметрами (см. комментарий в программном коде). Более того, эта функ- ция была и в VB6, т. е. в данном случае решение этой задачи не является оп- тимальным. Пример 52. Решение системы уравнений с помощью функций MS Excel Используя функции MS Excel, в своей VB2010-программе можно решать и более серьезные задачи. Например, покажем, как решить систему линейных алгебраических уравнений’. Хх+Х2+Х3 = (> х} +х2 = з ^2+^з = 5 через обратную матрицу. 6 Зак 145
162 Гпава 8 Исходную систему уравнений запишем в матричном виде: A -X=L. Здесь А — матрица коэффициентов при неизвестных; X — вектор неизвестныхХ\,Ху, Ху, L — вектор свободных членов 6, 3, 5. Тогда решением системы будет выражение Х=А~1 • L, где А~' — обратная матрица. Для нахождения обратной матрицы в русскоязычной версии MS Excel есть функция мобро, а объект WorksheetFunction в библиотеке объектов Microsoft Excel имеет функцию MinverseO. Для умножения обратной матрицы на век- тор свободных членов есть соответственно функции мпроизо и MMulto. Та- ких функций нет в VB2010, и в данном случае мы получаем реальный поло- жительный эффект от подключения к функциям MS Excel. Для программной реализации решения поставленной задачи запустим VB2010. Далее выбираем новый проект из шаблона Windows Forms Application и щелкаем на кнопке ОК. В проектируемую форму из панели Toolbox добавим метку и растянем ее побольше и симметрично относительно формы. На ней будем формировать ответ задачи. Кроме того, добавим биб- лиотеку объектов MS Excel. Для этого в пункте меню Project выберем команду Add Reference и на вкладке СОМ отметим библиотеку Microsoft Excel 11.0 Object Library, а затем щелкнем на кнопке ОК. Программу построим следующим образом (листинг 8.5): при загрузке формы прямо в тексте программы задаем (инициализируем) прямую матрицу в виде двумерного массива и вектор свободных членов в виде одномерного массива. Затем после решения системы выводим ответ на метку Labeli. ' Листинг 8.5, Решение системы линейных алгебраических уравнений ’ Программа решает систему уравнений с помощью функций объектной ’ библиотеки MS Excel Imports Microsoft.Office.Interop Public Class Forml Private Sub Forml_Load(ByVai sender As System.Object, ByVai e As System.EventArgs) Handles MyBase.Load ’ Центрирование метки Labeli.TextAlign = ContentAlignment.Middlecenter
Использование функций MS Word, MS Excel, AutoCAD 163 ’ Матричное уравнение: AX = L решаем через ’ обратную матрицу: X = A(-1)L ’ Решаем систему ’ XI + Х2 + ХЗ = 6 ’ XI + Х2 =3 ’ Х2 + ХЗ = 5 -’ Для этой системы прямая матрица будет иметь вид Dim А(,) As Double = {{1, 1, 1}Z {1, 1, 0}, {0, 1, 1}} ’ Свободные члены Dim L() As Double = {6, 3f 5} ’ Обратная матрица oA и решение X Dim oA, X As Object ’ Dim xl As Excel.Application = New Excel.Application Dim xl = New Excel.Application ’ xl = CreateObject("Excel.Application") With xl.Application.WorksheetFunction ’ Вычисление детерминанта матрицы A Dim det_A As Double = .MDeterm(A) ’ Если det_A <> 0, to Exit Sub: If Math.Abs(det_A) < 0.01 Then Labeli.Text = "Система не имеет решения, поскольку" & vbCrLf & vbCrLf & "определитель равен нулю" Exit Sub End If ’ Получение обратной матрицы oA = .Mlnverse(A) ' Умножение обратной матрицы‘на вектор свободных членов X = .MMult(oA, .Transpose(L)) End With ТАК НАПИСАТЬ ПРАВОМОЧНО Dim Xl As Double = X(l, 1)
164 Гпава 8 ОТВЕТ Labeli.Text = 'Неизвестные равны: ”Х1 = ”; X2 = ХЗ = & vbCrLf & vbCrLf & & X(l, 1).ToString & & X(2, 1).ToString & & X(3, 1).ToString & End Sub End Class Как видно из текста программы, при обработке события загрузки формы за- даем прямую матрицу, причем присваиваем значения коэффициентов сразу при объявлении двумерного массива. Аналогично поступаем с вектором сво- бодных членов. Согласно требованию объекта worksheetFunction возвращае- мые обратная матрица и вектор неизвестных должны быть объявлены как объектные переменные (Dim оа, х as object). Далее создаем объект х1. Блок with...End with сокращает полные имена. В этом блоке вначале вычисляем детерминант (определитель) прямой матри- цы, используя функцию MS Excel MdetermO. Если прямая матрица плохо обу- словлена, т. е. определитель по абсолютному значению меньше о.01, то выхо- дим из процедуры обработки события Formi_Load и сообщаем пользователю на метку Labeli, что система не имеет решения. Если определитель матрицы больше 0.01, то с помощью функции MS Excel Minverseo находим обратную матрицу. Далее обратную матрицу с помощью функции MS Excel MMuito умножаем на вектор неизвестных, но прежде его следует сделать вертикаль- ным массивом с помощью функции MS Excel Transpose, т. е. транспониро- вать массив L. Следующим оператором форматируем ответ на метку Labeli. Результат работы программы приведен на рис. 8.6. Убедиться в работоспо- собности программы можно, открыв решение Excel5.sln в папке Ехсе15. Рис. 8.6. Решение системы линейных алгебраических уравнений Как видим, довольно сложные задачи можно решать в коротенькой програм- ме благодаря обращению к функциям MS Excel. Причем на компьютере, где будет работать данная программа, вовсе не обязательно должен быть инстал-
Использование функций MS Word, MS Excel, AutoCAD 165 лирован MS Excel. Однако инсталляция вашей программы должна содержать соответствующую DDL-библиотеку. Пример 53. Построение диаграммы средствами MS Excel Очень часто необходимо изобразить на графике (диаграмме) какие-либо эко- номические показатели или технические измерения (геодезические, метро- логические, астрономические), например, с целью принятия каких-либо ре- шений. Часто сделать это надо очень оперативно. Для этих целей в ячейки рабочего листа MS Excel можно ввести измеренные данные, а далее, чтобы получить график, построенный по этим данным, воспользоваться пунктами меню Вставка | Диаграмма. В данном разделе я покажу, как можно очень быстро получить график (диаграмму) из программы VB2010, используя сред- ства (объекты компонентной библиотеки) MS Excel. Запустим VB2010, далее, поскольку экранная форма нам не нужна, выбираем новый проект из шаблона Console Application. Теперь к текущему проекту добавим библиотеку объектов MS Excel. Для этого в пункте меню Project выберем команду Add Reference, потом на вкладке СОМ отметим библиоте- ку Microsoft Excel 11.0 Object Library и щелкнем на кнопке ОК. Затем между строчками sub Main о и End Sub вставим программный код, приведен- ный в листинге 8.6. ' Листинг 8.6. Построение диаграммы средствами MS Excel ’ Программа строит график (диаграмму) средствами объектов ’ компонентной библиотеки MS Excel Module Modulel Sub Main() Dim EA As Object EA = CreateObject("Excel.Application") EA.Workbooks.Add() EA.Range("Al").Value = "Месяц" EA.Range("A2").Value = "Март" EA.Range("A3").Value = "Anp" EA.Range("A4").Value = "Май" EA.Range("A5").Value = "Июнь" EA.Range("A6").Value = "Июль"
168 Гпава 8 ская карта и пр.), то самый быстрый путь создания такого приложения — это обращение к функциям AutoCAD из вашей VB2010-программы. AutoCAD (Computer-Aided Design) — это 2- и 3-мерная система автоматизированного проектирования и черчения. Эта система, также как и пакет приложений Microsoft Office, может являться сервером OLE-объектов, и его функции мо- гут использоваться другими приложениями. Графическими примитивами векторной графики являются отрезки, дуги, ок- ружности, тексты, которые можно выводить под различными углами к гори- зонту, и, может быть, еще некоторые простейшие геометрические фигуры. Чертеж, подлежащий построению, состоит из совокупности таких элементов. VB2010-программа путем обращения к соответствующим функциям AutoCAD формирует такой чертеж и записывает его в DWG-файл. Пользова- тель может просмотреть этот файл в среде AutoCAD, отредактировать его и вывести на печать. Приступаем к программированию поставленной задачи. Как обычно после запуска VB2010, выбираем шаблон Windows Forms Application. Далее сле- дует подключить библиотеку объектов AutoCAD, для этого в пункте меню Project выбираем команду Add Reference, затем на вкладке СОМ дважды щелкнем на ссылке AutoCAD 2000 Object Library. Эта ссылка соответствует файлу ACAD.TLD в соответствующей папке Program Files, где расположен результат инсталляции AutoCAD. Теперь после компиляции проекта в папке obj\x86\Debug появится файл Interop.AutoCAD.dll. Таким образом, мы подключили библиотеку объектов AutoCAD версии 2000. Если на вашем компьютере инсталлирована другая версия AutoCAD, то дей- ствуйте аналогично. Программа, выводящая в DWG-файл два отрезка, а так- же два горизонтально и вертикально ориентированных текста представлена в листинге 8.7. | Листинг 8.7. Построение отрезков и двух строк текста в AutoCAD ’ Программа строит средствами объектов библиотеки AutoCAD ’ элементарный чертеж из отрезков и некоторого текста. ’ Этот чертеж сохраняется в файле формата DWG. Public Class Forml Private Sub Forml_Load(ByVai sender As System.Object, ByVai e As System.EventArgs) Handles MyBase.Load ’ Эта программа запускает AutoCAD 2000i, рисует два отрезка, ’ два текста, сохраняет чертеж в ’ C:\a.dwg и завершает работу AutoCAD.
Использование функций MS Word, MS Excel, AutoCAD 167 диаграммы— 51. Число 51 соответствует гистограмме (столбиковой диа- грамме), а число 66 — графику с маркерами. Устанавливаем источник данных для диаграммы setsourceData, указывая лист, диапазон ячеек и номер ячейки, с которой начинаются значения для по- строения диаграммы. Далее указываем название гистограммы и подписываем горизонтальную и вертикальную оси. Затем с помощью функции Exporto сохраняем полученную диаграмму на диске в виде JPG-файла. Графическое отображение этого файла можно посмотреть на рис. 8.7. Рис. 8.7. Графическое отображение полученного JPG-файла Далее делаем видимой (visible = True) построенную диаграмму на рабочем листе MS Excel. Убедиться в работоспособности программы можно, открыв решение Excel-Grafik.sln в папке Excel-Grafik. Пример 54. Управление функциями AutoCAD из программы на VB2010 Если результатом работы вашей программы должен быть какой-либо вектор- ный чертеж (техническая документация, строительный чертеж, географиче-
166 Гпава 8 EA. Range ("Bl") . Value = "Продажи: ’’ EA.Range("В2").Value = 138 EA.Range("B3").Value = 85 EA.Range("B4").Value = 107 EA.Range("B5").Value = 56 EA.Range("B6").Value = 34 EA.Charts.Add() With EA.ActiveChart ’ Задаем тип графика = 51 — столбчатая диаграмма: .ChartType = 51 ’ Excel.XlChartType.xlColumnClustered() .SetSourceData(EA.Sheets("Лист1").Range("A1:B6"), PlotBy:=2) ’ Отключаем легенду графика: .HasLegend = False ’ Отключаем легенду графика .HasTitle = True .ChartTitle.Characters.Text = "ПРОДАЖИ ЗА ПЯТЬ МЕСЯЦЕВ" ’ Подпись оси х .Axes(l, 1).HasTitle = True .Axes(l, 1).AxisTitle.Characters.Text = ’’Месяцы” ’ Подпись оси у .Axes(2, 1).HasTitle = True .Axes(2, 1).AxisTitle.Characters.Text = "Уровни продаж" ’ Цвет фона графика — белый ’.PlotArea.Interior.Colorindex = ’ Excel.XlColorlndex.xlColorlndexNone .Export("C:\excel.jpg") End With EA.Visible = True End Sub End Module В начале программного кода создаем объект Excel.Application и рабочую книгу. Причем поскольку наш проект мы запроектировали как Console Application, объект Excel. Application мы создаем через выражение CreateObject. Далее заполняем ячейки первого листа: вначале в ячейки А1 пишем подписи ординат гистограммы, а в ячейки В1 — значения ординат. Затем задаем тип
Использование функций MS Word, MS Excel, AutoCAD 169 ' Следует подключить библиотеку объектов AutoCAD ’ Project — Add Reference - вкладка COM — ’ AutoCAD 2000 Object Library - OK ’ Dim AcadApp As AutoCAD.AcadApplication = ' New AutoCAD.AcadApplication Dim AcadApp = New AutoCAD.AcadApplication ’ Также можно создать объект AcadApp таким образом ’ Dim AcadApp As AutoCAD.AcadApplication ’ AcadApp = CreateObject("AutoCAD.Application”) ’ Dim Docs As AutoCAD.AcadDocuments = AcadApp.Documents Dim Docs = AcadApp.Documents ' Dim Doc As AutoCAD.AcadDocument = Docs.Add Dim Doc = Docs.Add ' Видимость AcadApp.Visible = True ’ Точки Dim Tl() As Double = {10, 10, 0} Dim T2() As Double = {200, 200, 0} Dim T3() As Double = {200, 10, 0} Dim T4() As Double = {15, 200, 0} ’ Нарисовать отрезок Doc.ModelSpace.AddLine(Tl, T2) ’ Нарисовать отрезок красным цветом Doc.ModelSpace.AddLine(Т2, T3).Color = AutoCAD.ACAD_COLOR.acRed ’ Горизонтальный текст (с разворотом 0 градусов) Doc.ModelSpace.AddText("Горизонтальный", T4, 22) ' Вертикальный текст с разворотом на 90 град = ПИ/2 Doc.ModelSpace.AddText("Вертикальный", Tl, 22).Rotation = Math.PI / 2 Doc.SaveAs("C:\a.dwg") AcadApp.Quit() End Sub End Class
170 Гпава 8 Как видно из программного кода, весь процесс работы программы про- исходит при загрузке формы FormiLoad. Вначале создается объект AutoCAD.Application, причем его можно создать одним предложением или двумя, как показано в комментарии. Далее создаем коллекцию документов AcadDocuments и открываем (делаем активным) один документ предложением Docs.Add. В комментариях приведены варианты написания команд. Затем задаем видимость работы AutoCAD visible = True, при этом AutoCAD только мелькнет на экране. Замечу, что для конечной цели, т. е. для получе- ния DWG-файла, видимость не обязательна. Далее задаем четыре точки, ко- торые будут участвовать в построении чертежа. Обратите внимание, что каж- дая точка имеет три координаты, хотя мы собираемся строить плоский чер- теж. Третью координату мы будем воспринимать, как напоминание того, что AutoCAD способен строить трехмерные чертежи. Затем рисуем два отрезка AddLine через точки Tl, Т2 и т2, тз. Причем мы пока- зали, как второй отрезок задать красным цветом. Далее подаем команду вы- водить текст горизонтально, потом другой текст — вертикально с разворо- том на 90°, т. е. л/2. Затем, используя метод saveAs, записываем построенный в документе чертеж в DWG-файл на логический диск С:. В результате работы этой программы получаем чертеж в системе AutoCAD, подобный представленному на рис. 8.8. Убедиться в работоспособности программы можно, открыв решение ACADm.sIn в папке ACADm. Рис. 8.8. Отображение полученного DWG-файла в системе AutoCAD
ГЛАВА 9 Обработка баз данных с использованием технологии ADO.NET Пример 55. Создание базы данных SQL Server Покажем, как можно создать базу данных SQL Server в среде Visual Studio. В этой простейшей базе данных будет всего одна таблица, содержащая све- дения о телефонах ваших знакомых, т. е. в этой таблице будем иметь всего три колонки: Имя, Фамилия и Номер телефона. Запускаем VB2010, заказываем новый проект шаблона Windows Forms Ap- plication, задаем имя — BD_sdf_2. Далее непосредственно создаем новую базу данных SQL Server. Для этого в пункте меню Project выбираем команду Add New Item (т. е. создать новый элемент) и в появившемся одноименном окне выбираем шаблон Local Database (локальная база данных), указываем имя файла (в поле Name) vicl.sdf и последовательно щелкаем на кнопках Add, Next, Finish. Теперь добавляем таблицу в базу данных, для этого в пункте меню View вы- бираем команду Server Explorer (Обозреватель баз данных). В обозревателе баз данных развернем узел (щелкнем знак треугольника) vicl.sdf и выберем Tables (Таблицы). Щелкнем правой кнопкой мыши пункт Tables, а затем выберем пункт Create Table (Создать таблицу). Откроется окно New Table. Назовем новую таблицу (поле Name) БД телефонов. Заполним структуру таблицы, как показано на рис. 9.1. Нажмем кнопку ОК, чтобы создать таблицу и закрыть окно New Table. Чтобы исключить повторяющиеся записи (т. е. строки в таблице), следует назначить первичные ключи (или ключевые столбцы). Ключевым столбцом
172 Гпава 9 назначают столбец в таблице, который всегда содержит уникальные (непо- вторяющиеся в данной таблице) значения. Однако в нашей таблице могут быть люди с одинаковыми именами или одинаковыми фамилиями, т. е. в на- шей таблице в качестве первичных ключей следует использовать одновре- менно два столбца: столбец Имя и столбец Фамилия. Представьте себе, что у нас уже есть сотни записей в таблице, и при попытке ввести вторую строку, содержащую то же самое значение, появляется сообщение об ошибке. Это очень технологично, удобно! Рис. 9.1. Формирование структуры новой таблицы Чтобы добавить первичные ключи, в таблицу в Server Explorer развернем узел Tables, далее щелкнем правой кнопкой мыши на нашей только что соз- данной таблице и выберем пункт Edit Table Schema, затем для полей Имя и Фамилия укажем для параметра Allow Nulls значение No, т. е. обяжем наше- го пользователя всегда заполнять эти поля (ячейки таблицы). Далее для пара- метра Unique (Являются ли эти поля уникальными?) ответим No, поскольку и имена, и фамилии повторяются. И, наконец, назначим колонки Имя и Фами- лия первичными ключами (Primary Key — Yes). Нажмем кнопку ОК для со- хранения этих настроек и закрытия окна Edit Table — БД телефонов. Теперь добавим данные в таблицу. Для этого в окне Server Explorer щелкнем правой кнопкой мыши на пункте БД телефонов и выберем команду Show Table Data. Откроется окно данных таблицы, как показано на рис. 9.2, но только пока пустое. Далее заполняем данную таблицу. Для нашей демонстрационной цели введем пять строчек в данную таблицу. После ввода в меню File выберите команду Save АП для сохранения проекта и базы данных. Теперь убедитесь, что в пап- ке проекта появился файл vic2.sdf. Его можно открыть вне проекта с по- мощью Microsoft Visual Studio 2010 для редактирования базы данных.
Обработка баз данных с использованием технологии ADO.NET 173 Рис. 9.2. Заполнение ячеек таблицы Пример 56. Отображение таблицы базы данных SQL Server в экранной форме Имея базу данных, например базу данных SQL Server, в виде файла vic2.sdf, созданного в предыдущем разделе, покажем, как очень легко можно вывести таблицу из этой базы в экранную форму. Для этой цели запустим VB2010, закажем новый проект шаблона Windows Application и укажем имя проекта— BD_sdf_3. Далее в пункте меню View выберем команду Server Explorer. Щелкнув правой кнопкой мыши на значке Data Connection, добавим соединение — Add Connection, а в качест- ве источника данных Data source укажем Microsoft SQL Server Compact 3.5 и щелкнем на кнопке Continue. Далее, нажмем кнопку Browse, найдем соз- данный в прошлом проекте файл базы данных vic2.sdf и нажмем кнопку ОК. Теперь в окне Server Explorer мы видим значок базы данных vic2.sdf. Далее в пункте меню Data выберем команду Add New Data Source, тем са- мым мы запустим мастер Data Source Configuration Wizard. Здесь последо- вательно нажимаем кнопки Next, Dataset, Next. На запрос мастера, копиро- вать ли файл vic2.sdf в наш текущий проект, нажмем кнопку Да. В результате в окне Solution Explorer появится значок базы данных vic2.sdf и значок объекта vic2DataSet.xsd, но база данных в текущем проекте будет пус- той. Для заполнения базы данных в пункте меню Data укажем Show Data Source и в появившемся окне Data Source, щелкая правой кнопкой мыши
174 Гпава 9 значок vic2DataSet, выберем пункт Configure Data Source With Wizard — Finish. Теперь из окна Server Explorer перетащим узел БД телефонов на появившуюся вкладку vic2DataSet.xsd. Затем из окна Data Source перетащим узел БД телефонов на вкладку конструктора формы Forml.vbfDesign]. Как видно из рис. 9.3, автоматически появилось несколько программных объек- тов, необходимых для отображения данных из таблицы базы данных. Рис. 9.3. Проект формы с объектами для отображения таблицы базы данных Заметьте, мы пока не написали ни одной строчки программного кода. Теперь стартуем отладку программы — нажимаем клавишу <F5>. Как видим (рис. 9.4), в форме благодаря элементам управления DataGrid- View и BindingNavigator появилось отображение таблицы из базы данных. Мы имеем возможность модифицировать существующие записи (строки), добавлять новые записи (New), удалять записи из таблицы (Delete), сохранять данные (Save Data) с помощью соответствующих кнопок. То есть имеем пол- ный набор основных четырех функций по редактированию таблицы базы данных. Убедиться в работоспособности данной программы можно, открыв файл ре- шения BD_sdf_3.sln в папке BD_sdf_3. Обратите внимание на то, что копия исходной базы данных vic2.sdf находится в папке проекта bin\Debug, именно
Обработка баз данных с использованием технологии ADO.NET 175 этот файл претерпевает изменения при редактировании таблицы в данном проекте. Рис. 9.4. Фрагмент работы программы Пример 57. Создание базы данных в среде MS Access Вначале создадим базу данных (БД) vic.mdb средствами Access пакета MS Office. Поясню сразу, что реальный положительный эффект от решения ка- кой-либо задачи информатизации с использованием баз данных можно ощу- тить, если количество записей (т. е. количество строк в таблице) превышает 100 тысяч. В этом случае очень важным (решающим) фактором оказывается скорость выборки. Однако для примера работы мы будем оперировать совсем маленькой БД. Чтобы читатель данной книги смог реально повторить наши действия, созда- дим базу данных телефонов ваших контактов. Структура (поля) таблицы бу- дет следующей: Номер п/п, ФИО и Номер телефона. Для этого запускаем на компьютере офисное приложение Microsoft Access, далее в пункте меню Создать (или <Ctrl>+<N>) выбираем команду Новая база данных, задаем папку для размещения БД и имя файла — vic.mdb. Затем в появившемся окне vic: база данных выберем команду Создание таблицы в режиме конструк- тора. Далее задаем три поля (т. е. три колонки в будущей таблице): имя пер- вого поля — Номер п/п, тип данных — Счетчик; следующее имя поля — ФИО, тип данных— Текстовый; третье имя поля — Номер телефона, тип данных — Текстовый. При сохранении структуры таблицы появится запрос на имя таблицы, ука- жем: БД телефонов. В БД может быть несколько таблиц, а данную таблицу мы назвали именно так. Заметьте, что, работая в обычных приложениях, если
176 Гпава 9 вы решили отказаться от внесенных изменений в документе, то его просто закрывают без сохранения. Однако при работе с БД все изменения сохраня- ются на диске без нашего ведома. Запись на диск происходит напрямую, ми- нуя операционную систему. Далее двойной щелчок в пределах созданной таблицы — и приступаем к ее заполнению. В нашем примере в таблице всего семь записей (рис. 9.5). Рис. 9.5. Заполнение таблицы базы данных в среде MS Access Теперь закроем БД Access и откроем созданную нами таблицу БД vic.mdb в среде VB2010. Пример 58. Редактирование таблицы базы данных MS Access в среде Visual Studio без написания программного кода Запускаем VB2010, однако далее мы не заказываем новый проект. Сейчас наша цель — открыть созданную нами базу данных в среде VB2010. Для это- го выбираем пункт меню View | Server Explorer. Здесь щелкнув правой кнопкой мыши на значке Data Connections, выберем пункт Add Connection и укажем в качестве источника данных (Data source), нажав кнопку Change, Microsoft Access Database File (OLE DB). Далее с помощью кнопки Browse зададим путь и имя БД, например, C:\vic.mdb. Теперь проверяем подключе-
Обработка баз данных с использованием технологии ADO.NET 777 ние — кнопка Test Connection. Успешное подключение выдаст сообщение, представленное на рис. 9.6. Рис. 9.6. Тестирование подключения Проверка подключения выполнена, щелкаем на кнопке ОК. Теперь в окне Server Explorer раскроем узлы, символизирующие базу данных, таблицы, поля в таблице. Далее щелкнем правой кнопкой мыши на узле БД телефонов и выберем команду Retrieve Data. В результате в правом окне получим содержимое этой таблицы, как показано на рис. 9.7. Здесь данную таблицу мы можем ре- дактировать, т. е. изменять содержимое любой записи (Update), добавлять новые записи (Insert), т. е. новые строки в таблицу, удалять записи (Delete). Кроме того, щелкая правой кнопкой мыши в пределах таблицы и выбирая в контекстном меню пункты Pane | SQL, можно осуществлять SQL-запросы к базе данных, в том числе наиболее часто используемый запрос Select. Рис. 9.7. Редактирование таблицы базы данных в среде Visual Studio
178 Гпава 9 Пример 59. Отображение таблицы базы данных MS Access в экранной форме Поставим задачу вывода таблицы базы данных MS Access в экранную форму с возможностью редактирования базы данных, как мы это сделали для базы данных SQL Server. Разница будет состоять лишь в том, что мы не будем ко- пировать базу данных в наш проект, а подключимся к существующей базе данных. Сразу скажем, что данная задача решается аналогично. Запустим VB2010 и закажем новый проект шаблона Windows Forms Application, укажем имя проекта— BD_mdb. Откроется новый проект Windows Forms. В пункте меню Data (Данные) щелкнем пункт Add New Data Source, при этом запустится Data Source Configuration Wizard (Мастер настройки источников данных). Выберем Database (База данных) и нажмем кнопку Next. Далее после выбора модели Dataset и нажатия кнопки Next на- жимаем кнопку New Connection (Новое подключение). Откроется диалоговое окно Add Connection (Добавить подключение). В этом диалоговом окне проверяем, является ли источник данных (Data source) Microsoft Access Database File (OLE DB). Если нет, то нажимаем кнопку Change и выбираем Microsoft Access Database File в диалоговом окне Change Data Source, а затем нажимаем кнопку OK. Щелкнув на кнопке Browse, переходим в место сохранения базы данных vic.mdb, далее щелкнем на значке файла базы данных и на кнопке Открыть. Нажмем кнопку ОК, чтобы закрыть диалоговое окно Add Connection, затем в мастере настройки источников данных нажмем кнопку Next. Если будет предложено копировать файл данных в проект, нажмите кнопку Нет. Опять нажмите кнопку Next. На следующей странице мастера необходимо установить флажок возле всех объектов базы данных, при этом имя объекта DataSet будет vicDataSet. Нажимаем кнопку Finish для продолжения. Пере- ходя в пункт меню Data | Show Data Sources получим в окне Data Sources узлы объектов базы, показанные на рис. 9.8. Теперь перетащим узел БД телефонов из окна Data Source в проект экран- ной формы. При этом некоторые элементы управления автоматически доба- вятся в форму, также будут созданы некоторые компоненты и добавлены в область компонентов под формой. Появится элемент управления DataGridView, который будет отображать строки и столбцы таблицы, и эле- мент управления для переходов (AddressesBindingNavigator). Кроме того, система создает компоненты, которые подключаются к базе данных, управ- ляют извлечением и обновлением данных и хранят данные в локальном объекте DataSet (AddressesBindingSource, AddressesTableAdapter и FirstDatabaseDataSet соответственно).
Обработка баз данных с использованием технологии ADO.NET 179 Рис. 9.8. Узлы объектов базы данных Нажмем клавишу <F5> для запуска приложения. Данные из таблицы телефо- нов отображаются в элементе управления DataGridView в форме, как пока- зано на рис. 9.9. Рис. 9.9. Отображение таблицы на элементе управления DataGridView Можно использовать элементы управления в BindingNavigator в верхней части формы для перехода между строками, можно даже добавлять или уда- лять записи. Можно также изменять записи, изменяя данные, отображаемые в сетке, но эти изменения не будут сохранены до тех пор, пока не будет нажата кнопка сохранения (Save Data). Как видите, мы не написали ни одной строчки программного кода. Среда VB2010 автоматически сгенерировала программный код для управления
180 Гпава 9 представляемой программой. Этот программный код можно просмотреть, открыв файл проекта Forml.Designer.vb. Убедиться в работоспособности программы можно, открыв файл решения BDmdb.sln в папке BDmdb. Пример 60. Чтение всех записей из таблицы БД MS Access на консоль с помощью объектов Command и DataReader Напишем программу, которая минимальным количеством строк программно- го кода выводит на экран все записи (т. е. все строки) таблицы базы данных. При этом воспользуемся наиболее современной технологией ADO.NET. Тех- нология ADO.NET — это преимущественно 4 объекта. Объект Connection обеспечивает соединение с базой данных. Объект command обеспечивает при- вязку SQL-выражения к соединению с базой данных. А с помощью объектов DataSet И DataReaders МОЖНО просмотреть результаты запроса. Здесь и далее мы рассмотрим четыре основных действия над базой данных: select (выборка записей из таблицы БД), insert (вставка записей), update (модификация записей в таблице БД), Delete (удаление некоторых записей из таблицы). Для этого запустим VB2010 и щелкнем на пункте New Project. Форма нам в данном случае не нужна, поэтому выбираем шаблон Console Application. Мы хотим вывести на экран простейшим способом таблицу. Если мы будем вы- водить ее при ПОМОЩИ функции MessageBox.Show, ТО рОВНЫХ КОЛОНОК В окне MessageBox.Show мы не получим, поскольку буквы, реализованные в этой функции, имеют разную ширину. Обычно в этом случае для вывода таблиц используют шрифт Courier New ИЛИ Consolas, НО объект MessageBox не содер- жит возможностей смены шрифта (также как и MsgBox). Поэтому, идя по са- мому короткому пути, выводим таблицу из базы данных на консоль, т. е. на черный экран DOS. Здесь реализован моноширинный шрифт, где все симво- лы имеют одинаковую ширину. Например, буква "LU" и символ (точка) имеют одинаковую ширину, следовательно, колонки в построенных таблицах будут ровными. Теперь на вкладке ModuleLvb напишем текст программы из листинга 9.1. ' Программа читает все записи из таблицы БД MS Access на консоль * с помощью объектов Command и DataReader. Imports System.Data
Обработка баз данных с использованием технологии ADO.NET 181 Module Modulel Sub Main() ' Создаем объект Connection и передаем ему строку соединения Dim CONNECTION As New OleDb.OleDbConnection( "Data Source=""C:\vic.mdb"";User " & "ID=Admin;Provider=""Microsoft.Jet.OLEDB.4.0"";") CONNECTION.Open() ' Создаем объект Command, передавая ему SQL-команду Dim COMMAND As New О1ёОЬ.OleDbCommand("Select" & " * From [БД телефонов]", CONNECTION) ' Dim COMMAND As New OleDb.OleDbCommand("Select" & ’ " * From [БД телефонов] order by ФИО", CONNECTION) ’ Dim COMMAND As New OleDb.OleDbCommand("Select" & ' " * From [БД телефонов] ORDER BY ’Номер п/п'", ' CONNECTION) ' Выполняем SQL-команду: Dim DATAREADER As OleDb.OleDbDataReader = COMMAND. ExecuteReader(CommandBehavior.CloseConnection) Console.WriteLine("Таблица БД:" & vbCrLf) While DATAREADER.Read() = True ' reader.FieldCount — кол-во полей в строке ' Здесь три поля: 0, 1 и 2: ’ Минус прижимает строку влево: Console.WriteLine(String.Format( "{0,-3} {1,-15} {2,-15}", DATAREADER.GetValue(0), DATAREADER.GetValue(1), DATAREADER.GetValue(2))) End While DATAREADER.Close() : CONNECTION.Close() Console.Read() ' Читает след, символ co стандартного ввода End Sub End Module Как видно, вначале создаем объект Connection и передаем ему строку соеди- нения. В строке соединения полный доступ к MDB-файлу заключен в двой- ные кавычки. Это сделано для того, чтобы корректно читались длинные име- на папок и файлов, содержащие пробелы.
182 Гпава 9 Далее создаем объект command и передаем ему простейшую SQL-команду: Select * From [БД телефонов] То есть выбрать все записи из таблицы [БД телефонов]. Название таблицы в SQL-запросе заключено в квадратные скобки из-за пробела в имени таблицы. Заметьте, что в комментарии указаны возможные варианты SQL-запроса: сортировать записи по колонке ФИО (order by фио) и по колонке (order by ’Номер п/п’). Затем, используя объект DataReader, выполняем SQL-команду. В коммента- рии указано, что при этом можно было бы закрыть соединение closeconnection. Далее в цикле построчно читаем таблицу базы данных. При работе DataReaders в памяти хранится только одна строка (запись) данных. Объект DataReaders имеет булеву функцию Read, которая возвращает True, если существует следующая строка данных, и False, если такие строки уже исчерпались. Причем с помощью DataReaders невозможно заранее узнать ко- личество записей в таблице. Результат работы программы показан на рис. 9.10. Рис. 9.10. Отображение таблицы базы данных на консоли Таким образом, мы получили простейшую программу для просмотра табли- цы базы данных. С ее помощью можно только просматривать данные, но нельзя их редактировать. Убедиться в работоспособности программы можно, открыв решение DataReaderBDl.sIn в папке DataReaderBDl. Пример 61. Создание БД MS Access в программном коде Создадим программу, которая во время работы создает базу данных Access, т. е. файл new_BD.mdb. Эта база данных будет пустой, т. е. она не будет со-
Обработка баз данных с использованием технологии ADO.NET 183 держать ни одной таблицы. Наполнять базу данных таблицами можно будет впоследствии как из программного кода VB2010, так и используя MS Access. В этом примере технология ADO.NET не использована. Запускаем VB2010 (загрузочный модуль devenv.exe), щелкаем пункт меню New Project и выбираем шаблон Console Application. В результате на вклад- ке программного кода Modulel.vb получаем строчки sub Main о и End sub. Между ними пишем программный код, приведенный в листинге 9.2. ; Листинг 9.2. Создание БД во время работы программы ’ Программа создает базу данных MS Access, т. е. файл new_BD.mdb. ’ Эта база данных будет пустой, т. е. не будет содержать ни одной ’ таблицы. Наполнять базу данных таблицами можно будет впоследствии ’ как из программного кода VB2010, так и используя MS Access. ’ В этом примере технология ADO.NET не использована. Module Modulel ’ Для добавления ADOX: Project — Add Reference — вкладка COM - ’ Microsoft ADO Ext. 2.8 for DDL and Security Sub Main() Dim cat As New ADOX.Catalog Try cat.Create(”Provider=Microsoft.Jet.” & "OLEDB.4.0;Data Source=C:\new_BD.mdb”) MessageBox.Show("База данных C:\new_BD.mdb успешно создана”) Catch Ex As Runtime.InteropServices.COMException MessageBox.Show(Ex.Message) Finally cat = Nothing End Try End Sub End Module Для добавления в наш проект DLL-библиотеки ADOX выполним следующее. В пункте меню Project выберем команду Add Reference, затем на вкладке СОМ дважды щелкнем на ссылке Microsoft ADO Ext. 2.8 for DDL and Security, тем самым мы добавляем эту библиотеку в текущий проект. Убе- диться в том, что теперь существует ссылка на эту библиотеку, можно, вы- брав в меню Project пункт Console Application! Properties и на вкладке References среди ссылок References обнаружив ссылку Interop.ADOX.dll. Теперь мы можем ссылаться на это имя в программном коде.
184 Гпава 9 Далее, чтобы во время выполнения программы не появлялось черное окно DOS, в пунктах меню Project | ConsoleApplicationl Properties на вкладке Application в раскрывающемся списке Application type выберем Windows Forms Application. Чтобы был доступен объект MessageBox для вывода сообщений (хотя для вывода сообщений пользователю можно воспользо- ваться функцией MsgBox из VB6), добавим в проект еще одну DLL- библиотеку. Для этого, как и в предыдущем случае, укажем пункты меню Project | Add Reference и на вкладке .NET дважды щелкнем ссылку System.Windows.Forms.dll, а в тексте программы выше строки Module Moduiei напишем: Imports System.Windows.Forms Теперь эту библиотеку можно увидеть на вкладке Project | ConsoleAppli- cationlProperties | References. Ключевое слово imports используется для им- портирования пространства имен, которое содержит класс MessageBox. Программа работает следующим образом: создаем экземпляр класса adox.catalog, одна из его функций Create способна создавать базу данных, если на ее вход подать строку подключения. Заметим, что в строку подклю- чения входит также и полный путь к создаваемой БД. Функция Create заклю- чена в блоки Try.. .Catch, которые обрабатывают исключительные ситуации. После запуска этого приложения получим сообщение о создании базы дан- ных (рис. 9.11). Если тут же запустим наше приложение еще раз, то получим сообщение о том, что такая база данных уже существует (рис. 9.12), поскольку БД new_BD.mdb только что создана. Рис. 9.11. Сообщение о создании базы данных Рис. 9.12. База данных существует Данное сообщение генерировалось обработчиком исключительной ситуации. Программный код этой программы можно посмотреть, открыв решение Sozd_BD2.sln в папке Sozd_BD2.
Обработка баз данных с использованием технологии ADO.NET 185 Пример 62. Запись структуры таблицы в пустую БД MS Access. Программная реализация подключения к БД Здесь и далее мы используем только самую современную технологию ADO.NET. Создадим программу, которая записывает структуру таблицы, т. е. "шапку" таблицы, в существующую БД. В этой БД может еще не быть ни од- ной таблицы, т. е. БД может быть пустой. Либо в БД могут уже быть табли- цы, но название новой таблицы должно быть уникальным. Создадим БД sib.mdb в корневом каталоге логического диска С:, используя MS Access, или программным путем, как это было показано в предыдущем разделе. Никакие таблицы в БД создавать не станем, т. е. будем иметь пустую БД. Теперь запустим VB2010, затем выберем пункт New Project. Далее, по- скольку для этого приложения нам не нужна экранная форма с ее элементами управления, укажем среди шаблонов Console Application. Затем напишем программный код, указанный в листинге 9.3. Листинг 9.3. Создание таблицы в БД MS Access ’ Программа записывает структуру таблицы в пустую базу данных ’ MS Access. Программная реализация подключения к БД. В этой БД ’ может еще не быть ни одной таблицы, т. е. БД может быть пустой. ’ Либо в БД могут уже быть таблицы, но название новой таблицы ’ должно быть уникальным. Imports System.Data.OleDb Imports System.Windows.Forms Module modulel ’ ЗАПИСЬ СТРУКТУРЫ ТАБЛИЦЫ В ПУСТУЮ БД: Sub Main () ’ Создание экземпляра объекта Connection ' с указанием строки подключения: ’ Dim CONNECTION As OleDbConnection = ’ New OleDbConnection("Provider=Microsoft.” & ’ ”Jet.OLEDB.4.0;Data Source=C:\new_BD.mdb”) или короче: Dim CONNECTION = New OleDbConnection(”Provider=Microsoft." & ”Jet.OLEDB.4.0;Data Source=C:\new_BD.mdb”) ’ Открытие подключения: CONNECTION.Open()
186 Гпава 9 ' Создание экземпляра объекта Command ’ с заданием SQL-запроса: Dim COMMAND As New 01eDbCommand("CREATE TABLE [" & "БД телефонов] ([Номер п/п] counter, [ФИО] ch" & "ar(20), [Номер телефона] char(20))", CONNECTION) Try ’ Выполнение команды SQL: COMMAND.ExecuteNonQuery() MessageBox. Show("Структура таблицы ’БД телефонов’ записана в пустую БД") Catch ex As Exception MessageBox.Show(ex.Message) End Try CONNECTION.Close() End Sub End Module Чтобы работала функция MessageBox.Show, следует в текущий проект доба- вить ссылку на DLL-библиотеку. Для этого в пункте меню Project выберем команду Add Reference и на вкладке .NET дважды щелкнем на ссылке System.Windows.Forms.dll. Кроме того, используя пункты меню Project | ConsoleApplicationl Properties, на появившейся вкладке Application в рас- крывающемся списке Application type выберем тип приложения Windows Forms Application. Как видно из текста программы, вначале создаем экземпляр объекта Connection с указанием строки подключения. Теперь мы имеем возможность управлять этой строкой программно. Далее создаем экземпляр объекта Command с заданием SQL-запроса. В этом запросе создаем (create) новую таб- лицу с именем БД телефонов с тремя полями: Номер п/п типа счетчик (counter), ФИО и Номер телефона. Здесь имя таблицы и имена полей за- ключены в квадратные скобки, поскольку они содержат пробелы. Чтобы ВЫПОЛНИТЬ эту SQL-команду, вызываем метод ExecuteNonQuery, кото- рый заключим в блоки Try.. .Catch для обработки исключительных ситуаций. Если SQL-запрос благополучно выполнился, то получаем сообщение: "Структура таблицы 'БД телефонов' записана в пустую БД". А если, напри- мер, таблица с таким именем уже имеется в базе данных, то управление пере- дается блоку catch (перехват исключительной ситуации), и мы получаем со- общение о том, что такая таблица базы данных уже существует (рис. 9.13). Таким образом, в данной программе сначала организовано подключение Connection к БД через строку подключения и открытие подключения Open. Затем задание SQL-запроса в объекте command и выполнение запроса функци-
Обработка баз данных с использованием технологии ADO.NET 187 ей ExecuteNonQuery. Если связывание данных организовать программно, то добиваемся более высокой гибкости, когда, например, на стадии разработки неизвестно заранее, где (на каком диске, в какой папке) будет находиться БД. Убедиться в работоспособности программы можно, открыв решение Connect.sln в папке Connect. Рис. 9.13. Сообщение о существовании таблицы Пример 63. Добавление записей в таблицу базы данных MS Access Совсем маленькую программу из предыдущего раздела можно использовать для выполнения любого запроса к базе данных. Например, модифицируем всего лишь одну строчку программного кода программы из предыдущего примера для добавления новой записи в таблицу БД. Для этого при создании экземпляра объекта command зададим SQL-запрос на вставку (insert) новой записи в таблицу БД. Заметим, что в SQL-запросе мы сознательно обратились к таблице по имени [бд телефонов], т. е. со строчной буквы, хотя надо с прописной. Дело в том, что в именах таблиц следует точно указывать регистр символа, поскольку их поиск ведется с учетом регистра (case-sensitive search). Однако это не обяза- тельно при наличии только одной таблицы с таким именем, поскольку при этом используется поиск без учета регистра (case-insensitive search). Свойству Connection объекта command следует дать ссылку на объект Connection: COMMAND.Connection = CONNECTION Причем для добавления записи в таблицу БД такая ссылка обязательна в от- личие от предыдущего примера, где мы создавали новую таблицу в сущест- вующей БД. Программный код будет выглядеть так, как представлено в листинге 9.4.
188 Гпава 9 Листинг 9.4. Добавление записей в таблицу базы данных MS Access ’ Программа добавляет запись в таблицу базы данных MS Access. Для этого ’ при создании экземпляра объекта Command задаем SQL-запрос ' на вставку (Insert) новой записи в таблицу базы данных. Imports System.Data.OleDb Imports System.Windows.Forms Module Modulel ’ ДОБАВЛЕНИЕ ЗАПИСИ В ТАБЛИЦУ БД: Sub Main() ’ Создание экземпляра объекта Connection ’ с указанием строки подключения: Dim CONNECTION = New OleDbConnection("Provider=Microsoft." & "Jet.OLEDB.4.0;Data Source=C:\new_BD.mdb”) ’ Открытие подключения: CONNECTION.Open() ’ Создание экземпляра объекта Command с заданием SQL-запроса: Dim COMMAND = New 01 eDbCommand("INSERT INTO [бд телефонов] (’’ & "Фио, [номер телефона]) VALUES ('Света-Х', ’521-61-41’)") ’ Для добавления записи в таблицу БД эта команда обязательна: COMMAND.Connection = CONNECTION ’ Выполнение команды SQL: COMMAND.ExecuteNonQuery() MessageBox.Show(’’В таблицу 'БД телефонов' добавлена запись") CONNECTION.Close() End Sub End Module Часто, отлаживая программный код на VB2010 (равно как и в других версиях VB), при работе с БД появляется необходимость проверки работы програм- мы, например, создалась ли таблица в БД, добавилась ли запись в таблице БД, правильно ли сформирован SQL-запрос. Не обязательно запускать MS Access, чтобы выполнить SQL-запрос или проверить правильность его синтаксиса. Это можно сделать в среде VB. Для этого в пункте меню View выбираем команду Server Explorer (Обозреватель баз данных), далее в списке подключений указываем полный путь к нужной БД. Затем, щелкая правой кнопкой мыши на значке нужной таблицы, в контекстном меню вы-
Обработка баз данных с использованием технологии ADO.NET 189 бираем пункт Retrieve Data. При этом в панели инструментов (Toolbar) по- является значок SQL, после щелчка по этому значку (или нажатия комбина- ции клавиш <Ctrl>+<3>) получим окно SQL-запроса. В этом окне мы можем задавать SQL-запрос, а затем, например, щелкая правой кнопкой мыши, либо проверять его синтаксис, либо выполнять. Убедиться в работоспособности программы можно, открыв решение WritrelnBD.sIn в папке WritrelnBD. Пример 64. Чтение всех записей из таблицы БД с помощью объектов Command, DataReader и элемента управления DataGridView Покажем, как легко, малой кровью, можно вывести таблицу базы данных на элемент управления DataGridView (сетка данных, т. е. таблица данных) с использованием тех же объектов из предыдущей программы command и DataReader. Замечу, что в предыдущих версиях VB, в частности VB.NET, элементом управления для вывода данных на сетку был DataGrid с похожи- ми свойствами и методами. Для решения этой задачи запустим VB2010, закажем новый проект New Project шаблона Windows Forms Application. Из панели Toolbox добавим в проектируемую форму элемент управления DataGridView и растянем его на всю форму. При обработке события загрузки формы Formi Load напишем программный код, представленный в листинге 9.5. ’ Программа читает все записи из таблицы базы данных с помощью ’ объектов Command, DataReader и элемента управления DataGridView Imports System.Data.OleDb Public Class Forml Private Sub Forml_Load(ByVai sender As Object, ByVai e As System.EventArgs) Handles MyBase.Load ' Создаем объект Connection и передаем ему строку соединения: Dim CONNECTION As New OleDbConnection( "Data Source=””C:\vic.mdb””;User ” & ”ID=Admin; Provider=”"Microsoft. Jet. OLEDB. 4.0’”’; ”) CONNECTION.Open()
190 Гпава 9 ’ Создаем объект Command, передавая ему SQL-команду Dim COMMAND As New System.Data.OleDb.OleDbCommand( "Select * From [БД телефонов]”, CONNECTION) ’ Выполняем SQL-команду Dim DATAREADER As OleDbDataReader = COMMAND. ExecuteReader ’(CommandBehavior.Closeconnection) Dim DATATABLE As New DataTable ’ Заполнение шапки таблицы DATATABLE. Columns . Add (DATAREADER. GetName (0) ) DATATABLE. Columns . Add (DATAREADER. GetName (1) ) DATATABLE. Columns . Add (DATAREADER. GetName (2) ) While DATAREADER.Read() = True ’ Заполнение клеток (ячеек) таблицы DATATABLE.Rows.Add(New String() {DATAREADER.GetValue(0), DATAREADER.GetValue(1), DATAREADER.GetValue(2)}) ’ Здесь три поля: 0, 1 и 2 End While DATAREADER.Close() : CONNECTION.Close() DataGridViewl.DataSource = DATATABLE End Sub End Class Как видно из программы, она очень похожа на предыдущую. После выполне- ния SQL-команды создаем объект DataTable, который в конце программного кода (см. предпоследнюю строку) задаем как источник (Datasource) для сетки данных DataGridViewl. Заполняем "шапку” таблицы, т. е. названия колонок, МеТОДОМ Add. Далее, как и в предыдущей программе, в цикле while заполняем ячейки таб- лицы. Фрагмент работы программы показан на рис. 9.14. В этой таблице мы можем сортировать записи по любой из колонок, щелкая мышью на названиях соответствующих колонок. Можем редактировать (изменять) содержание ячеек, но в базу данных эти изменения не попадут (сохранения не будет). Одно из ключевых преимуществ использования объекта DataReader — это его скорость и небольшое использование памяти. Однако применение цикличе- ского считывания данных сводит эти преимущества на нет. Убедиться в работоспособности программы можно, открыв решение DataReaderBD2.sln в папке DataReaderBD2.
Обработка баз данных с использованием технологии ADO.NET 191 Рис. 9.14. Отображение таблицы базы данных на элементе DataGridView Пример 65. Чтение данных из БД в сетку данных DataGridView с использованием объектов Command, Adapter и DataSet Рассмотрим пример чтения таблицы с помощью объекта Adapter из базы дан- ных посредством выбора нужных данных и передачи их объекту DataSet. Очень удобно прочитать таблицу, записанную в DataSet, используя элемент управления DataGridView (сетка данных, т. е. таблица данных), указав в ка- честве источника данных для сетки DataGridView объект DataSet: DataGridViewl.DataSource = DATASET Поскольку нам нужен элемент управления DataGridView, мы создаем новый проект с экранной формой. Для этого, как обычно, запускаем VB2010, зака- зываем новый проект New Project шаблона Windows Forms Application. Из панели Toolbox добавляем в форму элемент управления DataGridView и рас- тягиваем его на всю форму, как показано на рис. 9.15. Далее при обработке события загрузки формы Formi_Load пишем программ- ный код, представленный в листинге 9.6. ; Листинг 9.6, Чтение данных из БД в сетку данных DataGridView ’ Программа читает из БД таблицу в сетку данных DataGridView с ’ использованием объектов Command, Adapter и DataSet Imports System.Data.OleDb
192 Гпава 9 Public Class Forml Private Sub Forml_Load(ByVai sender As Object, ByVai e As System.EventArgs) Handles MyBase.Load Me.Text = "Чтение таблицы из БД:" Dim CONNECTION As New OleDbConnection( "Data Source=””C:\vic.mdb”User ” & ”ID=Admin;Provider=”"Microsoft.Jet.OLEDB.4.0"";") CONNECTION.Open() Dim COMMAND As New System.Data.OleDb.OleDbCommand( "Select * From [БД телефонов]", CONNECTION) ’ Dim COMMAND As New OleDbCommand("SELECT * FRO" & ’ "M [БД телефонов] WHERE (фио LIKE ’м%’)", CONNECTION) ’ Создаем объект Adapter и выполняем SQL-запрос Dim ADAPTER As New OleDbDataAdapter(COMMAND) ’ Создаем объект DataSet Dim DATASET As New DataSet ' Заполняем DataSet результатом SQL-запроса ADAPTER.Fill(DATASET, "БД телефонов") DataGridViewl.DataSource = DATASET DataGridViewl.DataMember = "БД телефонов" CONNECTION.Close() End Sub End Class Рис. 9.15. Проектирование экранной формы
Обработка баз данных с использованием технологии ADO.NET 193 Как видно из текста программы, вначале создаем объект Connection, переда- вая строку подключения. Затем, создавая объект command, задаем SQL- команду выбора всех записей из таблицы БД телефонов. Здесь мы можем задать любую SQL-команду, в комментарии приведен пример такой команды, которая содержит select и like: выбрать из таблицы БД телефонов только записи, в которых поле ФИО начинается на "м". Оператор like используется для поиска по шаблону (pattern matching) вместе с символами универсальной подстановки (метасимволами) ’’звездочка” (*) и ’’знак вопроса” (?). Строка шаблона заключена в одинарные кавычки. Заметим также, что большинство баз данных использует символ % вместо значка * в LiKE-выражениях. Далее при создании объекта Adapter выполняем SQL-команду и при выпол- нении метода Fill заполняем объект DataSet таблицей, полученной в резуль- тате SQL-запроса. Затем указываем в качестве источника данных для сетки данных DataGridViewl объект DataSet. Этого оказывается достаточным для вывода на экран результатов SQL-запроса (рис. 9.16). Рис. 9.16. Вывод результата SQL-запроса Так же, как и при использовании объекта DataReader в предыдущем примере, в полученной таблице мы можем сортировать записи по любой из колонок. Можем редактировать (изменять) содержание ячеек, но в базу данных эти изменения не попадут (сохранения не будет). Заметим, что здесь с помощью визуального проектирования выполнено толь- ко перетаскивание в форму сетки данных DataGridView, остальное сделано программно, что обеспечивает большую гибкость программы. Убедиться в работоспособности программы можно, открыв решение DataSetGrid.sIn в папке DataSet_Grid. 7 Зак 145
194 Гпава 9 Пример 66. Обновление записей в таблице базы данных MS Access Одно из основных четырех действий над данными в БД (select, insert, update и Delete) является модификация (update, обновление) данных. Автор поставил задачу написать маленькую программу для обновления записей в таблице базы данных, но с большим удобством (гибкостью) управления про- граммным кодом. Рассматриваемая в данном примере программа имеет форму, сетку данных DataGridView, в которую из базы данных читается таблица при нажатии кнопки Читать из БД. Пользователь имеет возможность редактировать данные в этой таблице, после чего, нажав кнопку Сохранить в БД, данные в базе данных будут модифицированы, т. е. заменены новыми. Для написания этой программы запускаем VB2010, заказываем новый проект New Project шаблона Windows Forms Application. Из панели Toolbox до- бавляем в форму элемент управления DataGridView и две командные кноп- ки. Программный код программы представлен в листинге 9.7. Листинг 9.7, Обновление записей в таблице базы данных MS Access ’ Программа обновляет записи (Update) в таблице базы данных MS Access Imports System.Data.OleDb Public Class Forml Private DS As DataSet Private DA As OleDb.OleDbDataAdapter Private CO As New OleDb.OleDbConnection( "Data Source=””C:\vic.mdb”User " & _ ”ID=Admin;Provider=”"Microsoft.Jet.OLEDB.4.0"";") Private CB As OleDb.OleDbCommandBuilder ’ Dim COMMAND As OleDbCommand = New OleDbCommand или Dim COMMAND = New OleDbCommand Private Sub Forml_Load(ByVai sender As System.Object, ByVai e As System.EventArgs) Handles MyBase.Load Buttonl.Text() = "Читать из БД" Button2.Text() = "Сохранить в БД" End Sub
Обработка баз данных с использованием технологии ADO.NET 195 Private Sub ЧИТАТЬ(ByVai sender As System.Object, , ByVai e As System.EventArgs) Handles Buttonl.Click ’ Читать из базы данных DS = New DataSet If CO.State = Connectionstate.Closed Then CO.OpenO DA = New OleDb.OleDbDataAdapter("Select * From [БД телефонов]”, CO) CB = New OleDb.OleDbCommandBuilder(DA) DA.Fill(DS, "БД телефонов”) DataGridViewl.DataSource = DS.Tables("БД телефонов”) End Sub Private Sub СОХРАНИТЬ(ByVai sender As System.Object, ByVai e As System.EventArgs) Handles Button2.Click ’ Сохранить в базе данных COMMAND.CommandText = "UPDATE [БД телефонов] SET [Но” & "мер телефона] = ?, ФИО = ? WHERE ([Номер п/п] = ?)" ’ Имя, тип и длина параметра COMMAND.Parameters.Add("Номер телефона", OleDbType.VarWChar, 50, "Номер телефона") COMMAND.Parameters.Add("ФИО”, OleDbType.VarWChar, 50, "ФИО") COMMAND. Parameters .Add (New OleDb Parameter ("Original_HoMep_n_n", OleDbType.Integer, 0, System.Data.ParameterDirection. Input, False, CType(0, Byte), CType(0, Byte), "Номер п/п", System.Data.DataRowVersion.Original, Nothing)) DA.UpdateCommand = COMMAND COMMAND.Connection = CO Try ’ Update возвращает количество измененных строк Dim koi As Integer = DA.Update(DS, "БД телефонов") MessageBox.Show("Обновлено " & koi & " записей”) Catch ex As Exception MessageBox.Show(ex.Message, "Недоразумение") End Try End Sub End Class
196 Гпава 9 Вначале импортируем (imports) пространство имен System.Data.OleDb, это обеспечит более короткие объявления объектов и манипулирования ими. Да- лее, как видно, мы имеем три процедуры обработки событий: загрузки фор- мы, щелчок на кнопке Читать из БД и щелчок на кнопке Сохранить в БД. Чтобы объекты DataSet, DataAdapter, Connection, CommandBuilder И Command были видны в этих трех процедурах, объявляем эти объекты внешними внут- ри класса Forml. При программировании чтения из базы данных на сетку DataGridViewl мы использовали объект CommandBuilder для демонстрации возможности чтения данных с помощью этого объекта, хотя могли бы организовать чтение из ба- зы данных на сетку DataGridViewl так, как это было показано в предыдущих программах. Фрагмент работы программы после чтения из базы данных представлен на рис. 9.17. Рис. 9.17. Фрагмент работы программы обновления данных Представляет интерес программирование модификации записей базы данных. Эта возможность программирована при обработке события ’’щелчок мышью на кнопке” Сохранить в БД. Здесь свойству CommandText присвоено значение текста SQL-запроса. В качестве заменителей параметров используются во- просительные знаки. Как видно, в данном SQL-запросе имеют место три во- просительных знака. Этим трем вопросительным знакам соответствуют три параметра, которые должны указываться именно в порядке следования во- просительных знаков. Эти параметры задаем с использованием метода COMMAND. Parameters.Add. Здесь указываем ИМЯ ПОЛЯ (например, ’’Номер телефо- на"), тип, длину параметра и значение по умолчанию. Заметим, что третий параметр ("Номер п/п") задается как новый, поскольку он не должен подле-
Обработка баз данных с использованием технологии ADO.NET 197 жать редактированию со стороны пользователя, а устанавливаться автомати- чески, независимо от пользователя. Далее в блоке Try.. .Catch вызываем непосредственно метод da.update, кото- рый возвращает количество (koi) обновленных записей. В случае неудачного обновления обрабатывается исключительная ситуация Exception, объект Exception обеспечивает соответствующее сообщение о недоразумении. Убедиться в работоспособности программы можно, открыв решение Update.sln в папке Update. Пример 67. Удаление записей из таблицы БД с использованием SQL-запроса и объекта Command Можно также удалять записи (строки из таблицы БД), формируя в программ- ном коде соответствующий SQL-запрос, передаваемый в объект Command. Именно объект Command обеспечивает привязку SQL-выражения к соеди- нению с базой данных. Напишем самый простой пример такой программы. Для этого запустим VB2010 и закажем новый проект New Project. Экранная форма нам в данном случае не нужна, поэтому выбираем, как и в некоторых предыдущих примерах, шаблон Console Application. Для того чтобы во вре- мя выполнения данной программы не видеть черного DOS-экрана, в меню Project выберем команду ConsoleApplicationl Properties и на вкладке Application укажем в раскрывающемся списке Application type тип прило- жения Windows Forms Application. Чтобы иметь доступ к функции MessageBox.show (хотя можем воспользоваться MsgBox), добавим к проекту ссылку на динамическую библиотеку Forms.dll. Для этого выберем’ пункты меню Project | Add Reference и на вкладке .NET дважды щелкнем на ссылке на библиотеку System.Windows.Forms.dll. Отметим, что при этом на вклад- ке, открываемой командой Project | Properties | References, появилась соот- ветствующая этой библиотеке ссылка. Далее напишем следующий программный код (листинг 9.8). Листинг 9.8. Удаление записей из таблицы БД ; ’ Программа удаляет запись из таблицы БД с использованием ’ SQL-запроса и объекта Command Imports System.Data.OleDb Imports System.Windows.Forms Module Modulel
198 Гпава 9 Sub Main () ' Создаем объект Connection и передаем ему строку соединения Dim CONNECTION As New OleDb.OleDbConnection( "Data Source=’”’C:\_VB_NET\vic.mdb"";User " & "ID=Admin;Provider=""Microsoft.Jet.OLEDB.4.0"";") CONNECTION.Open() ’ Создаем объект Command, передавая ему SQL-команду Dim COMMAND As New System.Data.OleDb.OleDbCommand( "Delete * From [БД телефонов] Where " & "ФИО Like 'Vi%'", CONNECTION) ' Выполнение команды SQL Dim i As Integer = COMMAND.ExecuteNonQuery() ’ i — количество удаленных записей If i > 0 Then MessageBox.Show( "Записи, содержащие в поле ФИО фрагмент ’Vi*', удалены") If i = 0 Then MessageBox.Show( "Запись, содержащая в поле ФИО фрагмент ’Vi*’, не найдена") CONNECTION.Close() End Sub End Module Здесь при создании объекта command задан SQL-запрос на удаление (Delete) всех записей, содержащий в поле ФИО фрагмент текста "Vi*", причем строчные и прописные буквы являются равнозначными, т. е. будут удалены записи, содержащие "vi*", "vi*", "vi*" и прочие комбинации. Таким образом, поиск записей ведется без учета регистра (case-insensitive search). Замечу, что здесь для выполнения команды SQL использован метод ExecuteNonQuery. Он возвращает в переменную i количество удаленных запи- сей. Если i = о, значит, записи с таким контекстом не найдены и ни одна запись не удалена. Убедиться в работоспособности программы можно, открыв решение DelFromDB.sIn в папке DelFromDB.
ГЛАВА 10 Другие задачи, решаемые с помощью Windows Forms Application Пример 68. Проверка вводимых данных с помощью регулярных выражений Данные, вводимые пользователем, должны быть проверены программой на достоверность. В этом примере мы обсудим синтаксический разбор введен- ной пользователем текстовой строки на соответствие ее фамилии на русском языке, а также разбор строки на соответствие ее положительному рациональ- ному числу. Начнем с первой задачи; имеем на форме текстовое поле, метку и кнопку. В метке записано приглашение пользователю ввести фамилию на русском языке. После ввода программа должна сравнить эту строку с некото- рым образцом (шаблоном, pattern) и сделать заключение, соответствует ли введенное пользователем значение шаблону русской фамилии. Для решения этой задачи запустим VB2010, выберем пункт New Project, за- кажем новый проект из шаблона Windows Forms Application и щелкнем на кнопке ОК. Затем из панели элементов управления Toolbox в форму указате- лем мыши перетаскиваем текстовое поле TextBox, метку Label и командную кнопку Button. В листинге 10.1 приведен текст программы. Листинг ЮЛ. Проверка вводимой фамилии с помощью регулярных ’ Проверка данных, вводимых пользователем, на достоверность. ’ Программа осуществляют синтаксический разбор введенной пользователем ’ текстовой строки на соответствие ее фамилии на русском языке Imports System.Text.RegularExpressions Public Class Forml
200 Глава 10 Private Sub Forml_Load(ByVai sender As System.Object, ByVai e As System.EventArgs) Handles MyBase.Load Labeli.Text = "Введите фамилию на русском языке:" Buttonl.Text = "Проверка" End Sub Private Sub Buttonl_Click(ByVai sender As System.Object, ByVai e As System.EventArgs) Handles Buttonl.Click TextBoxl.Text = TextBoxl.Text.Trim If Not Regex.Match(TextBoxl.Text, "Л[А-ИК-ЩЭ-Я][а-яА-Я]*$").Success Then MessageBox.Show _ ("Неверный ввод фамилии", "Ошибка") End Sub End Class Как видно из программного кода, перед объявлением класса импортируем пространство имен System.Text.RegularExpressions ДЛЯ обеспечения более компактного кода. При обработке события ’’щелчок мыши на кнопке” тексто- вое поле TextBoxl.Text обрабатывается методом Trim, который удаляет все пробельные символы в начале и в конце строки. Ключевым моментом про- граммы является проверка соответствия введенной пользователем тексто- вой строки и шаблона с помощью функции Regex.Match (от англ, match — со- ответствовать): Regex.Match(TextBoxl.Text, "л[А-ИК-ЩЭ-Я][а-яА-Я]*$") Match представляет результаты из отдельного совпадения регулярного выра- жения. Как видно, мы начали регулярное выражение с символа л и закончили символом $. Символы л и $ соответствуют началу и концу строки соответст- венно. Это побуждает регулярное выражение оценивать всю строку, а не воз- вращать соответствие, если успешно совпадает подстрока. Далее в первых квадратных скобках указан диапазон допустимых букв для установления соответствия первой буквы фамилии. Первая буква должна быть прописной, т. е. верхнего регистра, в диапазоне алфавита (и таблицы символов) от А до И, от К до Щ и от Э до Я, т. е. недопустим ввод букв Й, Ъ, Ы, Ь в качестве первой буквы фамилии. Далее в следующих квадратных скобках указан диапазон букв либо нижнего, либо верхнего регистров, при- чем символ * означает, что второй диапазон символов может встретиться в строке ноль или более раз. Фрагмент работы программы представлен на рис. 10.1. Вторая задача, которую мы рассмотрим в данном примере, — это проверка правильности ввода положительного рационального числа. Следует допус-
Другие задачи, решаемые с помощью Windows Forms Application 201 тить возможность ввода любых вариантов, например, ”2010”, "2.9”, ”5.”, ”.777”. То есть допустим ввод цифровых символов и точки (или запятой). Рис. 10.1. Проверка корректности ввода фамилии на русском языке Пользовательский интерфейс для решения данной задачи такой же, как и для предыдущей, поэтому сразу приведу программный код решения (лис- тинг Ю.2). ' Листинг 10.2. Проверка вводимого числа с помощью регулярных выражений ’ Проверка данных, вводимых пользователем, на достоверность. Программа ’ осуществляет синтаксический разбор введенной пользователем текстовой ’ строки на соответствие ее положительному рациональному числу. Imports System.Text.RegularExpressions Public Class Forml Private Sub Forml_Load(ByVai sender As System.Object, ByVai e As System.EventArgs) Handles MyBase.Load Labell.Text = ’’Введите положительное рациональное число:’’ Buttonl. Text = ’’Проверка’’ End Sub Private Sub Buttonl_Click(ByVai sender As System.Object, ByVai e As System.EventArgs) Handles Buttonl.Click TextBoxl.Text = TextBoxl.Text.Trim If Regex. Ma*t ch (TextBoxl .Text, (([0-9] + .[0-9]*) | ([0-9]*.[0-9]+) | ([0-9]+))$”).Success = False Then MessageBox. Show (’’Некорректный ввод”, "Ошибка") End Sub End Class Данная программа построена аналогично предыдущей, в комментарии нуж- дается шаблон "л(([0-9]+.[0-9]*)I([0-9]*.[0-9]+)I([0-9]+))$"
202 Глава 10 Здесь между символами |, означающими логическое ИЛИ, между круглыми скобками представлены три группы выражений. Первая группа допускает ввод цифровых символов от 0 до 9 до десятичной точки. Знак ’’плюс" (+) оз- начает, что цифровой символ может встретиться в строке один или более раз. Символ * означает, что цифровой символ может встретиться в строке ноль или более раз. Таким образом, первая группа допускает ввод, например, ра- ционального числа б. Аналогично работает вторая группа выражений, она допускает ввод, например, числа .77. Третья группа— это совсем просто: она проверяет соответствие с любыми целыми числами. Убедиться в работоспособности программ, рассмотренных в данном примере, можно, открыв решение RegEx2.sln в папке RegEx2 и RegEx3.sln в папке RegEx3. Пример 69. Управление прозрачностью формы В VB6 возможности управлять прозрачностью формы не было, для этого приходилось пользоваться API-интерфейсом для доступа к функциям опера- ционной системы Windows. Такая возможность существует в VB, начиная с версии VB.NET. Создадим программу, которая демонстрирует стандартное Windows-окно, т. е. стандартную форму. Щелчок мышью в пределах этой формы начинает постепенный процесс исчезновения формы, форма стано- вится все более прозрачной, а затем исчезает вовсе, далее она постепенно проявляется снова, и т. д. Еще один щелчок в пределах формы останавливает этот процесс, а следующий щелчок процесс возобновляет и т. д. Для написания этой программы добавим в стандартную форму из панели элементов управления Toolbox объект Timer (Таймер). Это невидимый во время работы программы элемент управления предназначен для периодиче- ского генерирования события Tick, которое происходит, когда таймер ра- ботает и прошел заданный интервал времени. Этот интервал времени Timerl. interval по умолчанию равен 100 миллисекунд, его в нашей програм- ме мы изменять не будем. Управлять прозрачностью формы можно с помощью свойства формы opacity, задавая уровень непрозрачности от нуля до единицы. Текст про- граммы приведен в листинге 10.3. ? Листинг 10.3. Управление прозрачностью формы ’ Программа демонстрирует стандартную форму. Щелчок мышью в пределах • этой формы начинает постепенный процесс исчезновения формы: форма ’ становится все более прозрачной, а затем исчезает вовсе. Далее она ’ постепенно проявляется снова, и т. д. Еще один щелчок в пределах
Другие задачи, решаемые с помощью Windows Forms Application 203 ’ формы останавливает этот процесс, а следующий щелчок ’ процесс возобновляет и т. д. Public Class Forml Private s As Double =0.1 Private Sub Forml_Click(ByVai sender As Object, ByVai e As System.EventArgs) Handles MyBase.Click Timerl.Enabled = Not Timerl.Enabled End Sub Private Sub Timerl_Tick(ByVai sender As Object, ByVai e As System.EventArgs) Handles Timerl.Tick If Me.Opacity <= 0 Or Me.Opacity >= 1 Then s = -s End If Me.Opacity += s End Sub Private Sub Forml_Load(ByVai sender As System.Object, ByVai e As System.EventArgs) Handles MyBase.Load ’ Timerl.Interval() =400 End Sub End Class Как видно, здесь при обработке события ’’щелчок в пределах формы” запус- кается таймер, а еще один щелчок мышью его останавливает. Каждые 100 миллисекунд появляется событие Timeri ciick. Обрабатывая его, мы ме- няем значение непрозрачности Opacity от нуля до единицы с шагом 0.1, ко- торый задаем через внешнюю переменную s. Этот пример автор взял на сайте: http://subscribe.ru/archive/comp.sofLprog.visualbnet/200512/16181816.html Текст этой программы можно посмотреть, открыв решение Opacity.sin в пап- ке Opacity. Пример 70. Время по Гринвичу в полупрозрачной форме Время, дату, день недели очень легко выяснить, посмотрев в правый нижний угол рабочего стола Windows. Однако, если, например, вы читаете новости, которые поступают в реальном времени, где время публикаций указывают по Гринвичу (GMT) — это могут быть, например, новости валютного рынка или
204 Гпава 10 фондового рынка Форекс или другой экономический календарь, то в этом случае важно знать, насколько актуальна, свежа новость. Конечно, можно держать в голове, что время Москвы отличается от времени по Гринвичу на 4 часа, а время по Киеву— на 3 часа, а затем мучительно соображать, необ- ходимо прибавить эти 3 часа к киевскому времени или наоборот отнять. Кроме того, следует помнить, что время по Гринвичу не переводится на лет- ние и зимние часы. Поэтому, чтобы выяснить правильное время по Гринвичу, можно на стандартном рабочем столе Windows справа внизу двойным щелч- ком на отображении текущего местного времени на вкладке Часовой* пояс выбрать Время по Гринвичу и сбросить флажок Автоматический переход на летнее время и обратно. При этом очень удобно для сравнения времени иметь перед глазами сайт www.central-european-time.com, где показано те- кущее местное время, среднеевропейское (или центральноевропейское время, Central European Time (СЕТ)) и время по Гринвичу. Предлагаю написать маленькую программу, которая в полупрозрачной эк- ранной форме отображает текущее время по Гринвичу. То есть мы напишем программу, которая будет демонстрировать текущее время по Гринвичу и при этом, в силу своей прозрачности, не будет заслонять другие приложения. Для решения этой задачи создадим форму и перетащим в нее из панели эле- ментов управления Toolbox метку Label и объект Timer. Этот объект позво- лит обрабатывать событие Timerl.Tick через периодически заданные интер- валы времени. Далее на вкладке визуального проекта программы Forml.vb [Design] растянем мышью форму и метку примерно так, как показано на рис. 10.2. Б РЕМЯ ПО Г РИНБИЧУ: 09:44 Рис. 10.2. Фрагмент работы программы определения времени по Гринвичу Программный код данной программы представлен в листинге 10.4. ’ Листинг 10А Время по Гринвичу в полупрозрачной форме ' Программа в полупрозрачной экранной форме отображает текущее время ' по Гринвичу. Таким образом, программа демонстрирует текущее время ’ по Гринвичу и при этом не заслоняет собой другие приложения. Imports System.DateTime Public Class Forml Dim t As Boolean = False
Другие задачи, решаемые с помощью Windows Forms Application 205 Private Sub Forml_Load(ByVai sender As System.Object, ByVai e As System.EventArgs) Handles MyBase.Load Me.Text = ’’ВРЕМЯ ПО ГРИНВИЧУ:” Me.Opacity =0.75 ’ Уровень непрозрачности формы Labeli.Font = New Drawing.Font("Courier New”, 18.0!) Labeli.TextAlign = ContentAlignment.MiddleCenter Labeli.Text = "" Timerl.Interval = 1000 ’ 1000 миллисекунд = 1 секунда Timerl.Start () End Sub Private Sub Timerl_Tick(ByVai sender As Object, ByVai e As System.EventArgs) Handles Timerl.Tick ’ Обработка события, когда прошел заданный интервал ’ времени = 1000 миллисекунд = 1 с Labeli.Text = "ВРЕМЯ ПО ГРИНВИЧУ: ” Dim время As String t = Not t ’ To же, что и t = True Xor t If t = True Then время = Format(UtcNow, "HH:mm") _ Else время = Format(UtcNow, "HH mm") Labeli.Text = Labeli.Text & время End Sub Private Sub Forml_MouseLeave(ByVai sender As Object, ByVai e As System.EventArgs) Handles MyBase.MouseLeave Me.Opacity = 0.75 End Sub Private Sub Labell_MouseEnter(ByVai sender As Object, ByVai e As System.EventArgs) Handles Labeli.MouseEnter ’ При вхождении в границы метки Me.Opacity = 1 End Sub End Class Здесь при обработке события загрузки формы Fomi Load задаем текст ’’ВРЕМЯ ПО ГРИНВИЧУ:” в заголовке формы (свойство Me.Text), указываем уровень непрозрачности формы Me.Opacity = 0.75. Если Opacity = о, то изо-
206 Гпава 10 бражение формы совсем пропадает, программа будет благополучно работать в оперативной памяти, и мы будем догадываться о ее работе, т. к. она будет напоминать о своем существовании в свернутом виде в панели задач. При Opacity = 1 будем иметь обычное непрозрачное изображение формы. Замечу, что в VB6 у экранной формы не было такого свойства, и чтобы программиро- вать прозрачность формы, приходилось использовать функции Microsoft Windows API. Далее включаем таймер Timerl.start() и задаем интервал работы таймера Timer 1. interval = 1000 (1000 миллисекунд, т. е. 1 с). Это означает, что через каадую секунду мы имеем возможность обрабатывать событие "прошла одна секунда" Timerl.Tick. Справиться с задачей демонстрации времени было бы очень легко, если бы нам надо было просто отображать текущее время. Мы бы написали: Dim время As String: время = Format (Now, "hh:mm") если мы хотим иметь время AM (например, 4:32), и время = Format (Now, "HH:mm"), если мы хотим время РМ (т. е. 16:32). Однако по условию задачи, нам нужно показывать время по Гринвичу. Сис- тема VB2010 Имеет СВОЙСТВО UtcNow пространства имен System. DateTime. Это свойство возвращает так называемое универсальное координированное время (Universal Coordinated Time, UTC), которое с точностью до долей секунды совпадает со временем по Гринвичу. Поэтому выражение время = Format (UtcNow, "HH:mm") копирует в строку время значение текущего времени Гринвичского мери- диана. Далее, чтобы подчеркнуть, что время идет, между значением часа и значени- ем минут зададим двоеточие (:), которое появляется в течение одной секунды и исчезает тоже на одну секунду. Для этого у нас есть внешняя булева пере- менная t, которая периодически меняет свое значение с True на False, потом с False на True и т. д., т. е. на противоположное: t = Not t. Таким образом, при обработке события Tick (события, когда прошел заданный интервал вре- мени Interval, равный 1000 миллисекунд = 1 С) объекта Timerl В метку Labell копируется новое значение времени то с двоеточием, то без него. Как видно, в тексте данной программы мы использовали переменные с рус- скими именами, что добавило выразительности программному коду. Мы реа- лизовали возможность становиться форме непрозрачной при наведении кур- сора МЫШИ В область метки при обработке события Labell_MouseEnter вхож-
Другие задачи, решаемые с помощью Windows Forms Application 207 дения курсора мыши в границы метки. Из соображений эстетики (что, конеч- но же, может быть подвергнуто сомнению) мы запрограммировали возврат опять к прозрачной форме при выходе курсора мыши за пределы формы, а не метки, т. е. при наступлении события Forml_MouseLeave. Текст этой программы можно посмотреть, открыв решение time.sin в папке time. Пример 71. Создание ссылки на процесс, работающий в фоновом режиме, в форме значка в области уведомлений Название раздела для новичка кажется чрезвычайно ’’заумным”. На самом деле ничего сложного, как и многое другое в области компьютерных техно- логий, если разобраться в сути слов и попробовать практически испытать ра- боту элементов этих технологий. В данном разделе речь идет о программах, работающих на компьютере в фоновом режиме при использовании, напри- мер, антивирусных программ или элемента управления громкостью. Такие программы внешне напоминают о своем существовании лишь присутствием значка в области уведомлений панели задач в правом нижнем углу экрана. Кстати, программу ’’Время по Гринвичу в полупрозрачной форме”, рассмот- ренную в предыдущем разделе, уместно было бы запрограммировать именно со значком в области уведомлений. Однако чтобы замысел одного примера не смешивался с замыслом другого, а программный код при этом выглядел компактно и выразительно, эти программы приведены в разных примерах. Рассматриваемая в данном разделе программа также способна работать в фо- новом режиме. Внешне программа имеет форму с меткой, где записаны воз- можности программы, командную кнопку, при щелчке на которой форма ис- чезает, но зато появляется значок в области уведомлений. При этом програм- ма в оперативной памяти существует и работает в фоновом режиме. При щелчке правой кнопкой мыши на этом значке появляется контекстное меню из двух пунктов. Один пункт меню сообщает пользователю время работы данного компьютера с тех пор, как стартовала операционная система, а дру- гой пункт меню обеспечивает выход из данной программы. При двойном щелчке на искомом значке появляется опять исходная форма, а значок исче- зает. Таким образом, проектируемая программа способна переводить свою работу в фоновый режим и обратно. Для программирования данной задачи запустим VB2010, выберем новый проект Windows Forms Application. В конструкторе формы из панели эле- ментов перенесем в форму метку, командную кнопку, элемент управления
208 Глава 10 Notifylcon и контекстное меню ContextMenuStrip. Щелкая на значке ContextMenuStrip, спроектируем два пункта контекстного меню: Время старта ОС и Выход. Теперь перейдем на вкладку программного кода, где напишем текст программы, представленный в листинге 10.5. = Листинг 10.5. Перевод работы программы в фоновый режим и обратно ; ’ Эта программа сообщает пользователю время, прошедшее с момента ’ старта операционной системы на данном компьютере. ’ Доступ к этой информации реализован через контекстное меню ’ значка в области уведомлений панели задач. ' Программа сообщает пользователю время, прошедшее с ’ момента старта операционной системы на данном компьютере. ’ Доступ к этой информации реализован через контекстное меню ’ значка в области уведомлений панели задач. Public Class Forml ' Из панели элементов следует перенести в форму ’ Notifylcon и ContextMenuStrip. Private Sub Forml_Load(ByVai sender As System.Object, ByVai e As System.EventArgs) Handles MyBase.Load ’ Здесь можно написать Handles MyBase.Me Me.Text = "Создаю значок в области уведомлений" ’ Размер метки: Me.Labeli.Size = New System.Drawing.Size(292, 90) ’ Разрешить продолжение текста в метке с новой строки: Labeli.AutoSize = False Me.Labeli.Text = "При щелчке на командной кнопке данная программа " + "помещает значок в область уведомлений. Щелкните " + "правой кнопкой мыши на этом значке для доступа к " + "контекстному меню с пунктами ""Время работы ОС"" и " + """Выход"". Двойной щелчок на значке возвращает " + "на экран данную форму." Buttonl.Text = "Разместить значок в области уведомлений" ’ Systemicons это стандартные значки Windows: Notifylconl.Icon = Systemicons.Shield ’ — значок щита ’ Systemicons.Information — значок сведений Notifylconl.Text = "Время работы ОС" Notifylconl.Visible = False ’ "Привязываем" контекстное меню к значку Notifylconl: Notifylconl.ContextMenuStrip = ContextMenuStripl End Sub
Другие задачи, решаемые с помощью Windows Forms Application 209 Private Sub Buttonl_Click(ByVai sender As System.Object, ByVai e As System.EventArgs) Handles Buttoni.Click ’ Скрыть экранную форму и сделать видимым значок ’ в области уведомлений: Me.Hide() : Notifylconl.Visible = True End Sub Private Sub NotifyIconl_MouseDoubleClick(ByVai sender As _ System.Object, ByVai e As System.Windows.Forms. MouseEventArgs) Handles Notifylconl.MouseDoubleClick ’ Чтобы получить пустой обработчик этого события, можно, ’ например, в конструкторе формы дважды щелкнуть ’ на значке Notifylconl Notifylconl.Visible = False : Me.Show() End Sub Private Sub ВремяСтартаОС(ByVai sender As System.Object, ByVai e As System.EventArgs) Handles _ BpeMHCTapTaOCToolStripMenuItem.Click Dim Время_работы_ОС_в_минутах As Double = My.Computer.Clock.TickCount, / 1000 / 60 ' Формат "{0:F0}" округляет Double до целого значения: Dim ss As String = String.Format( "ОС стартовала {0:F0} минут назад", Время_работы_ОС_в_минутах) MessageBox.Show(ss) End Sub Private Sub Выход(ByVai sender As System.Object, ByVai e As _ System.EventArgs) Handles BbixoflToolStripMenuItem. Click Notifylconl.Dispose() : Application.Exit() End Sub End Class Как видно из программного кода, при обработке события загрузки формы выполняем очевидные инициализации свойств элементов управления, в том числе для компонента Notifylconl. Для него среди стандартных значков Windows выбираем значок щита (Notifylconl. Icon = Systemicons.Shield), a сам значок делаем невидимым (Notifylconl.Visible = False). При обработке
210 Гпава 10 события "щелчок на командной кнопке" скрываем экранную форму и делаем видимым значок в области уведомлений. Обработка события "двойной щел- чок" на этом значке обеспечивает противоположное действие, а именно по- казывает форму, но скрывает значок. Две последние процедуры обрабатыва- ют выбор пунктов меню Время старта ОС и Выход. На рис. 10.3 и 10.4 при- ведены фрагменты работы программы в обычном и фоновом режимах. 1 При щелчке на > оматнай кнопке данная программа ; '? помешает значо в область уведомлений Щелкните | -5 правой кнопкой мыши на этом значке для доступа к • t контепс-тному меню с пунктами ' Время работы ОС” и * \ ”Выхсд‘‘. Двойной щелчок на значке возвращает на ; i экран данную Форму \ I ’ _ На вместить значок в области уведомлении ,i j Рис. 10.3. Внешний вид формы при работе программы в обычном режиме Рис. 10.4. Контекстное меню при работе программы в фоновом режиме Убедиться в работоспособности данной программы можно, открыв соответ- ствующее решение в папке Значок_в_области_уведомлений. Пример 72. Нестандартная форма. Перемещение формы мышью Обычно экранную форму, любое Windows-окно мы перемещаем при нажатой левой кнопке мыши, ’’зацепив” за заголовок, т. е. за синюю полосу вверху окна. В заголовке расположены кнопки Свернуть, Свернуть в окно и Закрыть. Для демонстрации работы с событиями мыши, с аргументами про- цедуры обработки ЭТИХ событий MouseEventArgs напишем программу, с по- мощью которой появляется возможность перемещать форму, ’’зацепив” ее указателем мыши в любой части формы, а не за заголовок. Подобный пример приведен в книге "Visual Basic .NET. Библия пользователя’”. 1 Ивьен Б., Берес Дж. Visual Basic .NET. Библия пользователя. — М.: Вильямс, 2002. — С. 591.
Другие задачи, решаемые с помощью Windows Forms Application 211 Запускаем VB2010, далее заказываем новый проект шаблона Windows Forms Application и получаем таким образом стандартную экранную форму. Затем пишем текст программы, приведенный в листинге Ю.6. ’ Нестандартная форма. Программа позволяет перемещать форму мышью, ’ "зацепив" ее не за заголовок, а в любом месте формы. Public Class Forml Private Moving As Boolean = False ’ Перемещаем форму только тогда, когда Moving = True Private MouseDownX As Integer Private MouseDownY As Integer Private Sub Forml_MouseDown(ByVai sender As Object, ByVai e As _ System.Windows.Forms.MouseEventArgs) Handles Me.MouseDown ' Здесь обрабатываем событие "щелчок любой кнопкой мыши". Во время ’ щелчка левой кнопкой мыши запоминаем текущее положение мыши If е.Button = MouseButtons.Left Then Moving = True MouseDownX = e.X MouseDownY = e.Y End If End Sub Private Sub Forml_MouseUp(ByVai sender As Object, ByVai e As _ System.Windows.Forms.MouseEventArgs) Handles Me.MouseUp • Здесь обрабатываем событие, когда ’ пользователь отпустил кнопку мыши If е.Button = MouseButtons.Left Then Moving = False End Sub Private Sub Forml_MouseMove(ByVai sender As Object, ByVai e As _ System.Windows.Forms.MouseEventArgs) Handles Me.MouseMove ’ Здесь обрабатываем событие, когда указатель • мыши перемещается в пределах формы. ’ Перемещаем форму только тогда, когда Moving = True. If Moving = True Then Dim temp = New System.Drawing.Point temp.X = Me.Location.X + (e.X — MouseDownX) temp.Y = Me.Location.Y + (e.Y — MouseDownY) Me.Location = temp End If End Sub End Class
212 Глава 10 Вначале программы объявлены три внешние переменных, видимые в преде- лах класса Forml. Одна из переменных — булева переменная Moving — это как бы флажок, который сигнализирует, следует ли перемещать экранную форму. Если пользователь нажал левую кнопку МЫШИ (событие MouseDown, Button = Left), то Moving = True, т. e. следует перемещать форму. Если пользователь отпустил кнопку мыши (событие Mouseup), то Moving = False, т. е. форму пе- ремещать не следует. Остальные две переменных целого типа integer пред- назначены для запоминания текущего положения (е.х и е.у) мыши. Переме- щаем форму только тогда, когда перемещается указатель мыши (событие MouseMove), И При ЭТОМ флажок Moving = True. Убедиться в работоспособности программы можно, открыв решение Mov Form.sIn в папке MovForm. Пример 73. Проигрыватель Windows Media Player 11 Используя возможность подключения к проекту соответствующей библиоте- ки, можно написать программу для проигрывания различных файлов муль- тимедиа AVI, MPEG, MP3, MP4, FLV, WMV и других форматов. Причем ядром вашей программы будет, например, самый современный плеер Windows Media Player версии II. Но пользовательский интерфейс, т. е. спо- соб управления плеером: кнопки на форме или в виде выпадающего меню, цвет оболочки, значения параметров по умолчанию, размер экрана и пр., вы можете создать свой собственный. Итак, запустим VB2010 и закажем новый проект. Назовем этот новый проект Player. Далее в окне New Project выберем шаблон Windows Forms Application и нажмем кнопку ОК. Чтобы добавить на панель Toolbox эле- мент управления Windows Media Player, следует подключить библиотеку Windows Media Player. Для этого щелкая правой кнопкой мыши в пределах панели элементов, в контекстном меню выберем пункт Choose Items. Далее на вкладке COM Components установим флажок Windows Media Player и щелкнем на кнопке ОК. При этом на панели элементов появится значок Windows Media Player. Перетащите этот значок в форму. Растяните изобра- жения формы и плеера так, как вам представляется это привлекательным. По- сле этого в папках проекта bin\Debug\ и \obj\x86\Debug\ должны появиться два файла: AxInterop.WMPLib.dll и Interop.WMPLib.dll. В этих двух файлах находятся динамически вызываемые объекты для работы элемента управле- ния Windows Media Player. Далее для программирования меню перенесем с панели Toolbox в форму зна- чок MenuStrip. Слева вверху формы появится проект первого пункта меню
Другие задачи, решаемые с помощью Windows Forms Application 213 Type Here. Здесь мы проектируем пункты меню будущей программы. Меню Файл имеет пункты Открыть и Выход. А меню Сервис имеет пункты, пока- занные на рис. 10.5. Рис. 10.5. Проектирование пунктов меню Программный код приведен в листинге 10.7. . Листинг 10.7. Проигрыватель Windows Media Player 11 ' Программа реализует функции проигрывателя Windows Media Player 11 Public Class Forml Dim OpenFileDialogl As New OpenFileDialog Private Sub Forml_Load(ByVai sender As System.Object, ByVai e As System.EventArgs) Handles MyBase.Load ’ ВЕРСИЯ ПЛЕЕРА Me.Text = "Windows Media Player, версия = " & AxWindowsMediaPlayerl.versioninfo End Sub Private Sub Открыть(ByVai sender As System.Object, ByVai e As System.EventArgs) _ Handles OTKpbrrbToolStripMenuItem.Click ’ ПУНКТ МЕНЮ Открыть ’ Пользователь выбирает файл: OpenFileDialogl.ShowDialog()
214 Глава 10 ’ Передача плееру имени файла AxWindowsMediaPlayerl.URL = OpenFileDialogl.FileName ’ AxWindowsMediaPlayerl.URL = ’ "C:\WINDOWS\Media\Windows XP Startup.wav" ’ Команда на проигрывание файла AxWindowsMediaPlayerl.Ctlcontrols.play() ’ ИЛИ ТАК: передача имени файла и сразу PLAY ’ AxWindowsMediaPlayerl.openPlayer(OpenFileDialogl.FileName) End Sub Private Sub Выход(ByVai sender As System.Object, ByVai e As System.EventArgs) _ Handles ВыхoflToolStripMenuItem.Click ’ ПУНКТ МЕНЮ Выход Application.Exit() End Sub Private Sub ПолныйЭкран(ByVai sender As System.Object, ByVai e As System.EventArgs) _ Handles ПолныйЭкранТоо13Гг1рМепи1Гет.Click ’ ПУНКТ МЕНЮ Полный экран ’ Если плеер пребывает в состоянии PLAY, то можно ’ перейти в режим полного экрана: If AxWindowsMediaPlayerl.playState = WMPLib.WMPPlayState.wmppsPlaying _ Then AxWindowsMediaPlayerl.fullScreen = True End Sub Private Sub Пауза(ByVai sender As System.Object, ByVai e As System.EventArgs) _ Handles naysaToolStripMenuItem.Click ’ ПУНКТ МЕНЮ Пауза AxWindowsMediaPlayerl.Ctlcontrols.pause() End Sub Private Sub Play(ByVal sender As System.Object, ByVai e As System.EventArgs) _ Handles PlayToolStripMenuItem.Click ' ПУНКТ МЕНЮ Play AxWindowsMediaPlayerl.Ctlcontrols.play() End Sub
Другие задачи, решаемые с помощью Windows Forms Application 215 Private Sub ВыклЗвук (By Vai sender As System.Object, ByVai e As System.EventArgs) _ Handles ВыклЗвукТоо!StripMenuItern.Click ’ ПУНКТ МЕНЮ Выкл звук AxWindowsMediaPlayerl.settings.mute = True End Sub Private Sub ВклЗвук(ByVai sender As System.Object, ByVai e As System.EventArgs) _ Handles BKnSByKToolStripMenuItern.Click ' ПУНКТ МЕНЮ Вкл звук AxWindowsMediaPlayerl.settings.mute = False End Sub Private Sub Свойства(ByVai sender As System.Object, ByVai e As System.EventArgs) _ Handles CBoncTBaToolStripMenuItem.Click ’ ПУНКТ МЕНЮ Свойства AxWindowsMediaPlayerl.ShowPropertyPages() End Sub End Class Как видно из текста программы, перед загрузкой формы объявлено создание экземпляра объекта OpenFiieDiaiog. Этот объект можно было бы перенести в форму из панели элементов управления, как мы это делали в примере 23 (см. главу 3). а можно его создать программно, как в данном программном коде. В процедуре обработки события Formi Load задаем текст строки заголовка формы "Windows Media Player, версия = ". При этом номер версии получаем ИЗ СВОЙСТВа versioninfo. При обработке события "щелчок мышью по пункту меню" Открыть функция ShowDialog обеспечивает выбор нужного файла мультимедиа. Передача плее- ру имени выбранного файла происходит через свойство плеера url. Далее следует команда на проигрывание файла, хотя можно было бы предусмотреть эту команду в отдельном пункте меню. В комментарии приведена возмож- ность проигрывания файла мультимедиа при передаче имени этого файла од- ной функцией openPlayer. Далее по тексту программы реализованы очевидные функции в соответст- вующих обработчиках событий: переход в режим полного экрана (это воз- можно только, если плеер пребывает в состоянии проигрывания файла wmppsPlaying), Пауза, Play, ВклЗвук, ВыклЗвук, ВЫЗОВ меню Свойства, ВЫХОД ИЗ программы.
216 Глава 10 Убедиться в работоспособности программы можно, открыв решение Player.sln в папке Player. Замечу, что в книге ’’Как программировать на Visual Basic .NET'" также рас- смотрена возможность управления объектом Windows Media Player вер- сии 6.4.09.1119. Однако мы привели программирование плеера вер- сии 11.0.5721.5145, для которого система команд имеет существенные отли- чия. Пример 74. Программирование контекстной справки. Стандартные кнопки в форме Напишем программу, демонстрирующую организацию помощи пользовате- лю вашей программы. В данной программе предусмотрена экранная форма, которая в заголовке имеет кнопку Справка (в виде вопросительного знака) и кнопку Закрыть. Здесь реализована контекстная помощь, когда после щелч- ка мыши на кнопке Справка можно получить контекстную всплывающую подсказку по тому или иному элементу управления, находящемуся в форме. Для этого обычным путем создадим новый проект из шаблона Windows Forms Application, получим стандартную форму. Используя панель Toolbox, добавим в форму три текстовых поля, три метки и две кнопки, как показано на рис. 10.6. Рис. 10.6. Фрагмент работы программы с контекстной справкой Таким образом, мы получили пользовательский интерфейс редактирования таблицы телефонов, знакомый нам из предыдущих разделов. На вкладке программного кода напишем следующий текст (листинг 10.8). 1 Дейтел X. М., Дейтел П. Дж., Нието Т. Р. Как программировать на Visual Basic .NET. Книга 2. Программирование для сети, структуры данных. — М.: Бином-Пресс, 2003. — С. 159.
Другие задачи, решаемые с помощью Windows Forms Application 217 ’ В программе предусмотрена экранная форма, которая в заголовке имеет ’ только кнопку Справка (в виде вопросительного знака) и кнопку Закрыть. ’ Здесь реализована контекстная помощь, когда после щелчка мыши на ’ кнопке Справка можно получить контекстную всплывающую подсказку ’ по тому или иному элементу управления, находящемуся в форме. Public Class Forml Private Sub Forml_Load(ByVai sender As System.Object, ByVai e As System.EventArgs) Handles MyBase.Load MaximizeBox = False ’ — отмена кнопки Развернуть MinimizeBox = False ’ — отмена кнопки Свернуть ’ Чтобы стиль формы содержал кнопку помощи, ’ т. е. вопросительный знак HelpButton = True Me.Text = "Демонстрация помощи" Buttonl.Text = "Следующая" : Button2.Text = "Предыдущая" TextBoxl.Clear() : TextBox2.Clear() TextBox3.Clear() Labell.Text = "Номер п/п" : Label2.Text = "ФИО" Labe13.Text = "Номер телефона" ’ Dim helpProviderl As HelpProvider = New HelpProvider или Dim helpProviderl = New HelpProvider helpProviderl.SetHelpString(TextBoxl, "Здесь отображаются номера записи по порядку") helpProviderl.SetHelpString(TextBox2, "Поле для редактирования имени абонента") helpProviderl.SetHelpString(TextBox3, "Поле для ввода и отображения номера телефона") helpProviderl.SetHelpString(Buttonl, "Кнопка для перехода на следующую запись") helpProviderl.SetHelpString(Button2, "Кнопка для перехода на предыдущую запись") ’ Назначаем, какой help-файл будет ’ вызываться при нажатии клавиши <F1> helpProviderl.HelpNamespace = "mspaint.chm" End Sub End Class
218 Глава 10 Здесь при обработке события загрузки формы мы программируем всю по- мощь пользователю. Так, чтобы стиль формы содержал кнопку Справка (во- просительный знак), следует запретить в форме кнопки Развернуть и Свер- нуть: MaximizeBox = False MinimizeBox = False Затем вместо них задать кнопку Справка: HeipButton = True. Далее объявля- ем объект helpProvideri, который мы могли бы добавить в форму, используя Toolbox. Затем для каждого из текстовых полей и кнопок задаем текст кон- текстной подсказки. Эта подсказка будет работать так же, как и подсказка ToolTip (см. пример 10 в главе 7). Свойству HeipNamespace назначаем help- файл, который будет вызываться при нажатии клавиши <F1>. Мы указали файл mspaint.chm, который является справочным для графического редактора MS Paint, встроенного в ОС Windows, т. е. он имеется на любом компьютере под управлением Windows. Формат СНМ был разработан Microsoft для ги- пертекстовых справочных систем. У СНМ-файлов, как правило, есть Содер- жание— отдельная панель со списком статей для упрощения навигации. В наличии содержания, пожалуй, и заключается главное отличие СНМ- файлов от использовавшихся ранее HLP-файлов справки Windows. Убедиться в работоспособности программы можно, открыв решение help.sln в папке help. Пример 75. Создание инсталляционного пакета для распространения программы Допустим, вы отладили свою первую (или очередную) программу, и теперь вам надо создать дистрибутив (инсталляционный пакет) для распростране- ния программы (дистрибуции). Инсталляционный пакет будет включать в себя набор файлов (setup.exe, *.msi, *.dll, *.tlb и т. д.). Пользователь вашей программы должен запустить setup.exe и в режиме диалога будет происхо- дить распаковка msi-архива, регистрация в системном реестре и пр. Для соз- дания таких инсталляционных пакетов существует множество программ- инсталляторов, например, InstallShild, InnoSetup и др. Однако можно вос- пользоваться непосредственно системой VB2010. Покажем процесс создания инсталляционного пакета на примере программы управления функциями AutoCAD (см. пример 54 в главе 8). Запустим систему VB2010, закажем новый проект, в окне New Project рас- кроем узел Other Project Types и узел Setup and Deployment (Установка и распространение), а здесь выберем пункт Visual Studio Installer и шаблон Setup Project. В строке Location укажем папку, где будет располагаться наш
Другие задачи, решаемые с помощью Windows Forms Application 219 инсталляционный пакет, например папку C:\New, и нажмем кнопку ОК. Да- лее в пункте меню Project выберем команду Add | File. Здесь добавляем ЕХЕ-файл и прочие файлы, которые мы хотим, чтобы были в msi-архиве ин- сталляционного пакета, в нашем случае это файл ACADm.exe, также добав- ляем файл Interop.AutoCAD.dll. При этом в окне Solution Explorer (Обозре- ватель решений) мы видим зависимые от ЕХЕ-файла ссылки на TLB-, DLL- и MSM-файлы. В нашем случае в окне Solution Explorer добавился файл ACAD.TLB. Можно также добавить еще необходимые на ваш взгляд компо- ненты, например, какой либо OCX-файл или тестовый файл с какими-либо пояснениями. После создания дистрибутива все эти файлы окажутся внутри msi-архива. Теперь даем команду на непосредственное создание инсталляционного паке- та Build | Build Setupl. После завершения процесса создания инсталляции в папке C:\New\Debug находим файлы Setup.exe и Setupl.msi. Эти файлы копи- руем на какой-либо съемный носитель, например, на компакт-диск или флэш- накопитель. Теперь инсталляционный пакет готов для распространения. На компьютере вашего пользователя запускаем Setup.exe, далее в диалоге указываем папку, например C:\Program Files\Acadm\, и в конце диалога полу- чаем сообщение от системы о завершений инсталляции. Теперь ваша про- грамма находится в указанной папке, в ней вы видите ЕХЕ-файл и все свя- занные с ним файлы DLL- и TLB-файлы. Программа зарегистрирована в сис- темном реестре, и вы можете найти ее среди установленных программ в Панели управления в разделе Установка и удаление программ.

Visual Studicr 2*Уй !! ГЛАВА 1 1 Программирование Web-ориентированных приложений на Visual Basic 2010 Создание Web-страницы на языке HTML. Интернет-технологии HTML (HyperText Markup Language)— это язык для отображения информа- ции о Web-странице в браузере: текста, изображений, анимации, ссылок на другие Web-страницы. Это язык специальных инструкций браузеру, но его нельзя назвать языком программирования в обычном понимании этого слова, поскольку он не позволяет использовать логику, с его помощью невозможно выполнить даже элементарные арифметические операции. Мы уже приводи- ли примеры HTML-кода для отображения таблиц. В качестве примера в лис- тинге 11.1 представлен HTML-код простейшей Web-страницы, содержащей GIF-изображение и гиперссылку для перехода на другую Web-страницу. Листинг 11.1. HTML-код простейшей Web-страницы <html> <head> <11Ь1е>Простейшая Web-CTpaHMua</title> </head> <body> <pximg border="0" src="imagel.gif” width=”317" height="73" /></p> <p><a href="http://www.mail.ги/">Перейти на почтовый сервер</ах/р> </body> Здесь тег <htmi> описывает ваш документ как Web-страницу, выполненную в формате HTML. Тег <head> указывает на наличие текста, содержащего на-
222 Гпава 11 именование страницы и дополнительные сведения о ней. В раздел <head> обычно вложен тег <titie> для обозначения наименования страницы в строке заголовка. Наименования Web-страниц отображаются в строке заголовка ок- на браузера. Затем следует тег <body>, в котором размещаются: весь осталь- ной текст, изображения, таблицы, гиперссылки и другие элементы содержи- мого Web-страницы. Тег <р> служит для обозначения начала нового абзаца. Для вставки графических элементов служит тег <img>. Файл изображения imagel.gif создан с помощью MS Office FrontPage. В этой программе автор задал художественно оформить текст ’’Весело живем!” (объект Word Art). В ответ FrontPage сгенерировал файл imagel.gif. Для создания гиперссылки служит тег <а>. Синтаксис этого тега очевиден. Данный HTML-код записан с помощью Блокнота в файл primer.htm. На рис. 11.1 приведено отображение этого файла в браузере Internet Explorer. 1 ||1||1||ЦМ|и11^^ДИИД :: . -7 ’ ;<£«;? Простейшая 'Л’еЬ-стрлпнцо ~’.l v = 1МИ^ Рис. 11.1. Отображение графического файла в браузере Internet Explorer Чтобы создавать подобные Web-страницы, вовсе не обязательно знать язык разметки HTML. Можно пользоваться каким-либо редактором Web-страниц, например, Microsoft Office FrontPage. Здесь интерфейс для создания Web- страницы очень похож на интерфейс текстового редактора MS Word. В край- нем случае, содержание Web-страницы можно набрать непосредственно в редакторе MS Word, но сохранить файл с расширением htm и таким образом получить Web-страницу. Однако Web-страница, написанная только на языке разметки HTML, будет статичной, она способна только лишь отображать какие-либо сведения. Вы знаете, что современная Web-страница является, по сути, программой, спо- собной реагировать на действия пользователя, обеспечивать полноценный интерактивный режим, диалог с пользователем, работу с базой данных и т. д. Обеспечить такую интерактивность можно, например, используя технологию
Программирование Web-ориентированных приложений на Visual Basic 2010 223 Microsoft ASP.NET, в частности язык VB2010. Технология ASP (Active Server Pages, активные страницы сервера) представляет альтернативу статичных страниц, основанных на чистом HTML. Web-хостинг на платформах UNIX и Windows Интернет можно рассматривать как совокупность связанных между собой специализированных компьютеров, включенных 24 часа в сутки, называемых хостами (от англ, host— хозяин, принимающий гостей) или серверами. Пользователи, представляющие локальные компьютеры, подключаются через провайдеров к Интернету, могут, используя URL-адреса, запрашивать те или иные Web-страницы, расположенные на различных серверах. Web-хостинг — это услуга в Интернете по предоставлению дискового про- странства и программного обеспечения для Web-страниц различных пользо- вателей. Если ваша Web-страница написана исключительно на языке HTML, то для ее размещения в Интернете подойдет любой Web-хостинг. Однако для размещения активных Web-страниц с интерактивным содержимым различ- ные серверы предлагают разное программное обеспечение. Так серверы под управлением операционных систем семейства UNIX/Linux обеспечивают Web-хостинг с использованием таких технологий, как РНР, CGI, Perl, Apache, GNU C/C++, базы данных MySQL, а так же все возможно- сти HTML. При этом пользователи таких Web-страниц на своих локальных (клиентских) компьютерах могут работать под управлением любых операци- онных систем (UNIX, Windows, Mac OS X). Как видим, в этом перечне отсут- ствует поддержка технологии Microsoft ASP.NET. Хостинг на основе ASP.NET существует только на Windows-платформе. То есть этот сервер может работать только под управлением операционной сис- темы Windows. Это сравнительно новая технология от Microsoft, которая на- зывается .NET Framework. Она является расширенным языком ASP. Данная платформа менее популярна, чем технология РНР. Между тем, Web- страницы, написанные на языке VB2010, выполняются по разным оценкам примерно в полтора-два раза быстрее, чем написанные на языке РНР. Клиент-серверное взаимодействие на основе технологии ASP.NET Схема работы активной Web-страницы следующая. С помощью URL-адреса Web-браузер клиентского компьютера запрашивает необходимую активную Web-страницу. В ответ Web-сервер посылает браузеру ASPX-документ, со- держащий HTML-разметку и теги <asp>. ASPX-документ интерпретируется браузером клиента и представляется в виде Web-страницы. Пользователь на
224 Гпава 11 клиентском компьютере заполняет предложенные в этом документе формы, задает какие-либо команды, делает запросы и т. д., а затем отсылает (напри- мер, нажимая какую-либо командную кнопку) ASPX-документ назад на сер- вер для выполнения. Сервер реагирует на команды пользователя (клиента), выполняя команды с помощью библиотеки DLL, расположенной на сервере, и генерируя новый ASPX-документ, содержащий HTML-разметку вместе с тегами <asp>. Теги HTML, содержащие атрибут runat=”server”, выполняются на сервере. На стороне пользователя Web-браузер только лишь интерпрети- рует полученный от сервера HTML-поток. DLL (Dynamic-link library)— это динамически подключаемая библиотека, имеющая формат ЕХЕ-файла, в ней содержится программный код и ресурсы, используемые активной Web- страницей. С помощью библиотеки DLL реализуется весь сценарий взаимо- действия с пользователем. Таким образом, вся ’’активность” страницы выпол- няется на стороне сервера, а Web-браузеру пользователя (клиента) отсылает- ся лишь результат выполнения в виде HTML-потока. Как получить библиотеку DLL? Ничего сложного: управляющая среда VB20I0 сама генерирует файл разметки *.ASPX и файл программной под- держки *.ASPX.vb для Web-стр^ницы, причем файл *.ASPX.vb является про- граммным кодом VB2010. А для того чтобы получить библиотеку DLL, сле- дует скомпилировать разрабатываемый проект. При этом получим новую библиотеку DLL в папке bin. Отладка активного Web-приложения Тот факт, что Web-страница выполняет команды пользователя на стороне сервера, затрудняет отладку Web-приложения, поскольку требует как мини- мум двух компьютеров: один будет работать как клиент, а другой — как сер- вер. На самом деле, как правило, обходятся одним компьютером. Но при этом устанавливают сервер на собственном компьютере для тестирования различ- ных активных страниц, не выходя в Интернет. Среда Visual Studio 2010 имеет возможность использовать собственный локальнй сервер для отладки актив- ных Web-приложений. Прежние версии Visual Basic, например VB.NET, требовали обязательной установки локального сервера IIS (Internet Information Services) через Панель управления | Установка или удаление программ или компонентов Windows | Установка компонентов Windows. В этом случае система созда- вала папку C:\lnetpub\wwwroot, поддерживаемую локальным сервером, где должны были располагаться все разрабатываемые Web-приложения с инте- рактивным содержимым. Обращение к активным Web-страницам, располо- женным в папке C:\lnetpub\wwwroot, осуществляется через задание в адрес- ной строке браузера адреса локального сервера, например, http://localhost/
Программирование Web-ориентированных приложений на Visual Basic 2010 225 primer.aspx. Но заметьте, что они не будут проявлять себя как активные при обращении к ним таким образом: "C:\Inetpub\wwwroot\HMa страницы". Среда Visual Studio 2010 поддерживает обе указанные возможности отладки Web-приложения. Менять установку данных возможностей можно через пункты меню Project | имя_проекта Properties, вкладка Web. Причем по умолчанию отладка производится именно с использованием сервера Visual Studio. Это дает возможность отлаживать интерактивные Web-приложения в любой папке винчестера. Пример 76. Создание простейшей активной Web-страницы на VB2010 Как уже отмечалось, статичные Web-страницы не способны выполнять даже элементарные арифметические действия. Создадим Web-страницу, демонст- рирующую способность как раз складывать числа, введенные пользователем. И одновременно подчеркнем единый подход к разработке Windows- и Web- прилОжений. В обоих случаях имеем те же инструменты: форму, текстовые поля, метки, командные кнопки и пр. Таким образом, на данной разрабаты- ваемой странице будем иметь два текстовых поля, куда пользователь будет вводить числа, командную кнопку и метку, на которую будет выводиться ре- зультат сложения двух чисел. Для создания Web-приложения откроем VB2010, в окне New Project на вкладке Installed Templates (Инсталлированные шаблоны) выберем шаблон Empty ASP.NET Web Application. В поле Name укажем имя данного проек- та— Summa, при этом снимем флажок Create directory for Solution. После щелчка разработчика по кнопке ОК управляющая среда создаст папку Summa, в которой будет находиться проект нового Web-приложения. Теперь мы можем приступить к проектированию Web-страницы. Поскольку проект пустой (empty), добавим к текущему проекту Web-форму. Для этого в пункте меню Project выберем команду Add New Item и в появившемся окне укажем шаблон Web Form и щелкнем на кнопке Add. При этом в окне Solution Explorer будет добавлен значок WebForml.aspx. Теперь мы можем проектировать внешний вид формы на вкладке WebForml.aspx. Принцип перетаскивания из панели элементов Toolbox нужных для текущего проекта элементов управления точно такой же, как и при проектировании формы Windows. Поэтому перетащим из панели элементов управления необ- ходимые нам два текстовых поля, командную кнопку и метку. Кроме того, в заголовке Web-страницы предусмотрим текст ’’Введите два числа”. Для это- го щелкнем правой кнопкой мыши в пределах проектируемой Web-страницы, в контекстном меню выберем пункт Properties. В появившемся окне свойств 8 Зак I45
226 Глава 11 Properties среди свойств документа (DOCUMENT) находим свойство Title, которое содержит текст заголовка Web-страницы. Этому свойству присваи- ваем значение — "Введите два числа". Уже на этом этапе посмотрим на внешний вид проекта, для этого попытаемся выполнить этот проект— нажмем клавишу <F5>. В результате Internet Explorer откроет файл WebForml.aspx, сгенерированный управляющей сре- дой, и мы получим Web-страницу, изображенную на рис. 11.2. Рис. 11.2. Фрагмент работы активной Web-страницы Понятно, что пока эта страница является статической. Закроем Web-браузер и вернемся к проекту Web-страницы. По умолчанию проектируемая Web- страница имеет имя WebForml.aspx, но при желании в окне Sulution Explorer (Обозреватель решений), щелкнув правой кнопкой мыши на значке WebForml.aspx, это имя можно изменить. Вообще говоря, интерактивность, динамичность Web-страницы обеспечивает файл программной поддержки *.ASPX.vb, содержащий VB2010-код. Чтобы перейти на вкладку файла про- граммного кода WebForml.aspx.vb, следует, например, воспользоваться контекстным меню проекта Web-формы и выбрать команду View Code. Как видите, вкладка программного кода здесь такая же, как и при проектировании формы Windows. На вкладке файла WebForml.aspx.vb напишем следующий программный код (листинг 11.2). ’ Создание простейшей активной Web-страницы на VB2010. ’ Web-страница, демонстрирующая способность складывать числа, • введенные пользователем Public Class WebForml Inherits System.Web.UI.Page
Программирование Web-ориентированных приложений на Visual Basic 2010 227 Protected Sub Page_Load (ByVai sender As Object, ByVai e As System.EventArgs) Handles Me.Load Page.Title = "Введите два числа" Labe11.Text = Nothing Buttoni.Text = "Найти сумму двух чисел" End Sub Private Sub Buttonl_Click(ByVai sender As Object, ByVai e As System.EventArgs) Handles Buttoni.Click Dim Z As Double = Convert.ToDouble(TextBoxi.Text) + Convert.ToDouble(TextBox2.Text) Labe11.Text = "Сумма = " & Z End Sub End Class Как видно из текста программы, при обработке события загрузки страницы Page Load очищаем (Nothing) текстовую метку и задаем текст на командной кнопке. При обработке события "щелчок на кнопке", используя функцию ToDouble класса convert, преобразуем символы, введенные пользователем (клиентом) в переменные типа Double, складываем их и выводим сумму в тек- стовую метку. Готовая Web-форма будет иметь вид, представленный на рис. 11.3. Рис. 11.3. Сумма двух введенных чисел В результате работы управляющей среды была скомпилирована библиотека WebApplicationl.dll в папке bin. Теперь именно WebApplicationl.dll будет обеспечивать интерактивность файлу разметки WebForml.aspx. Таким образом, созданная Web-страница представляет собой два файла: WebForml.aspx и WebForml.aspx.vb. Файл WebForml.aspx определяет
228 Гпава 11 HTML-содержимое сайта, a WebForml.aspx.vb — программный код, который отделен от HTML-содержимого и предназначен для программного формиро- вания данного содержимого или выполнения каких-либо иных действий на сервере. Эта связь определена в файле WebForml.aspx в директиве Раде через СВОЙСТВО CodeBehind= ’’WebForml. aspx. vb”. Убедиться в работоспособности Web-страницы можно, открыв решение Summa.sln в папке Summa. Пример 77. Проверка введенных пользователем числовых данных с помощью валидаторов Очевидно, что созданная в предыдущем разделе Web-страница имеет много недостатков, в частности если пользователь не заполнил текстовые поля, то получим сообщение ’’Ошибка сервера...”. Между тем, следовало бы подска- зать пользователю ввести что-либо в указанные поля. Кроме контроля пустых полей необходимо проверить, является ли введенное значение числом или символом (например, буквой). Для этих целей при разработке Windows- приложений мы использовали функцию isNumeric, однако при разработке Web-приложений имеем среди элементов управления так называемые вали- даторы, которые можно использовать в документах ASP.NET для осуществ- ления любой проверки введенных данных. Валидаторы (их семь) можно уви- деть в разделе Validation в панели элементов Toolbox. В данной задаче мы будем совершенствовать Web-страницу, созданную нами в предыдущем примере. Выполним проверку, ввел ли пользователь хоть что- либо в текстовые поля, а также проверим тип введенных данных и выясним, СООТВеТСТВуЮТ ЛИ ОНИ ТИПУ ДаННЫХ Double. Для этого запустим VB2010, в окне New Project выберем шаблон Empty ASP.NET Web Application, в поле Name укажем имя нового решения Valid 1 и щелкнем на кнопке ОК. Теперь добавим к текущему проекту Web-форму. Для этого в пункте меню Project выберем команду Add New Item, в появив- шемся окне укажем шаблон Web Form и щелкнем на кнопке Add. Далее на вкладке конструктора формы перетащим из панели элементов Toolbox необ- ходимые нам два текстовых поля, командную кнопку и метку. В данной задаче мы должны контролировать два текстовых поля, поэтому перенесем мышью из панели Toolbox соответственно два валидатора RequiredFieldValidator, проверяющих факт заполнения текстовых полей, и два валидатора CompareValidator для проверки, ввел пользователь числа или другие символы. Расположим их в форме, как показано на рис. 11.4.
Программирование Web-ориентированных приложений на Visual Basic 2010 229 Рис. 11.4. Проектирование Web-формы программы, содержащей валидаторы Далее на вкладке файла программной поддержки WebForml.aspx.vb усовер- шенствуем программный код так, как представлено в листинге 11.3. ; Листинг 11.3. Использование валидаторов на Web-странице ’ Проверка введенных пользователем числовых данных с помощью ’ валидаторов. Выполним проверку, ввел ли пользователь хоть что-либо ’ в текстовые поля, а также проверим тип введенных данных и выясним, ' соответствуют ли они типу данных Double. Public Class WebForml Inherits System.Web.UI.Page Protected Sub Page_Load(ByVai sender As Object, ByVai e As System.EventArgs) Handles Me.Load Page.Title = ’’Введите два числа" Labeli.Text = Nothing Labeli.Width = 180 Buttoni.Text = "Найти сумму двух чисел" Buttoni.Width = 180 TextBoxi.Width = 180 TextBox2.Width = 180 RequiredFieldValidatorl.ErrorMessage = "* Следует заполнить это текстовое поле" RequiredFieldValidatorl.ControlToValidate = "TextBoxi" RequiredFieldValidator2.ErrorMessage = "* Следует заполнить это текстовое поле" RequiredFieldValidator2.ControlToValidate = "TextBox2"
230 Глаеа 11 CompareValidatorl.ControlToValidate = "TextBoxl" CompareValidatorl.Type = ValidationDataType.Double CompareValidatorl.Operator = ValidationCompareOperator.DataTypeCheck CompareValidatorl.ErrorMessage = "* Следует вводить числа" CompareValidator2.ControlToValidate = "TextBox2" CompareValidator2.Type = ValidationDataType.Double CompareValidator2.Operator = ValidationCompareOperator.DataTypeCheck CompareValidator2.ErrorMessage = "* Следует вводить числа" End Sub Private Sub Buttonl_Click(ByVai sender As Object, ByVai e As System.EventArgs) Handles Buttonl.Click Dim Z As Double = Convert.ToDouble(TextBoxl.Text) + Convert.ToDouble(TextBox2.Text) Labe11.Text = "Сумма = " & Z End Sub End Class Как ВИДНО, при загрузке страницы В свойствах валидаторов RequiredField мы указали имена полей, подлежащих контролю факта их заполнения, а также привели текст сообщения, как реакцию на данную ошибку. В свойствах вали- даторов compare также указали имена полей, подлежащих проверке типа дан- ных DataTypeCheck, И текст сообщения. Пример работы запрограммированных валидаторов приведен на рис. 11.5. Рис. 11.5. Фрагмент работы Web-страницы с валидаторами
Программирование Web-ориентированных приложений на Visual Basic 2010 231 Среди имеющихся на панели Toolbox валидаторов уместно здесь отметить ValidationSummary. Его можно поместить на какое-либо место на Web- страницу, где будут отображаться все сведения об ошибках от разных вали- даторов. Причем чтобы сообщения не дублировались, можно указать в свой- ствах всех валидаторов visible = False, но только свойство валидатора ValidationSummary.Visible = True. Очень ценно то, что валидаторы обеспечивают проверку данных не на серве- ре, а на машине клиента. Это происходит следующим образом: браузер кли- ента запрашивает на Web-сервере соответствующую страницу; в ответ сервер отсылает на клиентский компьютер HTML-код, который содержит JavaScript с диагностикой, которую мы предусмотрели в vb-файле поддержки. В резуль- тате пользователь (клиент) не ощущает задержки во время диагностики дан- ных, поскольку диагностика происходит на клиентском компьютере. Следует отметить то, что если бы мы сами писали валидаторы на языке JavaScript, то потребовалось бы написать гораздо больше строк программного кода. Убедиться в работоспособности Web-страницы можно, открыв решение Validl.sln в папке Validl. Пример 78. Проверка достоверности ввода имени, адреса e-mail, URL-адреса и пароля с помощью валидаторов В данном примере разберем типичную задачу проверки ввода пользователем имени, адреса e-mail, URL-адреса и пароля, например, при регистрации поль- зователя. Причем если страница (Web-форма) успешно прошла все этапы проверки, то направляем пользователя на другую, уже разрешенную для это- го пользователя, Web-страницу. Решая поставленную в данном разделе задачу, запустим VB2010, закажем новый проект из шаблона Empty ASP.NET Web Application, укажем в поле Name имя Validations и щелкнем кнопку ОК. К текущему проекту добавим Web-форму. Для этого в меню Project выберем команду Add New Item и в появившемся окне дважды щелкнем шаблон Web Form. Теперь в конструкторе формы на вкладке WebForml.aspx из панели ToolBox перенесем в форму пять меток Label, пять текстовых полей TextBox и ко- мандную кнопку Button. Текстовые поля соответствуют вводу имени пользо- вателя, адреса e-mail, URL-адреса персональной Web-страницы пользователя, пароля и подтверждения пароля. Для контроля правильности ввода данных перетащим из панели Toolbox несколько валидаторов. Так, для контроля обязательности ввода в пер- вые четыре текстовых поля перенесем в форму четыре валидатора
232 Гпава 11 RequireFieldValidator. Для контроля полей Пароль и Подтверждение па- роля перенесем валидатор CompareValidator, он будет сравнивать эти два поля, поэтому валидатор обязательности ввода для поля Подтверждение па- роля не нужен. Кроме того, для контроля формата ввода e-mail-адреса и URL-адреса Web-страницы на соответствие заданному шаблону выберем на панели Toolbox элемент управления RegularExpressionValidator. Располо- жим их в форме, как показано на рис. 11.6. Рис. 11.6. Проектирование Web-формы проверки личных введенных данных пользователя Теперь следует указать соответствующие свойства для каждого из исполь- зуемых элементов управления. Это можно сделать так же, как и при про- граммировании Windows-форм визуально, непосредственно в таблице свойств каждого из элементов управления. Свойства элементов управления можно задать также в программном коде, как это сделано в листинге 11.4. ; Листинг 11А Проверка достоверности ввода имени, адреса e-mail, URL-адреса ; : и пароля с помощью валидаторов. : ’ Проверка достоверности ввода имени, адреса e-mail, URL-адреса и • пароля. Web-страница проверяет ввод пользователем имени, ’ e-mail-адреса, URL-адреса и пароля, например, при регистрации ’ пользователя. Причем если страница (Web-форма) успешно прошла все
Программирование Web-ориентированных приложений на Visual Basic 2010 233 ’ этапы проверки, то направляем пользователя на другую, уже ’ разрешенную для этого пользователя, Web-страницу. Public Class WebForml Inherits System.Web.UI.Page Protected Sub Page_Load(ByVai sender As Object, ByVai e As System.EventArgs) Handles Me.Load Page.Title = "Заполните следующие поля:" Labeli.Text = "Имя" Label2.Text = "E-mail" Label3.Text = "Персональная Web-страница" Labe14.Text = "Пароль" TextBox4.TextMode = TextBoxMode.Password Label5.Text = "Подтвердите пароль" TextBox5.TextMode = TextBoxMode.Password RequiredFieldValidatorl.ControlToValidate = "TextBoxi" RequiredFieldValidatorl.ErrorMessage = "* Следует заполнить это текстовое поле" RequiredFieldValidator2.ControlToValidate = "TextBox2" RequiredFieldValidator2.ErrorMessage = "* Следует заполнить это текстовое поле" RequiredFieldValidator3.ControlToValidate = "TextBox3" RequiredFieldValidator3.ErrorMessage = "* Следует заполнить это текстовое поле" RequiredFieldValidator4.ControlToValidate = "TextBox4" RequiredFieldValidator4.ErrorMessage = "* Следует заполнить это текстовое поле" RegularExpressionValidatorl.ControlToValidate = "TextBox2" RegularExpressionValidatorl.ValidationExpression = "\w+([ —ь.]\w+)* @\w+([-.]\w+)*\.\w+([-.]\w+)★" RegularExpressionValidatorl.ErrorMessage = "* Следует ввести правильный адрес E-mail" RegularExpressionValidator2.ControlToValidate = "TextBox3" RegularExpressionValidator2.ValidationExpression = "http://([\w-]+\.)+[\w-]+(/[\w- ./?%&=]*)?" RegularExpressionValidator2.ErrorMessage = "* Следует ввести правильный адрес Web-узла"
234 Гпава 11 CompareValidatorl.ControlToValidate = "TextBox4" CompareValidatorl.ControlToCompare = ”TextBox5” CompareValidatorl.ErrorMessage = ”* Вы ввели разные паспорта” Buttonl.Text = "Готово” End Sub Private Sub Buttonl_Click(ByVai sender As Object, ByVai e As System.EventArgs) Handles Buttonl.Click If Page.IsPostBack = True Then If Page.IsValid = True Then ’ Здесь можно записать введенные пользователем сведения ’ в базу данных. Перенаправление на следующую страницу: Response.Redirect("Next_Page.htm") End If End If End Sub End Class Как видно, при обработке события загрузки Web-страницы page Load уста- навливаем значения свойств всех элементов управления. Мы могли бы это сделать в конструкторе на вкладке WebForml.aspx в таблицах свойств, но в программном коде это выглядит более выразительно для читателя, здесь трудно пропустить и не учесть какой-либо элемент управления. В свойствах полей TextBox4 (Пароль) и TextBox5 (Подтвердите пароль) указанное свойство TextMode установлено в режим Password, что обеспечивает "защиту от посто- ронних глаз", т. е. при вводе пароля в данных текстовых полях будем видеть жирные точки вместо вводимых символов. Далее следуют назначения свойств валидаторам обязательности заполнения полей RequiredFieid, знакомым нам из предыдущего раздела. Следует под- робнее остановиться на валидаторе RegularExpression. Регулярное выраже- ние, используемое для проверки достоверности ввода, выглядит несколько запутанным. Наверное, найдется мало людей, способных в точности перепи- сать регулярное выражение, например, для e-mail-адреса: "\w+( [-+. ] \w+) *@\w+( [-. ] \w+) *\.\w+( [-. ] \w+) *" Этот код можно расшифровать примерно таким образом: \w+— обязатель- ный ввод любого количества текстовых символов (буквы и цифры); далее ([-+.] \w+) — означает, что допустим ввод точки, а затем опять любое количе- ство букв и цифр, т. е. квадратные скобки означают необязательность, но возможность, а круглые скобки означают просто группировку выражения; затем *@\w+— обязательное наличие значка электронной почты @, после ко- торого должно следовать любое количество символов и т. д. Вручную такое
Программирование Web-ориентированных приложений на Visual Basic 2010 235 регулярное выражение вводить не стоит, поскольку это источник дополни- тельных ошибок. Для задания регулярных выражений лучше на вкладке кон- структора формы через щелчок правой кнопкой мыши посмотреть в таблицу свойств (Properties) валидатора RegularExpression. Здесь, напротив свойства ValidationExpression, после щелчка мышью на многоточии получим список типичных регулярных выражений для многих случаев жизни (рис. 11.7). standard expressions: ; French phone number | French postal code / | German phone number . i ||i|gi||i|||i|i^^ iiiO^ Сула ,,J Рис. 11.7. Список типичных регулярных выражений Выбирать и устанавливать нужное регулярное выражение можно либо в дан- ной таблице, либо копированием через буфер обмена (<Ctrl>+<C>, а затем <Ctrl>+<V>) в программный код. Контроль заполнения полей Пароль и Подтвердите пароль осуществлен с помощью валидатора CompareValidator путем сравнения этих полей. Фрагмент работы данной Web-формы в момент ее заполнения показан на рис. 11.8. Вернемся еще раз к программному коду. Здесь при обработке события "щел- чок на кнопке" Готово происходит проверка, вызвана (загружена) ли данная Web-страница первый раз IsPostBack = False или в результате повторной отправки (постбэка) IsPostBack = True. Если страница загружена в результа- те постбэка и проверка правильности страницы с помощью валидаторов так- же была успешной isValid = True, то можно записать сведения, предостав- ленные пользователем, в базу данных и перенаправить (Response.Redirect) его на следующую страницу Next_Page.htm, предусмотренную сценарием диалога с пользователем. Создать в текущем проекте новую статическую Web-страницу очень просто, для этого следует в пункте меню Project выбрать команду Add New Item и дважды щелкнуть шаблон HTML page. Далее в конструкторе страницы, ис- пользуя панель элементов Toolbox, спроектировать необходимую Web-
236 Гпава 11 страницу; заменить имя по умолчанию HTMLPagel.htm на Next_Page.htm удобно в окне Solution Explorer (Обозреватель решений). Убедиться в работоспособности Web-страницы можно, открыв решение Validations.sln в папке Validations. Рис. 11.8. Фрагмент работы Web-страницы при заполнении полей Пример 79. Регистрация и аутентификация пользователя с помощью базы данных Access Данный пример включает в себя три Web-формы: Registration.aspx, Login.aspx и Secret.aspx. Первая форма приглашает пользователя ввести реги- страционные данные, проверяет правильность ввода имени пользователя и пароля с использованием валидаторов, регистрирует пользователя в базе дан- ных MS Access и перенаправляет пользователя на уже разрешенный после регистрации ресурс Secret.aspx. Страница Secret.aspx допускает пользователя к закрытой информации, если он пришел либо со страницы Registration.aspx, либо со страницы Login.aspx. Форма Login.aspx запрашивает имя пользовате- ля и пароль, проверяет наличие пользователя с таким именем и паролем в ба- зе данных, если такового пользователя не оказалось, то программа отправля-
Программирование Web-ориентированных приложений на Visual Basic 2010 237 ет пользователя на регистрацию в Registration.aspx, а если есть, то он получа- ет доступ к ресурсу Secret.aspx. Для начала создадим базу данных Web.mdb, а в ней таблицу Аутентифи- цированные пользователи. Для этого запустим офисное приложение MS Access, далее в пункте меню Файл выполним команду Создать | Новая база данных и в нужной папке укажем файл Web.mdb. Далее следует создать таб- лицу в режиме конструктора в соответствии с очевидным интерфейсом. Име- на полей и типы данных приведены на рис. 11.9. Рис. 11.9. Проектирование таблицы базы данных в режиме конструктора В данном примере мы не собираемся заполнять поля e-mail и Web-страница, и приводим их здесь, чтобы была преемственность с предыдущим разделом. Вообще говоря, следует стараться чувствовать баланс между желанием больше знать о пользователе и не злоупотреблять терпением пользователя, который может потерять интерес к вашему сайту и перейти на другой ресурс. Теперь создадим регистрационную форму в системе VB2010, для этого после запуска системы закажем новый проект из шаблона Empty ASP.NET Web Application, в поле Name укажем имя Login.sln. К текущему проекту доба- вим Web-форму. Для этого в пункте меню Project выберем команду Add New Item и в появившемся окне дважды щелкнем шаблон Web Form. Далее, попав в конструктор Web-формы, в окне Solution Explorer (включите кнопку Show All Files), щелкнув правой кнопкой мыши на изображении фай- ла WebForml.aspx, переименуем его в Registration.aspx. Вид регистрационной формы показан на рис. 11.10. Как видно, для создания такой формы потребовалось четыре метки Label, три текстовых поля TextBox и командная кнопка Button. Кроме того, для контроля правильности ввода данных перетащим из панели Toolbox несколь- ко валидаторов. Так, для контроля обязательности ввода в первые два тексто- вых поля перенесем в форму два Валидатора RequireFieldValidotor. Для контроля полей Пароль и Подтверждение пароля перенесем вали- датор CompareValidotor, он будет сравнивать эти два поля, поэтому валида-
238 Гпава 11 тор обязательности ввода для поля Подтверждение пароля не нужен. В листинге 11.5 приведено содержимое файла программной поддержки Registration.aspx.vb. | ВВЕДИТЕ РЕП1СТРА1ДЮННЫЕ ДАННЫЕ ! * Следует запояншь это текстовое поле М1ИЙ^^Ь1^МИ|ЖИММИ|М^^^^^ДМ|||И^^^^М|^Ж1И||^МЯИ|1|И||||М||||И1|ИД|||||||||И • Подrsердгп е пароль * Вы ввели ратные паспорта Рис. 11.10. Фрагмент работы регистрационной формы ? Листинг 11.5. Регистрация пользователя . . - ' ". ’ Регистрация и аутентификация пользователя с помощью базы данных ’ MS Access. Данный пример включает в себя три Web-формы: • Registration.aspx и Login.aspx и Secret.aspx. Первая форма ’ Registration.aspx приглашает пользователя ввести регистрационные ’ данные, проверяет правильность ввода имени пользователя и пароля с ’ использованием валидаторов, регистрирует пользователя в базе данных • MS Access и перенаправляет пользователя на уже разрешенный после • регистрации ресурс Secret.aspx. ’ Импортируем пространство имен для манипуляций с БД: Imports System.Data.OleDb Public Class WebForml Inherits System.Web.UI.Page Protected Sub Page_Load(ByVai sender As Object, ByVai e As System.EventArgs) Handles Me.Load Page.Title = "РЕГИСТРАЦИЯ" Labeli.Text = "ВВЕДИТЕ РЕГИСТРАЦИОННЫЕ ДАННЫЕ" Labe12.Text = "Имя" Labe13.Text = "Пароль"
Программирование Web-ориентированных приложений на Visual Basic 2010 239 Labe 14.Text = ’’Подтвердите пароль” Buttonl. Text = ’’Готово” TextBox2.TextMode = TextBoxMode.Password TextBox3.TextMode = TextBoxMode.Password RequiredFieldValidatorl.ControlToValidate = "TextBoxl” RequiredFieldValidatorl.ErrorMessage = "* Следует заполнить это текстовое поле” RequiredFieldValidator2.ControlToValidate = "TextBox2" RequiredFieldValidator2.ErrorMessage = ’’* Следует заполнить это текстовое поле" CompareValidatorl.ControlToValidate -1"TextBox2’’ CompareValidatorl.ControlToCompare = "TextBox3" CompareValidatorl.ErrorMessage = ’’* Вы ввели разные паспорта" End Sub Protected Sub Готово(ByVai sender As Object, ByVai e As EventArgs) Handles Buttonl.Click ’ Запись в базу данных только при повторной отправке ’ и при достоверных данных If IsPostBack = False Or IsValid = False Then Exit Sub ’ Здесь можно записать введенные пользователем сведения в БД. ’ Строка подключения: Dim СтрокаПодкл As String = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=” & Server.MapPath("Web.mdb") ’ MapPath — возвращает физический путь ’ Создание экземпляра объекта Connection: Dim CONNECTION As OleDbConnection = New OleDbConnection(СтрокаПодкл) Try ’ Открытие подключения CONNECTION.Open() Catch ex2 As Exception Response.Write("<br><br>" & ex2.Message) Exit Sub End Try Dim SQL_3anpoc As String Dim COMMAND As New OleDbCommand ’ ДОБАВЛЕНИЕ ЗАПИСИ О ПОЛЬЗОВАТЕЛЕ В БД. ’ Строка SQL-запроса
240 Гпава 11 SQL_3anpoc = "INSERT INTO [Аутентифицированные пользовате" & "ли] ([Имя пользователя], [Пароль]) VALUES ('" & TextBoxl.Text & & TextBox2.Text & ’ Создание объекта Command с заданием SQL-запроса COMMAND.CommandText = SQL_saripoc ’ Для добавления записи в БД эта команда обязательна COMMAND.Connection = CONNECTION Try ’ Выполнение команды SQL, т. е. ЗАПИСЬ В БД COMMAND.ExecuteNonQuery() Catch ехЗ As Exception Response.Write("<br><br>” & ехЗ.Message) Exit Sub End Try CONNECTION.Close() ' Перенаправление на уже разрешенную страницу Response.Redirect("Secret.aspx") End Sub End Class Как видно, в данном программном коде при обработке события загрузки формы происходит проверка достоверности введенных пользователем дан- ных с помощью валидаторов так же, как и в предыдущем примере. При нажа- тии пользователем кнопки Готово запись в базу данных происходит только при повторной отправке данных IsPostBack = True, а также при достоверно- сти введенных данных isValid = True. Для записи в базу данных мы не стали переносить в форму соответствующие элементы управления из панели Toolbox, а очень кратко и выразительно использовали их непосредственно в программном коде. Теперь создадим Web-страницу для проверки имени пользователя и пароля с использованием таблицы Аутентифицированные пользователи в базе дан- ных. Для этого добавим к текущему проекту новую Web-форму, выбрав в пункте меню Project команду Add New Item | Web Form. Назовем эту новую форму Login.aspx. Внешний вид формы, запрашивающей у пользователя имя и пароль с их проверкой в базе данных, показан на рис. 11.11. Здесь потребовалось пять меток, два текстовых поля и две командных кноп- ки. В листинге 11.6 приведено содержимое файла программной поддержки Login.aspx.vb.
Программирование Web-ориентированных приложений на Visual Basic 2010 241 Рис. 11.11. Форма аутентификации пользователя i Листинг 11.6. Аутентификация пользователя ' Вторая форма Login.aspx запрашивает имя пользователя и пароль, ’ проверяет наличие пользователя с таким именем и паролем в базе ’ данных. Если такого пользователя не оказалось, то форма ’ отправляет пользователя на регистрацию Registration.aspx, а если ’ есть, то он получает доступ к ресурсу Secret.aspx. ’ Импортируем пространство имен для манипуляций с БД. Imports System.Data.OleDb Public Class WebForm2 Inherits System.Web.UI.Page Protected Sub Page_Load(ByVai sender As Object, ByVai e As System.EventArgs) Handles Me.Load Page.Title = "Логин” Page. Form.Method = ’’post" Labeli.Text = "АУТЕНТИФИКАЦИЯ ПОЛЬЗОВАТЕЛЯ" Label2.Text = "Имя" : Label3.Text = "Пароль" Label4.Text = "" : Label5.Text = "" TextBox2.TextMode = TextBoxMode.Password Buttoni.Text = "Готово" : Button2.Text = "Регистрация" End Sub Private Sub ГОТОВО(ByVai sender As Object, ByVai e As System.EventArgs) Handles Buttoni.Click ’ Щелчок на кнопке "Готово" Dim ПОЛЬЗОВАТЕЛЬ-АУТЕНТИФИЦИРОВАН As Boolean = False
242 Гпава 11 ’ Строка подключения Dim СтрокаПодкл As String = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" & Server.MapPath("Web. mdb") ’ Создание экземпляра объекта Connection Dim CONNECTION = New OleDbConnection(СтрокаПодкл) Try ’ Открытие подключения CONNECTION.Open() Catch exl As Exception Label5.Text = exl.Message End Try ’ Строка SQL-запроса для проверки имени и пароля Dim SQL_3anpoc As String = "SELECT Пароль FROM [Аутентифицированные пользо" & "ватели] WHERE ([Имя пользователя] = ’" & TextBoxl. Text & "’) AND (Пароль = ’" & TextBox2.Text & "’)" ’ Создание объекта Command с заданием SQL-запроса Dim COMMAND As New OleDbCommand COMMAND.CommandText = SQL_3anpoc COMMAND.Connection = CONNECTION Try ’ Выполнение команды SQL Dim DATAREADER As OleDbDataReader DATAREADER = COMMAND.ExecuteReader If DATAREADER.Read - True Then ПОЛЬЗОВАТЕЛЬ_АУТЕНТИФИЦИРОВАН = True Label4.Text = "Пользователь аутентифицирован" Else ПОЛЬЗОВАТЕЛЬ_АУТЕНТИФИЦИРОВАН = False Label4.Text = "Неправильное имя или " & "пароль, пожалуйста, зарегистрируйтесь!" End If Catch ех2 As Exception Labels.Text = Labels.Text & "<br />" & ex2.Message End Try CONNECTION.Close() If ПОЛЬЗОВАТЕЛЬ_АУТЕНТИФИЦИРОВАН = True Then ’ Направляем пользователя на уже разрешенную страницу Response.Redirect("Secret.aspx") End If End Sub
Программирование Web-ориентированных приложений на Visual Basic 2010 243 Private Sub РЕГИСТРАЦИЯ(ByVai sender As Object, ByVai e As System.EventArgs) Handles Button2.Click ’ Щелчок на кнопке "Регистрация" Response.Redirect("Registration.aspx") End Sub End Class Здесь при нажатии пользователем кнопки Готово производится SQL-запрос к базе данных на наличие записи с полями имени пользователя и пароля, полу- ченными от TextBoxl и TextBox2. Если такая запись найдена, то делаем вывод, что пользователь аутентифицирован, и направляем его на уже разрешенную для него Web-страницу Secret.aspx. Если же запись в базе данных с такими полями (именем и паролем) не найдена, то сообщаем об этом пользователю на метку Labei4. Пользователь при этом может либо уточнить имя и пароль, либо перейти к процедуре регистрации, нажав кнопку Регистрация. А что же Web-форма Secret.aspx? Если в ней просто привести закрытую ин- формацию, то недобросовестный пользователь, выяснив адрес этой страни- цы, очень легко наберет его в адресной строке браузера и получит без нашей санкции доступ к искомой странице, а все наши ’’умные’’ регистрации с ис- пользованием базы данных окажутся бесполезными. Исходя из этих сообра- жений, добавляем в текущий проект новую Web-форму, называем ее Secret.aspx. В эту форму из панели элементов перетаскиваем метку Label и командную кнопку Button. В листинге 11.7 приведен файл программной поддержки для файла-разметки Secret.aspx. Листинг 11 7 Web-форма SecreLaspx ’ К этой странице имеют доступ только зарегистрированные пользователи. ’ Вначале пытаемся (Try) определить, с какой Web-страницы пришел ’ пользователь на данный ресурс. Если не удается (ветка Catch, т. е. ’ пользователь пытается открыть данный закрытый ресурс, набрав ’ его URL-адрес в адресной строке браузера), то сообщаем пользователю, ’ что он не зарегистрирован, и делаем видимой кнопку "Регистрация". ’ Если удается определить URL-адрес страницы, с которой пользователь ’ пришел на данную страницу, то разрешаем доступ к закрытой информации ’ только для адресов /Login.aspx и /Registration.aspx. Partial Public Class Secret Inherits System.Web.UI.Page Protected Sub Page_Load(ByVai sender As Object, ByVai e As System.EventArgs) Handles Me.Load Buttonl.Visible = False : Buttonl.Text = "Регистрация"
244 Гпава 11 Dim ииь_адрес As String ’ Определение, с какой Web-страницы вы пришли на данную ’ страницу, т. е. определение локального адреса (пути) Try ииь_адрес = Request.UrlReferrer.LocalPath ’ Более эффективно определять абсолютный виртуальный адрес: ' URL-адрес = Request.UrlReferrer.AbsoluteUri If иРЬ_адрес = "/Login.aspx" Or _ URL—адрес = "/Registration.aspx" Then Labeli.Text = "Поскольку вы являетесь " & "зарегистрированным пользователем, то вы имеете " & "доступ к закрытой информации. Вы пришли на эту" & " страницу со страницы " & URL_адрес Exit Sub End If Catch ex As Exception Labeli.Text = "Вы не являетесь зарегистрированным " & "пользователем, поскольку пришли на эту страницу " & "набрав URL-адрес в адресной строке браузера." Buttoni.Visible = True Exit Sub End Try Labeli.Text = "Вы не являетесь зарегистрированным " & "пользователем, поскольку пришли со страницы " & URL—адрес Buttoni.Visible = True End Sub Protected Sub Регистрация(ByVai sender As Object, ByVai e As EventArgs) Handles Buttoni.Click Response.Redirect("Registration.aspx") End Sub End Class Как видно из программного кода, используя свойство LocalPath, определяем, с какой Web-страницы пришел пользователь на данную страницу. Причем мы здесь определяем локальный виртуальный адрес, поскольку нам таким обра- зом удобно производить отладку программу, но вообще говоря необходимо определять абсолютный вируальный адрес, как показано в комментарии. Да- лее разрешаем доступ к закрытой информации только пользователям, при- шедшим на данную страницу с Web-страниц Registration.aspx или Login.aspx. Убедиться в работоспособности Web-страницы можно, открыв решение Login.sin в папке Login.
Программирование Web-ориентированных приложений на Visual Basic 2010 245 Пример 80. Таблица с переменным числом ячеек, управляемая двумя раскрывающимися списками При Web-строительстве очень часто приходится работать с таблицами для различных целей. В данном примере продемонстрируем, как с помощью двух раскрывающихся списков DropDownList можно заказывать необходимое число рядов и столбцов в таблице. Программируя поставленную задачу, запустим систему VB2010 и создадим новый проект шаблона Empty ASP.NET Web Application, назовем его tab.sln. К текущему проекту добавим Web-форму. Для этого в пункте меню Project выберем команду Add New Item и в появившемся окне дважды щелкнем шаблон Web Form. Далее в конструкторе WebForml.aspx из панели элементов Toolbox в проек- тируемую форму перенесем элемент управления Table, два раскрывающихся списка DropDownList, две метки Label и командную кнопку Button. Теперь, используя, например, контекстное меню проекта Web-формы, выбираем команду View Code, попадаем на вкладку файла программной поддержки WebForml.aspx.vb. В листинге 11.8 приведен соответствующий программ- ный код. . Листинг 11.8. Таблица с переменным числом ячеек ' Таблица с переменным числом ячеек, управляемая двумя раскрывающимися ’ списками. Web-страница позволяет с помощью двух раскрывающихся ' списков DropDownList заказать необходимое число рядов ’ и столбцов в таблице, а затем строить заказанную таблицу. Public Class WebForml Inherits System.Web.UI.Page Protected Sub Page_Load(ByVai sender As Object, ByVai e As System.EventArgs) Handles Me.Load Page.Title = "Укажите размерность таблицы" If Page.IsPostBack = True Then Exit Sub ’ Заполнять выпадающий список необходимо при первой загрузке ’ страницы IsPostBack = False, иначе будут добавляться новые ’ пункты в выпадающей список при каждой перегрузке страницы DropDownList1.Items.Add ("I") DropDownLi s 11.1terns.Add("2") DropDownListl.Iterns.Add("3") DropDownList2.Items.Add("1")
246“Глава 11 DropDownList2.Items.Add("2") DropDownList2.Items.Add("3") Tablet.Caption = "Название таблицы" Tablet.CaptionAlign = TableCaptionAlign.Right Tablet.ToolTip = "Укажи количество рядов и столбцов и нажми кнопку" Tablet.Borderstyle = Borderstyle.Solid Tablet.GridLines = GridLines.Both Labell.Text = "Кол-во строк" Label2.Text = "Кол-во столбцов" Buttonl.Text = "Обновить таблицу" End Sub Private Sub Buttonl_Click(ByVai sender As Object, ByVai e As System.EventArgs) Handles Buttonl.Click Dim i, j As Integer For i = 1 To Int32.Parse(DropDownListl.Selectedltem.Value) Dim РЯД As New TableRow For j = 1 To Int32.Parse(DropDownList2.Selectedltem.Value) Dim ЯЧЕЙКА As New TableCell ЯЧЕЙКА.Text = "Ряд " & i & ", Кол " & j ЯЧЕЙКА.HorizontalAlign = HorizontalAlign.Center РЯД.Ce11s.Add(ЯЧЕЙКА) Next Tablet. Rows. Add (РЯД) Next End Sub End Class Как видно из программного кода, при загрузке страницы Page Load происхо- дит заполнение значениями раскрывающихся списков DropDownList, причем заполнение осуществляется только при первоначальной загрузке страницы, когда IsPostBack = False. Если бы мы не предусмотрели обход присвоения начальных значений при IsPostBack = True, то значения в списке добавля- лись бы каждый раз при очередной перезагрузке страницы. Заметим, что мы могли бы и не контролировать IsPostBack, если бы присвоение начальных значений выполнили бы в процедуре обработки события инициализации страницы Page Prelnit (в версии VB.NET ЭТО событие называлось Page_Init).
Программирование Web-ориентированных приложений на Visual Basic 2010 247 Свойства других элементов управления также инициализированы при обра- ботке события загрузки Web-страницы Page_Load. Мы могли бы это сделать в конструкторе, но, для удобства читателя, приводим их в программном коде. Назначения этих свойств очевидны и не требуют дополнительных коммента- риев. При обработке события щелчок на кнопке Обновить таблицу имеем два вложенных цикла. Параметры обоих циклов i и j изменяются от 1 до значе- ния, выбранного пользователем в соответствующем раскрывающемся списке. Метод int32. Parse пространства имен System конвертирует строку из соот- ветствующего свойства объекта DropDownList в переменную типа integer. Внешний цикл перебирает ряды таблицы, а внутренний — ячейки таблицы. В теле внешнего цикла очередная итерация создает новый объект ряд класса TabieRow, аналогично в теле внутреннего цикла каждый раз создается новый объект ячейка класса Tablecell. Для старта созданного проекта нажмем клавишу <F5>. В результате получим примерно такое отображение таблицы, как показано на рис. 11.12. Рис. 11.12. Фрагмент работы Web-страницы с таблицей Убедиться в работоспособности Web-страницы можно, открыв решение tab.sln в папке tab.
248 Гпава 11 Пример 81. Организация раскрывающегося меню гиперссылок с помощью DropDownList Переходы на другие Web-страницы, так называемую навигацию, в статиче- ских HTML-страницах обычно организуют с помощью ряда гиперссылок. Например, сайт состоит из десяти Web-страниц. На каждой из этих страниц слева страницы имеем колонку из десяти строчек текстовых гиперссылок для перехода на эти страницы. В данном примере продемонстрируем, как можно организовать переход на разные страницы сайта с помощью раскрывающего- ся списка DropDownList. Для реализации этой задачи запустим систему VB2010, далее— новый про- ект из шаблона Empty ASP.NET Web Application, имя — Menu. К текущему проекту добавим Web-форму. Для этого в пункте меню Project выберем команду Add New Item и в появившемся окне дважды щелкнем шаблон Web Form. Затем на проектируемую Web-форму перетащим из панели Toolbox элемент управления DropDownList и метку Label. Теперь перейдем к вкладке файла программной поддержки WebForml.aspx.vb и здесь организуем гиперссыл- ки от каждого пункта меню на некоторые Web-страницы, созданные в данной главе. Текст программы приведен в листинге 11.9. ; Листинг 11.9. Организация навигации по Web-страницам i ’ Web-страница демонстрирует, как можно организовать переход ' на разные страницы сайта (гиперссылки) с помощью раскрывающегося 1 списка DropDownList Public Class WebForml Inherits System.Web.UI.Page Protected,Sub Page_Load(ByVai sender As Object, ByVai e As System.EventArgs) Handles Me.Load Page.Title = "Переход на другую страницу:" If Page.IsPostBack = True Then Exit Sub ' Мы могли бы заполнять пункты раскрывающегося списка 1 не при загрузке формы, а при ее инициализации ’ (событие Page_PreInit), тогда не думать про постбэк. ’ Можно писать так: ’ Dim itl As New System.Web.UI.WebControls.Listitem 1 itl.Text = "Сложить два числа" 1 itl.Value = "Summa.aspx" ' DropDownList1.Items.Add(itl)
Программирование Web-ориентированных приложений на Visual Basic 2010 249 ’ А можно короче: ’ DropDownListl.Items.Add(New Listitem("Имя", "значение")) DropDownListl.Items.Add(New Listltem( "Остаться на этой странице", "WebForml.aspx")) DropDownListl.Items.Add(New ListItem( "Проверка достоверности введенных данных", "Validations.aspx")) DropDownListl.Iterns.Add(New Listitem( "Управляемая таблица", "tab.aspx")) ’ Делать ли повторную отправку (постбэк), когда ’ пользователь сделает выбор в раскрывающемся списке? DropDownListl.AutoPostBack = True ’ При AutoPostBack = True будет работать ' событие DropDownListl—SelectedlndexChanged. Labell.Text = "Перейти на другую Web-страницу:" End Sub Private Sub СПИСОК(ByVai sender As Object, ByVai e As System. EventArgs) Handles DropDownListl.SelectedlndexChanged Response.Redirect(DropDownListl.SelectedValue) End Sub End Class Здесь, так же как и в предыдущем примере, мы заполняли пункты раскры- вающегося списка при первой загрузке страницы IsPostBack = False. Это можно было бы делать и при инициализации Web-страницы (событие Page Prelnit). Причем заполняли СПИСОК ПО формату ("Имя", "Значение"). Здесь "Имя" будет ВИДНО В пунктах меню, а "Значение" можно использовать функционально. Кроме того, для раскрывающегося списка мы указали свойство AutoPostBack = True, что приведет к повторной отправке, когда пользователь сделает свой выбор в раскрывающемся списке, причем в этом случае будет доступно событие SelectedlndexChanged. Именно этим событием мы восполь- зовались для перенаправления (Redirect) браузера на выбранную пользовате- лем страницу. Как видно, все выбираемые пользователем Web-страницы являются актив- ными ASPX-страницами. Чтобы добавить их в текущий проект, следует вы- брать в пункте меню Project команду Add New Item и дважды щелкнуть шаблон Web Form. В окне Solution Explorer щелкнем правой кнопкой мыши на названии файла и переименуем новую Web-форму из WebForm2.aspx в Validations.aspx. Аналогично следует добавить вторую вызываемую Web- форму и назвать ее tab.aspx. Перед стартом программы (<F5>) в окне Solution
250 Гпава 11 Explorer правой кнопкой мыши щелкнем по изображению файла WebForml.aspx и в контекстном меню выберем команду Set As Start Page, чтобы программа начала работу с этой страницы. Фрагмент работы данной Web-страницы приведен на рис. 11.13. ? • . . hrrp:nio:.3lhost v < I ii^i[t||jiig||fiijgllj||iiti|ij|||i|^^ i i tepeniii as другую n ехэютрашшу' r j. О.уююя мз 3iей странице -^p \ l Оюзюся из згой с грзнйце i I ...........................I ,J 1 Интернет *p 10G% * f Рис. 11.13. Фрагмент работы Web-страницы, использующей раскрывающийся список Упомянутая функция Redirect является методом объекта Response. Очень часто пользуются методом write объекта Response для вывода в Web-форму каких-либо данных, в том числе для тестирования, отладки программы. Во- обще говоря, в технологии ASP.NET имеются два очень важных объекта: Response и Request. Объект Response содержит данные для передачи от серве- ра клиенту, а объект Request — информацию, полученную от пользователя. В дальнейшем мы будем обращаться к этим двум объектам. Убедиться в работоспособности Web-страницы можно, открыв решение Menu.sln в папке Menu. Пример 82. Передача данных между Web-страницами через параметры гиперссылки Передача данных между Web-страницами одного сайта может происходить через файлы, через объект Session, а может быть реализована через парамет- ры, указанные в гиперссылке. Эти параметры также называют строкой запро- са. Например, гиперссылка <а href="Target.aspx?nl=774n2='3M6opoB'"> после вопросительного знака содержит два параметра — ni и п2.
Программирование Web-ориентированных приложений на Visual Basic 2010 251 Значения этих параметров будут переданы в Web-документ Target.aspx. Про- читать эти параметры в Target.aspx можно с помощью объекта Request. В данном примере создадим две Web-страницы: Source.aspx и Target.aspx. На первой странице Source.aspx с помощью генератора случайных чисел Random выбираем одну из пар ’’имя — фамилия”, затем кодируем их, чтобы они не были видны в адресной строке. Щелчок пользователя по гиперссылке вызы- вает переход на страницу Target.aspx, причем в гиперссылке указаны оба за- кодированных параметра. На этой новой странице с помощью объекта Request получаем оба переданных параметра и выводим их в Web-документе. Для реализации данной задачи запустим VB2010, далее в окне New Project выберем шаблон Empty ASP.NET Web Application, в поле Name укажем имя Ssylka. К текущему проекту добавим Web-форму. Для этого в пункте ме- ню Project выберем команду Add New Item и в появившемся окне дважды щелкнем шаблон Web Form. В этом проекте будем программировать две Web-формы: одну назовем Source.aspx, а вторую — Target.aspx. Сначала запроектируем первую форму, для этого в окне Solution Explorer переименуем файл WebForml.aspx в Source.aspx. Теперь на вкладку Source.aspx из панели Toolbox перенесем элемент управления HyperLink. Содержимое файла программной поддержки Source.aspx.vb приведено в листинге 11.10. Листинг 11,10. Передача данных между \А/еЬ’Страницами через параметры гиперссылки ’ Передача данных между Web-страницами через параметры гиперссылки. 1 В данном примере имеем две Web-страницы: Source.aspx и Target.aspx. 1 На первой странице Source.aspx с помощью генератора случайных чисел ’ Random выбираем одну из пар "имя — фамилия", затем кодируем их, чтобы ’ они не были видны в адресной строке. Щелчок пользователя по ’ гиперссылке вызывает переход на страницу Target.aspx, причем ’ в гиперссылке указаны оба закодированных параметра. Public Class WebForml Inherits System.Web.UI.Page Protected Sub Page_Load(ByVai sender As Object, ByVai e As System.EventArgs) Handles Me.Load 1 Dim Генератор = New Random(DateTime.Now.Millisecond) ’ или просто Dim Генератор = New Random() Dim ЧИСЛО As Integer = Генератор.Next(0, 3)
252 Гпава 11 Dim tl, t2 As String Select Case ЧИСЛО Case 0 tl = "Витя'’ : t2 = "Зиборов" Case 1 tl = "Света" : t2 = "Ломачинская" Case 2 tl = "Андрей" : t2 = "Зиборов-младший" End Select ’ Закодировать tl и t2 для того, чтобы ’ они не были видны в адресной строке tl = System.Web.HttpUtility.UrlEncode(tl) t2 = System.Web.HttpUtility.UrlEncode(t2) HyperLinkl.Text = "Щелкните эту ссылку для " & "передачи данных на страницу Target.aspx" HyperLinkl.NavigateUrl = "Target.aspx?nl=" & tl & "&n2=" & t2 End Sub End Class Как видно из текста программы, при обработке события загрузки страницы Page Load создаем объект генератор класса Random, в скобках задаем начало псевдослучайной последовательности, равное, например, как приведено в комментарии, текущей миллисекунде текущей даты. Используя объект гене- ратор, получаем случайное число в интервале от 0 до 2. Это число, попадая в оператор выбора Select Case, вызывает присваивание пары ’’имя — фами- лия”. Далее функция UrlEncode кодирует tl и t2 для того, чтобы они не были видны в адресной строке браузера. В конце назначены свойства гиперссылки с указанием параметров ni и п2 для передачи их в вызываемую Web-страницу Target.aspx. В результате работы Web-формы Source.aspx в браузере мы по- лучим следующее (рис. 11.14). I . I?; http 7/tocaihcst; 1364/- A' I А? Ф-- http://Jocabost; 1364(Sou..... ; '4i; * LJ -W' ИиШ I Интернет А ЮОА. » Рис. 11.14. Фрагмент работы Web-страницы с гиперссылкой
Программирование Web-ориентированных приложений на Visual Basic 2010 253 Далее щелкнув на этой ссылке, мы попадаем на вызываемую Web-страницу Target.aspx. Однако в нашем проекте еще нет Web-страницы Target.aspx. Для добавления новой Web-формы в пункте меню Project выберем команду Add New Item и в появившемся окне дважды шелкнем на значке шаблона Web Form. В окне Solution Explorer переименуем (щелкнув правой кнопкой мы- ши) новую Web-форму из WebForm2.aspx в Target.aspx. Добавлять в эту фор- му из панели Toolbox ничего из элементов управления не станем, поскольку выводить в форму некоторый текст будем, используя метод write объекта Response. В листинге И.II приведено содержимое файла программной под- держки Target.aspx.vb. : Листинг 11.11. Формирование целевой Web-страницы ’ Передача данных между Web-страницами через параметры гиперссылки. ’ На этой новой странице Target.aspx.vb с помощью объекта Request ’ получаем оба переданных параметра и выводим их в Web-документе. Public Class WebForm2 Inherits System.Web.UI.Page Protected Sub Page_Load(ByVai sender As Object, ByVai e As System.EventArgs) Handles Me.Load ’ Получаем параметры, переданные с Web-страницы, ’ с которой была вызвана данная страница Dim ИМЯ1, ИМЯ2 As String ИМЯ1 = Request.Querystring("Nl") ИМЯ2 = Request.Querystring("N2") Dim URL As String = Request.UrlReferrer.AbsoluteUri , Response.Write("<br />Вы попали на данную Web-” & "страницу со страницы: " & URL & "<br />") Response.Write("<br />Страница " & URL & " передала на " & "данную страницу имя: " & ИМЯ1 & " и фамилию " & ИМЯ2) End Sub End Class В этом программном коде извлекаем переданные параметры nl и п2 методом Querystring объекта Request. С помощью объекта Request получаем также абсолютный URL-адрес вызывающей страницы. Для вывода какого-либо тек- ста на Web-страницу мы могли бы воспользоваться элементом управления Label, однако мы вывели текст "Вы попали..." методом write объекта Response, чтобы продемонстрировать удобство метода write, например, для
254 Гпава 11 отладки программного кода. Тег <br /> использован нами для того, чтобы начать предложение с новой строки. Перед стартом программы в окне Solution Explorer правой кнопкой мыши щелкнем по изображению файла Source.aspx и в контекстном меню выберем команду Set As Start Page, чтобы программа начала работу с этой страницы. Результат работы Web-страницы приведен на рис. 11.15. Рис. 11.15. Целевая Web-страница При использовании строки запроса, т. е. параметров гиперссылки, следует помнить, что некоторые браузеры ограничивают длину URL. Поэтому необ- ходимо следить, чтобы текст в адресной строке не превышал 255 символов. Убедиться в работоспособности Web-страницы можно, открыв решение Ssylka.sln в папке Ssylka. Пример 83. Передача данных формы на другую Web-страницу методами класса Request Имеется возможность предложить пользователю заполнить в форме тексто- вые поля, установить в какое-либо положение переключатели, выбрать ка- кой-либо элемент из списка и т. д., т. е. выполнить какие-либо манипуляции с элементами управления, а затем перейти на другую Web-страницу и отобра- зить на этой новой странице измененные свойства элементов управления предыдущей страницы. Замечу, что это — типичная ситуация. Поставим следующую конкретную задачу. Имеем Web-форму, написанную на "чистом" HTML, т. е. в данной разметке нет тегов ASP, нет JavaScript-кода, нет PHP-скрипта, есть только теги HTML. Web-форма содержит два тексто- вых поля и кнопку для отправки данных. Одно поле приглашает пользователя
Программирование Web-ориентированных приложений на Visual Basic 2010 255 ввести свое имя, а второе— адрес электронной почты. Щелчок на кнопке отправляет данные, заполненные пользователем в форме, на другую Web- страницу для обработки и отображения принятых данных на этой новой странице. Дня решения этой задачи запустим VB2010, закажем новый проект из шабло- на Empty ASP.NET Web Application. Добавим Web-форму, содержащую только теги HTML, для этого в пункте меню Project выберем команду Add New Item и в появившемся окне укажем шаблон HTML page. В окне Solution Explorer переименуем новый появившийся файл в ishod.htm, на вкладке View Code этого файла введем HTML-разметку, представленную на рис. 11.16. lent Objects & Events Рис. 11.16. HTML-разметка Web-страницы, содержащей форму Обратите внимание на тег <fom>: здесь атрибут action (действие) формы ссылается на страницу, которая будет обрабатывать данные, принятые с фор- мы. Атрибут формы method определяет способ передачи данных. Существуют два метода: get и post. Метод get передает все данные формы в конце URL через параметры гиперссылки. Из-за различных ограничений, связанных со спецификой языков и длиной данных, этот метод применяется редко. Метод post передает все данные формы в теле запроса. Этот метод используется чаще, чем get. Элемент <input> является базовым для всех элементов формы. Он использу- ется для внедрения в форму кнопок, графических изображений, флажков, пе-
256 Гпава 11 реключателей, паролей и текстовых полей. Атрибут type определяет тип эле- мента, ДЛЯ текстовых ПОЛеЙ type="text", ДЛЯ КНОПОК type="submit", для флажков type="checkbox" и т. д. Атрибутом name мы будем пользоваться для идентификации элементов управления при обработке данных формы. Атри- бутом value мы воспользовались, чтобы в первом поле по умолчанию каждый раз при запуске формы оказывалась фамилия автора. Заметим, что Visual Studio 2010 содержит удобный HTML-редактор, который зеленым подчеркиванием указывает на синтаксические ошибки, допущенные при вводе HTML-разметки. Для примера на рис. 11.16 мы не заключили зна- чение атрибута type в двойные кавычки, редактор HTML-разметки подчерк- нул этот фрагмент зеленой волнистой линией, и при "зависании" указателя мыши над ним мы получили сообщение об этой ошибке: "Validation (XHTML 1.0 Transitional): Attribute values must be enclosed in quotation marks". Нажмем клавишу <F5> для запуска данного проекта, в результате получим форму, подлежащую заполнению (рис. 11.17). ] / Д. НД://bcalhc.<t. 1332..; м •' X ' ( 4 < - Заполните форму i 1 Веслпг ваше имя I i Отправить { Рис. 11.17. Форма для заполнения и дальнейшей обработки Теперь создадим Web-страницу, которая будет обрабатывать данные, приня- тые с формы. Для этого в пункте меню Project выберем команду Add New Item, в новом появившемся окне укажем шаблон Web Form и добавим его к нашему проекту. В окне Solution Explorer переименуем новый файл в res.aspx. На этой новой странице текущего проекта мы не будем использовать никакие элементы управления. Отображать принятые новой страницей дан- ные будем с помощью объекта Response. На вкладке файла программной под- держки res.asp^.vb введем программный код, приведенный в листинге 11.12.
Программирование Web-ориентированных приложений на Visual Basic 2010 257 \ Листинг 11Л 2. Формирование Web-страницы, получающей-данные' - . ’ Данная Web-страница получает имя пользователя и адрес его ’ электронной почты от Web-формы ishod.htm и отображает эти ’ данные на странице. Public Class WebForml Inherits Systern.Web.UI.Page Protected Sub Page_Load(ByVai sender As Object, ByVai e As System.EventArgs) Handles Me.Load Dim Метод As String = Request.HttpMethod() Dim Имя As String = Request. Item ("name") ’ или Dim Имя As String = Request. Form. Item (’’name”) Dim Почта As String = Request.Item("email") Response.Write("Передача данных произведена методом ’’ + Метод + "<br />") Response.Write("Получено имя: " + Имя + "<br />") Response.Write("Получен адрес электронной почты: " + Почта) End Sub End Class Как видно из программного кода, при обработке события загрузки страницы чтение переданных данных организуем с помощью методов класса Request. Фрагмент работы Web-страницы представлен на рис. 11.18. зянных пражвдена методом POST ~ Полечено имя. Зпооров ' - Т Получен адрес электронной почты: Рис. 11.18. Отображение данных формы на новой странице Убедиться в работоспособности данного проекта можно, открыв решение Передачами в папке Передача. 9 Зак 145
258 Глава 11 Пример 84. Передача значений элементов управления на другую Web-страницу с помощью объекта PreviousPage Покажем, как можно решить задачу из предыдущего примера методами объ- екта PreviousPage. Итак, на начальной Web-странице имеем командную кноп- ку ПЕРЕХОД и текстовое поле, которое заполняет пользователь. После щелчка на кнопке происходит переход на другую Web-страницу. На новой странице отображается содержимое текстового поля и надпись на кнопке из предыдущей страницы. Для решения этой задачи запустим VB2010, закажем новый проект из шабло- на Empty ASP.NET Web Application. Далее добавим в текущий проект на- чальную Web-форму, для этого в пункте меню Project выполним команду Add New Item и в появившемся окне выберем шаблон Web Form. В окне Solution Explorer переименуем (команда Rename в контекстном меню) но- вую появившуюся форму из WebForml.aspx в ishod.aspx. На вкладке конст- руктора формы из панели элементов Toolbox перенесем командную кнопку Button и текстовое поле TextBox. На вкладке программного кода (клавиша <F7>) напишем текст, приведенный в листинге 11.13. Лкглин< 1 ; ЛЗ 3<v>-.•пн.-ние данных на первой Web-странице ’ На начальной Web-странице имеем командную кнопку "ПЕРЕХОД" и ’ текстовое поле, которое заполняет пользователь. После щелчка на ’ кнопке происходит переход на другую Web-страницу. На новой странице ’ отображается содержимое текстового поля и надпись на кнопке ’ из предыдущей страницы. Public Class WebForml Inherits System.Web.UI.Page Protected Sub Page_Load(ByVai sender As Object, ByVai e As System.EventArgs) Handles Me.Load Buttonl.Text = "ПЕРЕХОД" Buttonl.PostBackUrl = "res.aspx" End Sub Protected Sub Buttonl_Click(ByVai sender As Object, ByVai e As EventArgs) Handles Buttonl.Click ’ Response.Redirect("res.aspx") End Sub End Class
Программирование Web-ориентированных приложений на Visual Basic 2010 259 Как видно из программного кода, при обработке события загрузки формы присваиваем надписи на кнопке строку ’’ПЕРЕХОД”, а свойству кнопки PostBackuri назначаем URL-адрес, на который должно перейти управление при щелчке на командной кнопке. Вообще говоря, переход на другую Web- форму можно программировать, так же обрабатывая событие ’’щелчок на кнопке” и используя при этом метод Redirect объекта Response, как показано в комментарии. Замечу, что Web-формы res.aspx, на которую имеем ссылку в программном коде, еще нет в нашем проекте. Добавим эту форму так же, как добавили ис- ходную форму, т. е. используя в пункте меню Project команду Add New Item, выберем шаблон новой формы Web Form. В окне Solution Explorer пере- именуем новую появившуюся форму в res.aspx. На вкладке программного кода res.aspx.vb напишем текст, приведенный в листинге 11.14. Листинг 11.14. Вторая Лхт'-страница Public Class WebForm2 Inherits System.Web.UI.Page Protected Sub Page_Load(ByVai sender As Object, ByVai e As System.EventArgs) Handles Me.Load Try Dim ТПоле As TextBox = СТуре(Page.PreviousPage. FindControl("TextBoxl"), TextBox) Dim Кнопка As Button = СТуре(Page.PreviousPage. FindControl("Buttonl"), Button) ’ Значения элементов управления могут быть также ’ получены с помощью объекта Request ’ Dim SI As String = Request.Item("TextBoxl") ’ Dim S2 As String = Request.Item("Buttonl") Response.Write("На начальной странице: <br />") Response.Write(" — содержимое текстового поля: " + ТПоле.Text + "<br />") Response.Write(" — надпись на кнопке: " + Кнопка.Text) Catch ex As Exception Response.Write("Начальная Web-страница должна " + "содержать<br />текстовое поле и командную " + "кнопку.<br />" + ex.Message) End Try End Sub End Class
260 гпава 11 Как видно из данного программного кода, новая, результирующая форма не содержит ни одного элемента управления. Вывод текста в форму осуществ- ляем С ПОМОЩЬЮ метода Write объекта Response. Чтобы вывести в новую форму значения элементов управления первоначальной формы, воспользуем- ся методом FindControl объекта PreviousPage. На вход этого метода подадим идентификатор (ID) соответствующего элемента управления, указанного в HTML-разметке первоначальной формы ishod.aspx. Функция FindControl воз- вращает объект класса web.ui.control, его удобно конвертировать в объект класса TextBox или Button с помощью функции СТуре о. В комментарии пока- зано, как можно получить значения элементов управления первоначальной формы также С ПОМОЩЬЮ объекта Request. Перед тем как запустить созданный проект на выполнение, в окне Solution Explorer назначим в качестве стартовой страницы проекта файл ishod.aspx, для этого в контекстном меню для этого файла выберем команду Set As Start Page. На рис. 11.19 показана исходная форма ishod.aspx с текстовым полем, подлежащим заполнению, и командной кнопкой. ' jf? hUp./'iccalhosV1Г Ж, ’* л ; | Ис одаривай гпупнэ 1 - ; ? ОЙЙДО ; Рис. 11.19. Первоначальная форма < * •£., hrtP 105?/^ • л i \ & x$http://io€aihost:10S2/re5,... ’’ч * •...•/ | | На н ач альной с транице: j I содержимое текстового поля: Не испарив ай гл гп из ‘ | I - надпись на кнопке' 11ЕРлХОД i I Интернет \1иСЛ * ? Рис. 11.20. Результирующая форма
Программирование Web-ориентированных приложений на Visual Basic 2010 261 На рис. 11.20 продемонстрирована результирующая форма, где отображены значения элементов управления первоначальной формы. Убедиться в работоспособности Web-страницы можно, открыв решение Передача2.з1п в папке Передача2. Пример 85. Отображение табличных данных в Web-форме с помощью элемента управления GridView В данном примере покажем, как можно вывести какие-либо данные, напри- мер, два строковых массива в виде таблицы в Web-форму с помощью элемен- та управления GridView (просмотр или обзор сетки данных в таблице) и объ- екта DataTable. Мы решали подобную задачу для Windows-приложения. Ме- жду тем для Web-приложения это также типичная задача, но она имеет некоторые особенности, в частности, и там и здесь в выводе таблицы прини- мают участие похожие элементы управления (DataGridView и GridView), но свойства и методы этих объектов в разных приложениях немного отличают- ся. В данной задаче таблица телефонов представлена в виде двух строковых массивов. Требуется минимальными усилиями вывести в Web-форму эти массивы в виде таблицы. Для решения данной задачи запускаем VB2010, заказываем новый проект из шаблона Empty ASP.NET Web Application, в поле Name вводим имя TabGrdWeb. К текущему проекту добавим Web-форму. Для этого в пункте меню Project выберем команду Add New Item и в появившемся окне дважды щелкнем шаблон Web Form. Далее перетащим в форму из панели Toolbox (из подраздела Data) элемент управления GridView. Содержимое файла программной поддержки WebForml.aspx.vb приведено в листинге 11.15. j Листинг 1L15. Вывод табличных данных в Web-форму .. . । с помощью элемента управления GridV/ew .' . . . . ’ Вывод табличных данных в Web-форму с помощью элемента управления ’ GridView. В данной Web-странице организован вывод двух строковых ’ массивов в таблицу в Web-форму с помощью элемента управления • GridView и объекта DataTable. Public Class WebForml Inherits System.Web.UI.Page Protected Sub Page_Load(ByVai sender As Object, ByVai e As System.EventArgs) Handles Me.Load Page.Title = "Вывод таблицы в Web-форму"
262 Глава 11 Dim Imena () As String = {’’Андрей — раб’’, ”ЖЭК", ’’Мама — дом", "Карапузова Таня’’} DimTeK) As String = {"274-88-17", "22-345-72", "570-38-76", "201-72-23-прямой моб’’} Dim dt As New DataTabie ’ Заполнение шапки таблицы dt.Columns.Add("ИМЕНА") dt.Columns.Add("НОМЕРА ТЕЛЕФОНОВ") ’ Заполнение клеток (ячеек) таблицы For i As Short = 0 To 3 dt.Rows.Add(New String() {Imena(i), Tel(i)}) Next ’ Немного другое свойство, чем в WindowsApplication GridViewl.Caption = "Таблица телефонов" GridViewl.Borderwidth = WebControls.Unit.Pixel(2) GridViewl.BorderColor = Drawing.Color.Gray GridViewl.DataSource = dt ’ Этого нет в WindowsApplication GridViewl.DataBind() End Sub End Class Содержание программного кода очевидно. Вначале инициализируются два строковых массива: массив имен и массив телефонов, далее с помощью этих массивов заполняются ячейки объекта DataTabie. Затем этот объект назнача- ется нами ИСТОЧНИКОМ данных DataSource ДЛЯ сетки данных GridViewl. Фраг- мент работы данной Web-страницы показан на рис. 11.21. f W Вывод табМцы в Web-ф... : . = ’ I Таблица телефонов | ;..ИМШАЛ’’'^11ОМЕРА1ЕЛЕФС>НОВ^ >; \ Андрей — раб 2 7 4 - 8 S -17 I ГАЭК 22-345-Л2 j г АЫмз~дом 5*0-38-76 | .^Карапузова Таня 201 -*2-23-прямой моб { Интернет Рис. 11.21. Фрагмент работы Web-страницы с табличными данными
Программирование Web-ориентированных приложений на Visual Basic 2010 263 Замечу, что данную таблицу можно было бы вывести с помощью элемента управления DataList, однако в этом случае пришлось бы задавать шаблоны Template для каждой колонки в ASPX-файле, что на субъективный взгляд ав- тора не технологично. Убедиться в работоспособности Web-страницы можно, открыв решение TabGrdWeb.sln в папке TabGrdWeb. Пример 86. Отображение в Web-форме хэш-таблицы Хэш-таблица— это таблица из двух столбцов, один из них содержит ключи, а второй — значения. То есть каждая строка в этой таблице образует пару ’’ключ — значение”. Имея ключ в хэш-таблице, можно быстро найти значе- ние. Хэш-таблицу можно назвать таблицей соответствий. Простейшим при- мером хэш-таблицы является таблица телефонов, которая участвовала в пре- дыдущем разделе, однако там мы программировали ее просто как два масси- ва. Если эти два массива поместить в хэш-таблицу, то ключом в данном случае было бы фио, а значением — номер телефона. При этом программиро- вание поиска значения по ключу оказалось бы тривиальной задачей, опера- ция добавления и удаления пары также упрощается, поскольку хэш-таб- лица— это объект, который содержит соответствующие эти и другие методы. В реальной жизни много разнообразных примеров представления данных в виде хэш-таблицы. Например, таблица, где расширения файлов (txt, jpg, mdb, xls) являются ключами, а соответствующими значениями— про- граммы, которые открывают файлы с такими расширениями (Notepad.exe, Pbrush.exe, MSAccess.exe, Excel.exe). Следующим примером является англо- русский и другие словари. База данных доменных имен, которая доменному имени сопоставляет IP-адрес. По принципу хэш-таблицы организованы объ- екты viewstate И Session технологии ASP.NET. Поставим следующую задачу, сопоставим в хэш-таблице государства в каче- стве ключей, а их столицы — в качестве значений. Далее, используя элемент управления GridView, выведем эту хэш-таблицу на Web-страницу. Для этого запустим VB2010, закажем новый проект шаблона Empty ASP.NET Web Application, в поле Name укажем имя Hash Grid. К текущему проекту доба- вим Web-форму. Для этого в пункте меню Project выберем команду Add New Item и в появившемся окне дважды щелкнем шаблон Web Form. Далее перетащим в форму из панели Toolbox (из подраздела Data) элемент управления GridView. Содержимое файла программной поддержки WebForml.aspx.vb приведено в листинге 11.16.
264 Глава 11 Листинг 1116. Хэш-таблица в Web-форме 1 Вывод в Web-форму хэш-таблицы, которая позволяет поставить • в соответствие государства их столицам. То есть в качестве ключей • имеем государства, а их столицы — в качестве значений. Далее, ’ используя элемент управления GridView, программа выводит • эту хэш-таблицу на Web-страницу. Public Class WebForml Inherits System.Web.UI.Page Protected Sub Page_Load(ByVai sender As Object, ByVai e As System.EventArgs) Handles Me.Load Page.Title = "Пример хэш-таблицы" Dim h = New System.Collections.Hashtable h("Украина") = "Киев" h.Add("Россия", "Москва") h("Белоруссия") = "Минск" Dim dt As New DataTable ’ Заполнение шапки таблицы dt.Columns.Add("ГОСУДАРСТВА") dt. Columns . Add ("СТОЛИЦЫ") Dim ПЕРЕЧИСЛИТЕЛЬ As IDictionaryEnumerator = h.GetEnumerator While ПЕРЕЧИСЛИТЕЛЬ.MoveNext = True dt.Rows.Add(New String() {ПЕРЕЧИСЛИТЕЛЬ.Key, ПЕРЕЧИСЛИТЕЛЬ.Value}) End While ' Немного другое свойство, чем в WindowsApplication GridViewl.Caption = "Таблица государств" GridViewl.Borderwidth = WebControls.Unit.Pixel(2) GridViewl.BorderColor = Drawing.Color.Gray ’ Источник данных для GridView GridViewl.DataSource = dt ’ Этого нет в WindowsApplication GridViewl.DataBind() End Sub End Class Здесь при обработке события загрузки Web-страницы создается объект клас- са Hashtable. Хэш-таблица заполняется тремя парами "код — значение", при-
Программирование Web-ориентированных приложений на Visual Basic 2010 265 чем, как показано в программном коде, допустимы обе формы записи: через присваивание и посредством метода Add. Далее создается вспомогательный объект DataTable, который следует заполнить данными из хэш-таблицы. Хэш- таблица имеет метод GetEnumerator, который возвращает перечислитель типа idictionaryEnumerator. Перечислитель позволяет перемещаться по рядам таб- лицы в цикле while и таким образом получить все пары из хэш-таблицы. В этом цикле происходит заполнение объекта DataTable. Далее, также как и в предыдущем примере, для GridViewl указываем в качестве источника данных заполненный объект DataTable. Пример работы данной Web-страницы пока- зан на рис. 11.22. | гл дс Пример хэигтаблицы I аблии.а государств {ГОСУ^РСТ В А СТОЛИЦЫ^ ^Белоруссия Минск рЛфшшз Киев I Рис. 11.22. Фрагмент работы Web-страницы с хэш-таблицей В заключение отметим, что хэш-таблицу называют ассоциативным масси- вом, но в этом ’’массиве” роль индекса играет ключ. Для реализации хэш- таблицы можно было бы использовать обычный одномерный массив, в кото- ром элементы с четным индексом являются ключами, а с нечетным — значе- ниями. Однако для реализации трех основных операций с хэш-таблицей: до- бавления новой пары, операцию поиска и операцию удаления пары по ключу потребовалось бы отлаживать довольно-таки много строчек программного кода. Убедиться в работоспособности Web-страницы можно, открыв решение Hash Grid.sin в папке Hash_Grid.
266 Глава 11 Пример 87. Чтение/запись текстового файла Web-приложением Активная Web-страница может сохранять, а также читать данные на диске в каких-либо файлах, в том числе текстовых. Принцип чтения/записи на диск текстовых файлов такой же, как и в Windows-приложениях, однако есть не- которые особенности. Поставим задачу написать Web-приложение, читающее текстовый файл в текстовое поле, пользователь имеет возможность редакти- ровать текст и сохранять его в том же файле. Для решения поставленной задачи запустим VB2010, закажем новый проект из шаблона Empty ASP.NET Web Application, имя Web-приложения — RW txt. К текущему проекту добавим Web-форму. Для этого в пункте меню Project выберем команду Add New Item и в появившемся окне дважды щелкнем шаблон Web Form. В конструкторе формы из панели Toolbox перетащим мышью текстовое поле TextBox и две командные кнопки Button. Содержимое файла программной поддержки приведено в листинге 11.17. Листинг 11,17. Чтение/запись текстового файла ' • . • ' - ’ Чтение/запись текстового файла Web-приложением. Web-приложение ’ читает текстовый файл в текстовое поле, а пользователь имеет ’ возможность редактировать текст и сохранять его в том же файле. Public Class WebForml Inherits System.Web,UI.Page Dim filename As String • Чтобы русские буквы читались нормально, • объявляем объект КОДИРОВКА Dim КОДИРОВКА As System.Text.Encoding = System.Text.Encoding.GetEncoding(1251) Protected Sub Page_Load(ByVai sender As Object, ByVai e As System.EventArgs) Handles Me.Load Page.Title = "Здесь кодировка Winl251" Buttoni.Text = "Читать" Button2.Text = "Сохранить" • Разрешаем многострочие TextBoxi.TextMode = TextBoxMode.MultiLine filename = Request.PhysicalApplicationPath & "txt.txt" End Sub
Программирование Web-ориентированных приложений на Visual Basic 2010 267 Private Sub Чтение(ByVai sender As Object, ByVai e As System.EventArgs) Handles Buttonl.Click Try ' Создаем экземпляр StreamReader для чтения из файла Dim ЧИТАТЕЛЬ As New 10. StreamReader (filename, КОДИРОВКА) TextBoxl.Text = ЧИТАТЕЛЬ.ReadToEnd() ЧИТАТЕЛЬ.Close() Catch Exc As System.10.FileNotFoundException Response.Write("Нет такого файла <br />") Catch Ex As Exception ' Отчет о других ошибках Response.Write("Ошибка чтения фай i . " & Ex.Message & " <br />") End Try End Sub Private Sub Сохранение(ByVai sender As Object, ByVai e As System.EventArgs) Handles Button2.Click Try ’ Создание экземпляра StreamWriter для записи в файл Dim ПИСАТЕЛЬ As New 10.StreamWriter(filename, False, КОДИРОВКА) ПИСАТЕЛЬ.Write(TextBoxl.Text) ПИСАТЕЛЬ.Close() Catch EXC As Exception ’ Отчет обо всех возможных ошибках Response.Write("Ошибка записи файла " & EXC.Message & " <br />") End Try End Sub End Class В начале программного кода объявляем имя файла filename и объект кодировка в качестве внешних переменных по отношению к процедурам клас- са, чтобы они были видны из всех процедур обработки событий. При загрузке страницы Page Load задаем надписи на кнопках Buttonl и Button2, а текстовое поле переводим в режим Multiline, т. е. разрешаем размещать текст на не- скольких строчках. Далее, поскольку мы не можем разрешить пользователю выбирать папку на удаленном сервере для размещения файла, в качестве та- кой папки указываем папку, где расположено текущее Web-приложение. При этом мы не сможем воспользоваться методом GetCurrentDirectory класса ю. Directory, поскольку эта функция нам укажет на системную папку C:\Windows\system32. Поэтому воспользуемся методом PhysicaiAppiicationPath объекта Request. При обработке события ’’щелчок на кнопке” Читать читаем
268 Гпава 11 текстовый файл, используя объект StreamReader. Также как и при записи фай- ла, данная процедура ничем не отличается от программирования ее в Windows-приложении. Однако существует большая вероятность получить отказ в доступе к файлу. Операционная система, в зависимости от настроек, может выдать сообщение об ошибке сервера в вашем приложении вследствие отказа в доступе к ваше- му текстовому файлу. То есть можем получить запрет на запись файла на диск сервера. В этом сообщении об ошибке указано, что следует на вкладке Безопасность свойств текстового файла разрешить чтение/запись. Однако весьма вероятна ситуация, когда, щелкнув правой кнопкой мыши на изобра- жении файла txt.txt и выбрав команду Свойства, мы получим свойства файла в таком виде, как показано на рис. 11.23. Рис. 11.23. Вкладки окна свойств файла Как видно, в окне свойств файла txt.txt отсутствует вкладка Безопасность. Чтобы ее получить, следует в Проводнике выбрать пункт меню Сервис | Свойства папки и в появившемся окне на вкладке Вид снять флажок Ис- пользовать простой общий доступ к файлам. Далее — щелчок на кнопках Применить и ОК (рис. 11.24). Рис. 11.24. Вкладки окна свойств папки
Программирование Web-ориентированных приложений на Visual Basic 2010 269 Теперь опять перейдем к свойствам файла txt.txt. Вкладка Безопасность, как видно, уже появилась. На вкладке Безопасность щелкнем на кнопке Доба- вить, перейдя таким образом в окно Выбор. Далее нажмем кнопки Допол- нительно, Поиск и, выбрав в появившемся списке имя пользователя ASP.NET, щелкнем на кнопке ОК. Теперь на вкладке Свойства в строках Чтение и Запись установим флажок разрешения и нажмем кнопки Приме- нить и ОК (рис. 11.25). I Рис. 11.25. Вкладка Безопасность окна свойств файла Рис. 11.26. Фрагмент работы Web-страницы, осуществляющей чтение/запись текстового файла
270 Гпава 11 Теперь еще раз запускаем Web-приложение и убеждаемся в его корректной работе. На рис. 11.26 показан фрагмент работы созданной Web-страницы. Используя инструмент чтения/записи текстового файла, можно обмениваться данными между страницами Web-приложения, организовать форум на Web- сайте, гостевую книгу, счетчик посещений и пр. Убедиться в работоспособности Web-страницы можно, открыв соответст- вующее решение в папке RW_txt. Пример 88. Программирование счетчика посещений сайта с использованием базы данных и объекта Session Поставим задачу создать счетчик посещения вашего сайта. Каждое посеще- ние будем фиксировать в виде записи в базе данных MS Access. Чтобы чита- тель мог реально повторить описываемые действия, подробно их рассмотрим. Запустим офисное приложение MS Access, далее в меню Файл выберем команду Создать | Новая база данных, файл — Web.mdb. Затем создадим "шапку" новой таблицы в режиме конструктора. Имена полей и типы данных приведены на рис. 11.27. I Файл Правда Вид Вставка Сервис > Рис. 11.27. Проектирование полей таблицы базы данных Как видно, автор не предусмотрел поля типа Счетчик, а ведь нам нужно счи- тать именно количество посещений, т. е. количество записей. Сделано это сознательно, т. к. количество записей в базе данных выяснить очень просто, например, с помощью SQL-запроса: SELECT COUNT(*) FROM [Таблица посещений Web-страницы] Теперь запустим VB2010, закажем новый проект из шаблона Empty ASP.NET Web Application, назовем его Counter. К текущему проекту доба- вим Web-форму. Для этого в пункте меню Project выберем команду Add New Item и в появившемся окне дважды щелкнем по шаблону Web Form.
Программирование Web-ориентированных приложений на Visual Basic 2010 277 Здесь из панели Toolbox перенесем на Web-форму метку Label, куда будем выводить количество посещений данной страницы. Метку Label разместим пока в самом верху формы, но, в конце концов, ее следует разместить скром- но в самом низу страницы. Содержимое файла программной поддержки WebForml.aspx.vb приведено в листинге 11.18. Листинг 11.18. Счетчик посещений сайта ; ' Web-приложение, реализующее счетчик посещений сайта с ' использованием базы данных и объекта Session. ' Импортируем пространство имен: Imports System.Data.OleDb Public Class WebForml Inherits System.Web.UI.Page Protected Sub Page_Load(ByVai sender As Object, ByVai e As System.EventArgs) Handles Me.Load Page.Title = ’’Счетчик посещений сайта" If Page.IsPostBack = True Then Exit Sub ' При первой загрузке страницы ' Выясняем IP-адрес посетителя сайта Dim 1Р_адрес As String = Request.UserHostAddress Dim URL_a,npec As String Try ' Определение, с какой Web-страницы вы сюда пришли URL_a,npec = Request.UrlReferrer.AbsoluteUri Response.Write("<br /xbr />Вы пришли на эту" & " страницу со страницы " & URL_a,npec) Catch exl As System.NullReferenceException ’ Если пришли на эту страницу, набрав URL-адрес ' в адресной строке браузера URL_a,Kpec = "Адресная строка браузера" Response.Write("<br /><Ьг />Вы пришли на эту " & "страницу набрав URL-адрес в адресной строке") End Try Response.Write ("<br /xbr />Вы пришли на эту страницу " & "с IP-адреса ’’ & 1Р_адрес)
272 Гпава 11 ’ МАНИПУЛЯЦИИ С БД О ПОСЕЩЕНИИ ПОЛЬЗОВАТЕЛЯ. ’ Строка подключения Dim СтрокаПодкл As String = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" & Server.MapPath("Web.mdb") ’ Создание экземпляра объекта Connection Dim CONNECTION = New OleDbConnection(СтрокаПодкл) Try ’ Открытие подключения CONNECTION.Open() Catch ex2 As Exception Response.Write ("<br /xbr />’’ & ex2.Message) End Try Dim SQL_3anpoc As String Dim COMMAND As New OleDbCommand ’ ЕСЛИ ОБ ЭТОМ ПОСЕЩЕНИИ ЕЩЕ НЕТ ЗАПИСИ If Page.Session( "ЕСТЬ ЛИ ЗАПИСЬ ОБ ЭТОМ ПОСЕЩЕНИИ?") О "ДА" Then ’ ДОБАВЛЕНИЕ ЗАПИСИ В БД О ПОСЕЩЕНИИ Dim ДАТА As String = Now ’ Строка SQL-запроса SQL_3anpoc = "INSERT INTO [Таблица посещении Web-страницы] " & "([Дата посещения], [IP-адрес посетителя], " & "[С какой страницы пришли]) VALUES ( ”' & ДАТА & & 1Р_адрес & & URL_anpec & ’”) ” ’ Создание объекта Command с заданием SQL-запроса COMMAND.CommandText = SQL_3anpoc ’ Для добавления записи эта команда обязательна COMMAND.Connection = CONNECTION Try ’ Выполнение команды SQL, т. е. ЗАПИСЬ В БД COMMAND.ExecuteNonQuery() Response.Write( "<br /xbr />В таблицу БД посещений добавлена запись") ’ ТЕПЕРЬ ПОЯВИЛАСЬ ЗАПИСЬ ОБ ЭТОМ ПОСЕЩЕНИИ Page.Session("ЕСТЬ ЛИ ЗАПИСЬ ОБ ЭТОМ ПОСЕЩЕНИИ?") = "ДА"
Программирование Web-ориентированных приложений на Visual Basic 2010 273 Catch ехЗ As Exception Response.Write("<br /xbr />” & ехЗ.Message) End Try End If ’ ОПРЕДЕЛЕНИЕ КОЛИЧЕСТВА ЗАПИСЕЙ О ПОСЕЩЕНИИ ’ Новый SQL-запрос — это одна ячейка в новой таблице SQL_запрос = "SELECT COUNT(*) FROM [Таб" & "лица посещений Web-страницы]" COMMAND.CommandText = SQL_3anpoc COMMAND.Connection = CONNECTION ’ ExecuteScalar выполняет запрос и возвращает первую 1 колонку первого ряда таблицы запроса Dim КОЛ_ВО As Integer Try КОЛ_ВО = COMMAND.ExecuteScalar() Catch ex4 As Exception Response. Write ("<br /xbr />’’ & ex4. Message) End Try CONNECTION.Close() Labell.Text = "Количество посещений страницы = " & КОЛ_ВО End Sub End Class Как видно из программного кода, программирование счетчика посещений реализовано при обработке событий загрузки Web-страницы Page Load, при- чем при ее первой загрузке, когда isPostBack = False. Используя объект Request, определяем IP-адрес посетителя данной Web-страницы. Далее с по- мощью этого же объекта Request и блока Try...Catch определяем, с какой Web-страницы пользователь перешел на данную страницу. Если попытка (тгу) определить оказалось неудачной, то управление переходит на Exception и делается вывод, что пользователь оказался на данной странице, набрав URL-адрес в адресной строке своего браузера. Для вывода текста в форму использован метод Response.write. Роль этой печати здесь вспомогательная, как бы отладочная. Читатель может ее закомментировать или вовсе удалить. Далее происходит подготовка к записи строки из трех полей в базу данных. Вначале задаем строку подключения к базе данных, затем — непосредствен- ное подключение Connection. Далее перед непосредственной записью строки посещения в базу данных происходит проверка, есть ли (зарегистрирована ли 10 Зак. 145
274 Гпава 11 уже) запись об этом посещении. Может быть, пользователь в своем браузере просто обновил страницу путем нажатия клавиши <F5>. Вы можете себе представить, читатель, какой соблазн появляется у пользователя нажимать <F5>, если он видит, что после каждого нажатия увеличивается количество посещений сайта! Чтобы избежать этого, воспользуемся объектом страницы Page.Session. В технологии ASP.NET каждое Web-приложение при обращении к нему пользователя (клиента) создает объект Page.Session, этот объект называют сессией или сеансом пользователя. Объект Session содержит в себе методы для создания коллекции данных. Причем созданная коллекция данных на од- ной странице Web-приложения оказывается доступной на любой другой странице данного приложения. Даже если пользователь перешел на другое Web-приложение (на другой Web-узел), а затем вернулся в данное приложе- ние, то исходная коллекция данных сессии будет сохранена. Она будет со- хранена до тех пор, пока пользователь не закрыл свой Web-браузер. Однако время жизни (лимит времени) сессии все же ограничено параметром timeout. По умолчанию время жизни равно 20 минутам, его можно регулировать В файле программной поддержки СВОЙСТВОМ объекта Session.Timeout. Программировать создание сессии пользователя и получение из нее инфор- мации, доступной во всем приложении, несложно. Например, включение бавление) в коллекцию данных сессии пар ’’имя (ключ) — значение" можно программировать таким образом: Session ("Имя пользователя") = "Андрей” ИЛИ Session. Add ("Имя пользователя", "Андрей"). На любой другой странице дан- ного Web-приложения имеем доступ к данным, записанным в коллекцию данных сессии: Labeli .Text = Session ("Имя пользователя") ИЛИ Labeli.Text = Session, item ("Имя пользователя"). Таким образом можно обмениваться дан- ными между страницами Web-приложения. Теперь вернемся к добавлению в БД записи о данном посещении страницы. После команды ExecuteNonQuery запись в базу данных будет добавлена, затем сразу после этого включаем в коллекцию текущей сессии пару Page. Session ("есть ли запись об этом посещении?")="да". Теперь эта пара будет существовать не только после нажатия клавиши <F5> (команда в брау- зере Обновить страницу), но и после того, как пользователь покинет данное Web-приложение и затем вернется в него опять. (Но при этом не будет за- крывать свой Web-браузер.) Поэтому в программном коде, прежде чем до- бавлять запись в базу данных о посещении пользователя, предусмотрена про- верка с помощью коллекции объекта Session. Фрагмент работы счетчика посещений представлен на рис. 11.28. Теперь давайте проверим полученный IP-адрес. Является ли он действитель- но адресом нашего локального компьютера в Интернете? Для этого на панели
Программирование Web-ориентированных приложений на Visual Basic 2010 275 задач вашего компьютера найдем значок Подключение по локальной сети. В контекстном меню укажем пункт Состояние, здесь на вкладке Поддержка увидим свой правильный IP-адрес. Он будет отличаться от выведенного в форму. Почему? Дело в том, что фрагмент работы данной программы полу- чен на локальном сервере, поэтому и IP-адрес мы получили как адрес из внутренней подсети. После того как проект Web-приложения будет скопиро- ван на удаленный сервер, предоставляющий Web-хостинг, мы получим кор- ректный IP-адрес. Как указывалось ранее, три первых строки, выведенные в форму, носят отладочный характер и могут быть удалены из программного кода. Рис. 11.28. Фрагмент работы Web-страницы, подсчитывающей посещеня Убедиться в работоспособности Web-страницы можно, открыв решение Counter.sln в папке Counter. Пример 89. Чтение/запись cookie-файлов Cookie (от англ, cookie— печенье)— это небольшой фрагмент данных (обычно до 4096 байт), созданный Web-сервером и хранимый на компьютере клиента (пользователя) в виде файла. Каждый раз при запросе какой-либо страницы сайта браузер пользователя посылает серверу в HTTP-запросе этот cookie-файл. Данные, записанные в cookie-файле, обычно используются для аутентификации пользователя, т. е. для его распознавания среди прочих пользователей, для хранения его персональных предпочтений, настроек поль- зователя, для ведения статистики пользователей и пр. В самом начале использования cookie было для определения, посещал ли пользователь сайт ранее.
276 Гпава 11 Зайдя на любой сайт, вы можете увидеть активные на данном сайте cookie, набрав в адресной строке браузера следующее: javascript:alert("Cookies: "tdocument.cookie) В ответ ваш Web-браузер покажет вам примерно такое окно, как приведено на рис. 11.29. Рис. 11.29. Отображение активного cookie на некотором сайте В этом окне содержатся те сведения, которые сервер некоторого Web-узла закодировал о вас в cookie-файле, записанном на ваш компьютер. В данном примере мы научимся читать cookie при загрузке страницы и запи- сывать cookie-файл при нажатии пользователем командной кнопки. То есть постановка задачи следующая. Web-страница предлагает посетителю ввести данные о себе: его имя и род занятий. При нажатии кнопки Запись Cookie введенные в текстовые поля сведения будут записаны в cookie-файл. Этот cookie-файл будет храниться на компьютере пользователя сутки. В течение этих суток, каждый раз вызывая данную страницу, в текстовых полях мы бу- дем видеть введенные нами сведения, которые мы можем тут же исправлять и опять записывать в cookie. Фрагмент функционирования подобной Web- страницы приведен на рис. 11.30. Рис. 11.30. Фрагмент работы Web-страницы записи cookie
Программирование Web-ориентированных приложений на Visual Basic 2010 277 Для реализации поставленной задачи запустим VB2010, закажем новый проект из шаблона Empty ASP.NET Web Application, назовем его Cookie. К текущему проекту добавим Web-форму. Для этого в пункте меню Project выберем команду Add New Item и в появившемся окне дважды щелкнем по шаблону Web Form. Затем из панели Toolbox перенесем в проектируемую Web-форму две метки Label, два текстовых поля TextBox и командную кнопку Button. Содержимое файла программной поддержки WebForml.aspx.vb приведено в листин- ге 11.19. ; Листинг 11Л9. Чтение/запись cookie-файлов ' . ’ Чтение/запись cookie-файлов. Web-страница предлагает посетителю ’ ввести данные о себе: имя и род занятий. При нажатии кнопки ’ "Запись Cookie" введенные в текстовые поля сведения будут ’ записаны в cookie-файл. Этот cookie-файл будет храниться на ’ компьютере пользователя сутки. В течение этих суток, ’ каждый раз вызывая данную страницу, в текстовых полях мы будем 1 видеть введенные нами сведения, которые мы можем тут же ’ исправлять и опять записывать в cookie. Public Class WebForml Inherits System.Web.UI.Page Protected Sub Page_Load(ByVai sender As Object, ByVai e As System.EventArgs) Handles Me.Load Page.Title = "Введите данные о себе" ’ При повторной отправке выйти из процедуры If Page.IsPostBack = True Then Exit Sub Labeli.Text = "Имя посетителя" Label2.Text = "Род занятий" Buttonl.Text = "Запись Cookie" ’ ЧТЕНИЕ COOKIE. ’ Cookie может быть целая коллекция 1 Dim CookieN As HttpCookieCollection Dim Cookiel As HttpCookie ’ Читаю только один раздел cookie "О посетителе страницы" Cookiel = Request.Cookies("О посетителе страницы") ’ Если на машине клиента нет такого cookie If Cookiel Is Nothing Then Exit Sub
278 Глава 11 ’ Если есть, то заполняю текстовые поля из cookie TextBoxi.Text = Cookiel.Item("Имя посетителя") TextBox2.Text = Cookiel.Item("Род занятий посетителя") End Sub Private Sub Buttonl_Click(ByVai sender As Object, ByVai e As System.EventArgs) Handles Buttoni.Click ’ ЗАПИСЬ COOKIE. Dim Cookiel As HttpCookie Cookiel = New HttpCookie("О посетителе страницы") ’ Запись двух пар "имя (ключ) - значение" Cookiel.Values("Имя посетителя") = TextBoxi.Text Cookiel.Values("Род занятий посетителя") = TextBox2.Text ’ Установка даты удаления cookie: сейчас плюс один день Cookiel.Expires = DateTime.Now.AddDays(1) ’ Добавление раздела "О посетителе страницы" в cookie-файл Response.Cookies.Add(Cookiel) End Sub End Class Здесь ВО время загрузки страницы Page_Load при isPostBack = False инициа- лизируем надписи на метках Label, а затем читаем cookie-файл посредством объекта Request. В данном случае функция Request. Cookies возвращает раз- дел cookie-файла "О посетителе страницы”. В данной программе мы преду- смотрели только один раздел, хотя их может быть несколько (коллекция HttpCookieCoiiection). Если компьютер пользователя не содержит данного cookie-файла, то программируем выход Exit Sub из данной процедуры. Если cookie прочитан, то текстовые поля заполняем соответствующими значе- ниями. При обработке события щелчок на кнопке Запись Cookie происходит запись в cookie-файл, в его раздел "О посетителе страницы" двух пар "имя — зна- чение" имя посетителя и Род занятий, скопированное из текстовых полей. В предложении Cookie.Expires указываем срок хранения cookie. Если дата не указана, то cookies удаляются сразу, как только пользователь закроет браузер. Например, интернет-магазин может использовать cookie для хранения назва- ний товаров, которые пользователь выбрал и поместил в виртуальную корзи- ну покупок. В таком случае даже если пользователь закроет браузер, не со- вершив покупки, то при последующем посещении интернет-магазина ему не придется формировать корзину заново. Вернемся к нашему программному коду. Оператор Add(Cookiel) объекта Response.Cookies добавляет раздел "О посетителе страницы" в cookie-файл.
Программирование Web-ориентированных приложений на Visual Basic 2010 279 Теперь давайте найдем этот cookie-файл на винчестере вашего компьютера. Различные браузеры для разных операционных систем пишут cookie-файлы в различные папки. Скорее всего, вы найдете данный cookie в папке C:\Documents and 8еЦт§з\Администратор\Соок!ез. Структура имени cookie- файла следующая: Имя_пользователя_компьютера@имя_сервера[1] Поскольку в данном случае речь идет о локальном сервере, то скорее всего имя обсуждаемого в данном разделе cookie-файла будет: aflMMHMCTpaTop@localhost[2].txt Поскольку cookie — это текстовый файл, его можем легко открыть, напри- мер, с помощью Блокнота (рис. 11.31). Рис. 11.31. Содержимое cookie-файла Как видно, первая строка содержимого cookie-файла — это имя раздела, за- тем пары "имя — значение", запрограммированные нами в программе, далее имя сервера и служебная информация. В заключении замечу, что cookies представляют собой лишь данные, а не программный код, т. е. они не могут стереть или прочитать информацию с компьютера пользователя, поэтому не стоит демонизировать cookie. Убедиться в работоспособности Web-страницы можно, открыв решение Cookie.sln в папке Cookie. Пример 90. Вывод изображения в Web-форму Отображение изображения в Web-форме является тривиальной задачей. Для ее решения Visual Studio имеет класс image пространства имен
280 Гпава 11 System.web.ui.webcontrois. С помощью свойства imageUri этого класса задаем URL-адрес изображения, посредством AiternateText задаем альтернативный текст, отображаемый в элементе управления Image, когда изображение не- доступно. Немножко усложним задачу и поставим ее в следующем виде. На странице имеем некоторое изображение, при щелчке мышью на нем изобра- жение увеличивается вдвое без перезагрузки Web-страницы. Сначала решим эту задачу, используя исключительно HTML-разметку с не- большим включением программного кода на JavaScript. Очень удобно вы- полнить HTML-разметку в редакторе Visual Studio, поэтому запустим систе- му VB2010 и создадим новый проект из шаблона Empty ASP.NET Web Application, назовем его Web-изображение. К текущему проекту добавим HTML-страницу. Для этого в пункте меню Project выберем команду Add New Item и в появившемся окне дважды щелкнем по шаблону HTML Page. Далее на вкладке HTMLPagel.htm введем текст, представленный в листин- ге 11.20. [. Листинг 11.20. Увеличение изображения в Web-форме (HTML-код) ’ <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtmll/DTD/xhtmll-transitional.dtd"> chtml xmlns="http://www.w3.org/1999/xhtml”> <head> <1111е>Щелкнуть мышью для увеличения</1111е> </head> <body> <img src="poryv.png" width="100" height="100" а1Ь="Двойной щелчок возвращает в исходный размер" onclick="this.src=’poryv.png’;this.height=200;this.width=200" ondblclick="this.src=’poryv.png’;this.height=100;this.width=100" /> </body> </html> В приведенной разметке в качестве атрибутов тега <img>, размечающего изо- бражение, записаны две обработки событий onciick (щелчок мышью на изо- бражении) и ondbiciick (двойной щелчок) на JavaScript. Теперь для просмот- ра этой страницы в браузере мы можем нажать клавишу <F5> или непосред- ственно открыть файл HTMLPagel.htm, например, в Internet Explorer. При этом мы увидим следующее (рис. 11.32). Теперь решим эту же задачу программированием на VB2010. Для этого доба- вим в текущий проект новую Web-форму. В пункте меню Project выполним команду Add New Item и в появившемся окне выберем шаблон Web Form.
Программирование Web-ориентированных приложений на Visual Basic 2010 281 На вкладке конструктора формы перетащим из панели Tollbox элемент управления изображения Image, а на вкладке программного кода WebForml.aspx напишем текст, представленный в листинге 11.21. Рис. 11.32. Щелчок мышью увеличивает изображение ; Листинг 11.21. Увеличение изображения в Web-форме (УВ2010-код) ’ На странице имеем изображение — файл poryv.png, при щелчке мышью на ' нем изображение увеличивается вдвое без перезагрузки Web-страницы. Public Class WebForml Inherits System.Web.UI.Page Protected Sub Page_Load(ByVai sender As Object, ByVai e As System.EventArgs) Handles Me.Load Page.Title = ’’Щелкнуть мышью для увеличения’’ ’ Указываем виртуальный путь к файлу изображения Image1.ImageUrl = Request.АррlicationPath + ’’poryv.png” ’ Получаем URL, который используется в браузере Dim адрес As String = ResolveClientUrl(Imagel.ImageUrl) ’ Добавляем атрибут Alt Imagel.AlternateText = "Двойной щелчок возвращает в исходный размер"
282 Глава 11 ’ Добавляем два события JavaScript Imagel.Attributes.Add("onclick", ’’this.src=’" & адрес & ’’’; this. height=200; this. width=200") Imagel.Attributes.Add(’’ondblclick", ”this.src=”’ & адрес & this.height=l00;this.width=100”) End Sub End Class Как видно из программного кода, кроме двух очевидных свойств объекта Imagel ImageUrl И AlternateText СВОЙСТВО Attributes добавляет объекту imagel два события JavaScript. Нам пришлось включать таким образом собы- тия JavaScript, поскольку объект imagel не имеет событий мыши. Поставим другую, более интересную задачу. На Web-странице имеем изо- бражение, например, мужчины. Это изображение используем для ссылки на другую Web-страницу, например, на WebForml.aspx. Причем при наведении на него указателя мыши происходит смена изображения на изображение женщины. Для решения этой задачи добавим в текущий проект еще одну HTML- страницу и на вкладке разметки HTMLPage2.htm напишем текст, приведен- ный в листинге 11.22. ? Листинг 11.22. Смена изображения в Web-форме (HTML-код) : <!DOCTYPE html PUBLIC ’’-//W3C//DTD XHTML 1.0 Transitional//EN" ”http://www.w3.org/TR/xhtmll/DTD/xhtmll-transitional.dtd”> <html xmlns=”http://www.w3.org/1999/xhtml’’> <head> <title>CMeHa изображения при наведении</Ь1Ь1е> </head> <body> <a href="HTMLPage1.htm”> <img onmouseover="this.src=’g.jpg’" onmouseout="this.src=’m.jpg’" alt="Щелкните, чтобы перейти на HTMLPagel.htm" src="m.jpg" border="0" /> </a> </body> </html> Здесь тег <a> обеспечивает гиперссылку на другую Web-страницу — HTMLPagel.htm, причем в качестве гиперссылки используется изображение m.jpg (изображение мужчины). Это изображение меняется на изображение женщины (файл g.jpg) при наведении на него указателя мыши (JavaScript-
Программирование Web-ориентированных приложений на Visual Basic 2010 283 событие onmouseover) и возвращается в исходное, когда указатель мыши по- кидает элемент (событие onmouseout). Установим в качестве стартовой страницы проекта файл HTMLPage2.htm. Для этого в контекстном меню окна Solution Explorer для этого файла ука- жем Set As Start Page. Внешний вид данной Web-страницы в браузере пока- зан на рис. 11.33. Рис. 11.33. Смена изображения при наведении указателя мыши Для решения этой же задачи с помощью VB2010 в текущий проект добавим новую Web-форму — WebForm2.aspx. В конструкторе формы добавим из па- нели Tollbox элемент управления ImageButton, отображающий изображение и отвечающий на нажатия на нем кнопки мыши. На вкладке программного кода этой формы напишем текст программы, приведенной в листинге 11.23. I -Листинг 11.23. Смена изображения в Web-форме (VB201 Очкод) j ’ На Web-странице имеем изображение, например мужчины, — файл ’ m.jpg. Это изображение используем для ссылки на другую Web-страницу, 1 например, на WebForml.aspx. Причем при наведении на него указателя 1 мыши происходит смена изображения на изображение женщины — файл g.jpg Public Class WebForm2 Inherits System.Web.UI.Page Protected Sub Page_Load(ByVai sender As Object, ByVai e As System.EventArgs) Handles Me.Load ’ Элемент управления ImageButton отображает изображение и ’ отвечает за нажатия на нем указателя мыши ImageButtonl. PostBackUrl = ’’WebForml.aspx"
284 Гпава 11 ’ Указываем виртуальный путь к файлу изображения ImageButtonl.ImageUrl = Request.Applicationpath + "m.jpg” ’ Задаем альтернативный текст ImageButtonl.AlternateText = "Щелкните, чтобы перейти на WebForml.aspx" ’ Добавляем два события JavaScript ImageButtonl.Attributes.Add("onmouseover", "this.src=’g.jpg’") ImageButtonl.Attributes.Add("onmouseout", "this.src=’m.jpg’") End Sub End Class Как видно из программного кода, мы использовали те же приемы, что и в предыдущей задаче. Убедиться в работоспособности Web-страниц, рассмот- ренных в данном разделе можно, открыв соответствующее решение в папке Web_ изображение. Пример 91. Формирование изображения методами класса Graphics и вывод его в Web-форму При создании Web-страниц часто бывает удобно сначала создать изображе- ние, что-либо на нем нарисовать, например график какой-нибудь зависимо- сти, актуальной именно в момент загрузки страницы, затем это изображение записать на диск сервера и вывести его клиенту в обозреватель. Таким графи- ком может быть, скажем, график статистики посещений сайта по месяцам, по неделям, по дням. Задача, решаемая в данном разделе, состоит в следующем. Во время загрузки Web-страницы создать изображение, методами класса Graphics вывести на это изображение текстовую строку, представляющую текущую дату. С целью демонстрации возможностей методов Graphics развернуть данную строку на некоторый угол относительно горизонта. Далее сохранить рисунок в текущий каталог сервера и вывести его на Web-страницу. Для решения этой задачи запустим VB2010, закажем новый проект шаблона Empty ASP.NET Web Application. Добавим Web-форму, для этого в пункте меню Project выберем команду Add New Item и в появившемся окне выбе- рем шаблон Web Form и добавим его к нашему проекту. На вкладке дизай- нера формы WebForml.aspx добавим элемент управления Image. А на вкладке WebForml.aspx.vb введем программный код, представленный в лис- тинге 11.24.
Программирование Web-ориентированных приложений на Visual Basic 2010 285 Листинг 11,24, Формирование изображения и вывод его в Web-форму ’ Web-страница формирует файл изображения методами класса Graphics. ’ На изображение выводится текстовая строка, наклоненная к горизонту ’ на 356 градусов. Далее этот файл изображения отображается в форме. Imports System.Drawing Public Class WebForml Inherits System.Web.UI.Page Protected Sub Page_Load(ByVai sender As Object, ByVai e As System.EventArgs) Handles Me.Load ’ Создаем точечное изображение размером 215 х 35 точек ’ с глубиной цвета 24 Dim РАСТР As Bitmap = New Bitmap(width:=215, height:=35, Format:=Imaging.PixelFormat.Format24bppRgb) ’ Создаем новый объект классу Graphics из изображения РАСТР Dim ГРАФ As Graphics = Graphics. Fromlmage (РАСТР) ’ Теперь становятся доступными методы класса Graphics! ’ Заливка поверхности указанным цветом ГРАФ.Clear(Color.AliceBlue) ' или ГРАФ.Clear(ColorTranslator.FromHtml("#ECECFF")) Dim Дата As String = "Сегодня " + Format(Now, "d MMMM, yyyy") ’ Разворачиваем мир на 356 градусов по часовой стрелке ГРАФ.RotateTransform(356.OF) ’ Выводим на изображение текстовую строку Дата, ’ х, у — координаты левого верхнего угла строки ГРАФ.Drawstring(Дата, New Font("Times New Roman", 14, Fontstyle.Regular), Brushes.Red, x:=5, y:=15) ’ Определяем физический путь файла для текущего Web-узла, ’ сохраняем изображение в файле risunok.jpg каталога Web-узла РАСТР.Save(Request.PhysicalApplicationPath + "risunok.jpg", Imaging. ImageFormat. Jpeg) ’ Возможность вывода изображения в исходящий поток ответа HTTP: ’ РАСТР.Save(Response.Outputstream, Imaging.ImageFormat.Jpeg) ’ Цвет и ширина рамки рисунка: Imagel.BorderColor = Color.Red Imagel.Borderwidth = 2 ’ Указываем виртуальный путь к файлу изображения Imagel.ImageUrl = Request.ApplicationPath + "risunok.jpg"
286 Гпава 11 ’ Освобождение ресурсов РАСТР.Dispose() ГРАФ.Dispose() End Sub End Class Как видно из программного кода, при загрузке страницы создаем точечное изображение указанного размера, формат Format24bppRgb указывает, что от- водится 24 бита на точку: по 8 бит на красный, зеленый и синий каналы. Дан- ное изображение позволяет создать новый объект класса Graphics методом Fromimage. Теперь разворачиваем поверхность рисования на 356° методом RotateTransform и выводим на поверхность рисования текстовую строку с текущей датой. Задавая физический путь файла изображения, методом save сохраняем его в каталоге Web-узла в формате JPEG. В комментарии приведе- на возможность вывода рисунка в исходящий поток ответа HTTP, при этом изображение не будет записываться на диск, но пользователь будет видеть его в браузере. Далее элементу управления imagel указываем виртуальный путь к файлу изображения. Замечу, что физический путь не должен отправ- ляться клиенту, поскольку он может использоваться злоумышленниками для получения сведений о приложении. На рис. 11.34 показан фрагмент работы программы. Рис. 11.34. Вывод в форму изображения, сформированного программно Убедиться в работоспособности Web-страницы, рассмотренной в данном раз- деле можно, открыв соответствующее решение в папке TeKCT_Haioi_Web. Пример 92. Гостевая книга Допустим, на своем сайте вы обсуждаете какую-либо тему и хотите, чтобы посетители сайта оставляли свои мнения, впечатления, пожелания, замена-
Программирование Web-ориентированных приложений на Visual Basic 2010 287 ния, адресованные владельцу или будущим посетителям. Причем так, чтобы сообщения, написанные посетителями, были бы тут же отображены и со- хранены. и тем самым стимулировали желание новых посетителей написать свое сообщение. Такое программное обеспечение называют гостевой книгой сайта. В гостевой книге следует предусмотреть поля для ввода имени посетителя, адреса его электронной почты, а также поле для непосредственно сообщения. Все записи, оставленные посетителями сайта, будем сохранять в текстовом файле kniga.txt на винчестере сервера, предоставляющего Web-хостинг. Впрочем, вместо текстового файла можно воспользоваться какой-либо базой данных. Для программирования гостевой книги запустим VB2010, в окне New Project выберем шаблон Empty ASP.NET Web Application, в поле Name укажем имя нового решения Гостевая_книга и щелкнем на кнопке ОК. Теперь до- бавим к текущему проекту Web-форму. Для этого в пункте меню Project вы- берем команду Add New Item, в появившемся окне укажем шаблон Web Form и щелкнем на кнопке Add. На вкладке конструктора формы в панели элементов нам понадобятся четыре метки Label, три текстовых поля TextBox, соответственно, для имени поль- зователя, его электронной почты и сообщения, одна командная кнопка Button с надписью "Добавить сообщение" и сетка данных GridView для отображе- ния всех вводимых записей. Кроме того, возле каждого текстового поля раз- местим валидатор RequiredFieldValidator, проверяющий факт заполнения текстовых полей. Правильность заполнения проверять не будем, поскольку в данной ситуации если мы будем слишком "принципиальничать" по поводу вводимых данных, то посетитель потеряет терпение и уйдет на другой ресурс (не наш!). Не забываем, что мы гораздо больше заинтересованы во всех но- вых сообщениях, чем посетители их написать. С другой стороны (другая крайность), если мы вовсе не будем контролировать заполнения текстовых полей, то у недобросовестного пользователя появится соблазн нажимать кнопку Добавить сообщение без заполнения полей и заполнять таблицу сет- ки данных пустыми строками, что будет вовсе дискредитацией замысла гос- тевой книги. В конструкторе формы разместим выбранные элементы управ- ления так, как показано на рис. 11.35. После размещения в конструкторе необходимых элементов управления пере- ходим на вкладку программного кода. Текст программы представлен в лис- тинге 11.25.
288 Гпава 11 1 ЕЙ |Ж BuM Debug ГМа Format Table Таок Лея Wirtfto Hefp j Рис. 11.35. Размещение элементов управления в конструкторе формы ? Листинг 11.25. Гостевая книга • Данная Web-страница приглашает посетителя оставить ' какие-либо записи, которые могут прочитать другие посетители ' страницы. Записи сохраняются в текстовом файле kniga.txt. ’ Записи отображаются на Web-странице с помощью элемента • "сетка данных" GridView. Public Class WebForml Inherits System.Web.UI.Page Dim Таблица As New DataTable Dim Читатель As 10.StreamReader, Писатель As 10.Streamwriter Protected Sub Page_Load(ByVai sender As Object, ByVai e _ As System.EventArgs) Handles Me.Load
Программирование Web-ориентированных приложений на Visual Basic 2010 289 Labeli.Text = "ВЫ МОЖЕТЕ НАПИСАТЬ КАКОЕ-НИБУДЬ " & "СООБЩЕНИЕ В НАШЕЙ ГОСТЕВОЙ КНИГЕ" Label2.Text = "Ваше имя:" Label3.Text = "Ваш E-mail:" Label4.Text. = "Ваше сообщение:" Buttoni.Text = "Добавить сообщение" ’ Разрешаем многострочие: TextBox3.TextMode = TextBoxMode.MultiLine ’ Контролируем обязательность заполнения всех полей: RequiredFieldValidatorl.ErrorMessage = "* Следует заполнить это текстовое поле" RequiredFieldValidatorl.ControlToValidate = "TextBoxi" RequiredFieldValidator2.ErrorMessage = "* Следует заполнить это текстовое поле" RequiredFieldValidator2.ControlToValidate = "TextBox2" RequiredFieldValidator3.ErrorMessage = "* Следует заполнить это текстовое поле" RequiredFieldValidator3.ControlToValidate = "TextBox3" Таблица.Columns.Add("Дата") : Таблица.Columns.Add("Имя") Таблица.Columns.Add("E-mail") Таблица.Columns.Add("Сообщение") GridViewl.Borderwidth = WebControls.Unit.Pixel(2) ЗaпoлнитьGridView() End Sub Public Sub ЗaпoлнитьGridView() ’ Эта процедура читает файл kniga.txt (если его нет, то ’ создает, разбивает каждую строку файла на четыре части ' (дата, имя, e-mail и сообщение) и заполняет этими ' частями строки таблицы. Затем записывает эту таблицу ' в сетку данных Gridview. ’ Открываем файл kniga.txt, а если его нет, то ’ его создаем Dim Открыватель As 10. Filestream = New 10. Filestream( Request.PhysicalApplicationPath & "kniga.txt", 10.FileMode.OpenOrCreate) ’ Открываем поток для чтения всех записей из файла Читатель = New 10.StreamReader(Открыватель)
290 Глава 11 ’ В качестве разделителя частей строки файла выбираем ’ Tab, поскольку Tab невозможно ввести в текстовое ’ поле. После нажатия клавиши <ТаЬ> происходит переход ’ в следующее текстовое поле. Dim Разделитель As Char() = New Char() {vbTab} ’ — массив ’ Читаем из файла одну строку Dim Одна_строка As String - Читатель.ReadLine Dim Массив_частей_строки As String() ’ Цикл по строчкам файла kniga.txt While Одна_строка о "" ’ Функция Split делит строку на четыре части ’ и присваивает каждую часть элементам массива Массив_частей_строки = Одна_строка.Split(Разделитель) ’ Загружаем данные в таблицу, т. е. заполняем ’ одну строку таблицы Таблица.LoadDataRow(Массив_частей_строки, True) ’ Читаем из файла одну строку Одна_строка - Читатель.ReadLine End While GridViewl.DataSource = Таблица ’ Обновление сетки данных: GridViewl.DataBind() Таблица.Clear() Читатель.Close() : Открыватель.Close() End Sub Protected Sub Добавить(ByVai sender As Object, ByVai e _ As EventArgs) Handles Buttonl.Click ’ Открываем поток для добавления данных в конец файла Писатель = New 10.StreamWriter(Request. PhysicalApplicationPath & "kniga.txt", True) ’ True означает разрешить добавление строк в файл. ’ Записываем в файл новое сообщение Писатель.WriteLine(DateTime.Now.Date.ToString(). Substring(0, 10) & vbTab & TextBoxl.Text & vbTab & TextBox2.Text & vbTab & TextBox3.Text) ’ Очищаем поля и закрываем поток TextBoxl.Text = "" ; TextBox2.Text = "" TextBox3.Text = ""
Программирование Web-ориентированных приложений на Visual Basic 2010 291 Писатель.Close() 3anonHHTbGridView() End Sub End Class Как видно из программного кода, вначале создаем таблицу данных класса DataTabie и два потока данных для чтения и для записи файлов так, чтобы они были видны из всех процедур класса. При обработке события загрузки формы организуем контроль обязательности заполнения текстовых полей формы, задаем ’’шапку” таблицы (т. е. названия колонок таблицы), а послед- ней командой вызываем процедуру 3anonHHTbGridView. Эта процедура в цикле while читает строки текстового файла kniga.txt и за- полняет ими строки таблицы данных методом LoadDataRow (). Далее запол- ненную таблицу данных указываем в качестве источника данных (DataSource) для сетки данных GridViewl, предназначенной для визуализации (отображе- ния) таблицы в форме. После этого важно очистить таблицу данных методом Clear(). При обработке события ’’щелчок на кнопке" открываем поток данных писа- тель для добавления данных в конец файла kniga.txt и записываем в этот файл Рис. 11.36. Интерфейс гостевой книги
292 Гпава 11 текстовую строку, содержащую текущую дату, имя посетителя Web- страницы, его e-mail и непосредственно его сообщение. Причем в качестве разделителя между этими текстовыми строками мы используем управляю- щий символ Tab, поскольку его невозможно ввести в текстовое поле, т. к. по- сле нажатия клавиши <ТаЬ> предусмотрен переход в следующее текстовое поле. После закрытия потока данных писатель вызываем процедуру SancjiHHTbGridView, которая как бы начинает опять "с чистого листа”: снова открывает поток для чтения файла и опять заполняет таблицу данных, кото- рая, как мы помним, была очищена от предыдущих данных. Именно поэтому строки (команды) процедуры 3anojiHMTbGridview были оформлены в отдель- ную процедуру, поскольку заполнение таблицы и ее визуализация происхо- дят два раза\ один раз при загрузке формы, а другой при добавлении новой записи. Фрагмент работы гостевой книги представлен на рис. 11.36. Убедиться в работоспособности данной программы можно, открыв соответ- ствующее решение в папке Гостевая_книга. Пример 93. Отображение времени в Web-форме с использованием технологии AJAX Мы уже обсуждали вопрос отображения времени в Windows-приложении (см. пример 70 в главе 10). Тогда, для того чтобы время обновлялось каждую се- кунду, нами был использован элемент управления Timer. При обработке со- бытия Tick (события, когда прошел заданный интервал времени interval, равный 1000 миллисекунд, т. е. 1с) элемента управления Timer в метку Label копировалось новое значение времени, при этом изображение формы обновлялось (перерисовывалось). Когда речь идет о Web-форме, технология ASP.NET предполагает операции обратной отправки данных. Когда пользо- ватель щелкает на кнопке или делает выбор в окне списка с включенной функцией AutoPostBack, серверу отсылается соответствующий запрос, после чего с него обратно клиенту отправляется целая страница. Если такое обра- щение к серверу будет происходить через каждую секунду, то возрастет объ- ем сетевого трафика и вследствие инерции Сети пользователь будет ощущать дискомфорт. Кроме того, если на этой странице предусмотрено заполнение пользователем полей, то серверу будет отсылаться страница с частично за- полненными полями. Решение этой проблемы состоит в использовании технологии AJAX, которая обеспечивает возможность выполнения частичного визуального обновления страницы посредством поддерживаемой ASP.NET AJAX операции обратной отправки. Продемонстрируем возможность технологии AJAX на примере,
Программирование Web-ориентированных приложений на Visual Basic 2010 293 когда мы имеем метку Label в Web-форме. На эту метку каждую секунду копируем новое время, но обновляем при этом не всю форму, а только метку с помощью технологии AJAX. Решая эту задачу, запустим VB2010 и закажем новый проект из шаблона Empty ASP.NET Web Application, укажем имя Name— AJAX_Timer. К текущему проекту добавим Web-форму. Для этого в пункте меню Project выберем команду Add New Item и в появившемся окне дважды щелкнем по шаблону Web Form. Далее, попав на вкладку конструктора Web-формы, перетащим в форму из раздела AJAX Extensions панели ToolBox элементы управления ScriptMandger, UpdatePanel. Затем на элемент UpdatePanel поместим Timer и метку Label. Теперь на вкладке файла программной поддержки WebForml.aspx.vb напишем программный код, приведенный в листин- ге 11.26. : Листинг 11.26. Отображение времени в Web-форме ’ Web-страница демонстрирует время на метке Labeli. На эту метку ’ каждую секунду копируем новое время, но обновляем при этом не всю ’ форму, а только метку с помощью технологии AJAX. Public Class WebForml Inherits System.Web.UI.Page Protected Sub Page_Load(ByVai sender As Object, ByVai e As System.EventArgs) Handles Me.Load Timerl.Interval = 1000 ’ миллисекунд = 1 сек Labeli.Text = ’’Текущее время: ” + DateTime .Now.ToLongTimeString End Sub Private Sub Timerl_Tick(ByVai sender As Object, ByVai e As System.EventArgs) Handles Timerl.Tick Labeli.Text = ’’Текущее время: ” + DateTime.Now.ToLongTimeString End Sub End Class Как видно из программного кода, при загрузке страницы задаем интервал времени, равный одной секунде. При обработке события Tick— события, когда прошел заданный интервал времени, в метку Labeli копируется новое значение времени. При этом благодаря использованию технологии AJAX об-
294 Глава 11 новляется не вся Web-форма, а только те элементы, которые расположены на элементе UpdatePanel. Фрагмент работы программы показан на рис. 11.37. i -'‘X . ..> . . I | ч.- v http://focalhost;3211i-Ч;-* *t X- | • <- : ^|http;//iocaiho$t:32il/WeiJf • ! >£' * ;3J ? .... ...-... ............;..,.......;....„..^.....;.A...... ч.::...,^..;...^ i Товтгеевремя: 1B36:49 -;.-J f 0 Интернет < 109% * ! Рис. 11.37. В форме обновляется только AJAX-элемент UpdatePanel Убедиться в работоспособности Web-страницы можно, открыв решение AJAX Timer.sIn в папке AJAX_Timer.
ГЛАВА 12 Создание Web-служб и их клиентов О Web-службах Web-служба (от англ. Web service) — это программная система (более кон- кретно— откомпилированная библиотека динамической компоновки, т. е. файл формата DLL в папке bin приложения), расположенная на удаленном сервере (компьютере), к которой можно обращаться (потреблять сервис Web- службы) из своего клиентского компьютера. При этом возможности удален- ной Web-службы будут реализованы в вашем Windows- или Web-при- ложении, а пользователь при достаточной скорости трафика может даже не заметить обращения вашей программы к удаленному серверу. На удаленном компьютере могут находиться и программный код, и данные. Для передачи по Интернету вызовов методов Web-служб и результатов их выполнения ис- пользуется протокол SOAP (Simple Object Access Protocol). Протокол SOAP применяет формат сообщений, основанный на XML. Web-служба и протокол SOAP не зависят от конкретной платформы. Поэтому различные разработчи- ки могут использовать Web-службы друг друга, не беспокоясь о совместимо- сти операционных систем, технологий или языков программирования. Другое название Web-службы — Web-сервис. Web-службы решают очень разные задачи. Это прогноз погоды, гороскоп, переводчик слов на различные иностранные языки, курсы валют, котировки ценных бумаг, проверка на корректность введенного пользователем почтово- го адреса, реестр улиц города, статистика правонарушений, информация о наличии свободных мест на авиарейс или в кинотеатр и т. д. Причем любой из подобных сервисов вы можете легко встроить в свое Windows- или Web- приложение путем создания клиентского приложения, потребляющего такой уже существующий сервис Web-службы. Для поиска Web-служб в Интернете существует несколько сайтов, в которых Web-службы регистрируются их провайдерами для того, чтобы их могли
296 Гпава 12 найти заинтересованные в них разработчики. Таким сайтом является, напри- мер: http://uddi.xml.org/uddi-org. Регистрация в каталоге UDDI бесплатна. Здесь сегодня можно найти несколько десятков более или менее полезных Web-служб. В Сети можно найти и другие списки общедоступных Web- служб различных производителей, например: http://www.xmethods.org/ve2 /index.po. Список русскоязычных Web-служб можно найти по адресу: http://ivbeg.bestpersons.ru/feed/post3279396/. Упрощенно говоря, Web-служба в среде .NET состоит из двух компонентов: ASMX-файла и файла программной поддержки ASMX.vb. ASMX-файл содержит в себе информацию о методах Web-службы, о способах их тестиро- вания, это можно посмотреть в любом Web-браузере. Файл программной поддержки написан на языке Visual Basic, может быть скомпилирован для получения библиотеки DLL, именно он обеспечивает реализацию методов Web-службы. Например, на рис. 12.1 показано отображение в браузере Internet Explorer методов Web-службы, представленного в Сети по адресу: http://webservice.webserviceshare.com/currencyconverter/rates.asmx. Рис. 12.1. Пять методов Web-сервиса по операциям с курсами валют Здесь перечислены пять методов Web-службы по операциям с текущими кур- сами валют. В создаваемом разработчиком клиентском приложении необхо- димо сделать ссылку на данный Web-сервер и таким образом включить в те- кущий проект удаленный класс. А затем в своем программном коде объявить создание нового экземпляра этого класса, и теперь можно уже обращаться ко всем методам класса.
Создание Web-служб и их клиентов 297 Пример 94. Клиентское приложение, потребляющее сервис Web-службы "Прогноз погоды" В данном разделе создадим клиентское Web-приложение, потребляющее сер- вис Web-службы сайта http://www.webservicex.net/globalweather.asmx, и продемонстрируем тем самым, что это— просто! Данная Web-служба воз- вращает прогноз погоды в городе, который пользователь задает в за- просе к службе. Эта Web-служба поддерживает два метода (функции): GetcitiesByCountry И GetWeather (рИС. 12.2). На ВХОД первой функции GetcitiesByCountry подают название страны, где хотят получить прогноз по- годы, а на выходе функции получают перечисление городов этой страны, для которых Web-служба готова сделать прогноз погоды. Рис. 12.2. Два метода Web-службы прогноза погоды На вход второй функции GetWeather подают названия города и страны, а на выходе функции получают XML-строку, содержащую прогнозируемые пара- метры погоды (листинг 12.1). I Листинг 12.1. X ML-код, полученный из функции GetWeather <?xml version="l.О" fencoding="utf-16’’?> <CurrentWeather> <Location>Kyiv, Ukraine (UKKK) 50-24N 030-34E 167M</Location> <Time>0ct 16, 2009 - 07:30 AM EDT / 2009.10.16 1130 UTC</Time> <Wind> from the SE (130 degrees) at 4 MPH (4 KT):0</Wind> <Visibility> greater than 7 mile(s):0</Visibility> <SkyConditions> mostly cloudy</SkyConditions> <Temperature> 42 F (6 C)</Temperature>
298 Гпаеа 12 <DewPoint> 39 F (4 С)</DewPoint> <RelativeHumidity> 86%</RelativeHumid±ty> <Pressure> 30.00 in. Hg (1016 hPa)</Pressure> <Status>Success</Status> </CurrentWeather> Как видно из листинга, параметры погоды указываются в XML-элементах: температура (Temperature), относительная влажность (ReiativeHumidity), дав- ление (Pressure) и пр. Напишем Web-приложение (также легко можно написать и Windows- приложение), обращающееся к функции Getweather данной удаленной Web- службы. Причем программный код должен быть минимальным и демонстри- ровать лишь принцип подключения и доступ к нужному элементу (например, температуре) XML-документа. Для этой цели после запуска VB2010 выберем шаблон Empty ASP.NET Web Application, укажем имя Name — Погода-Web. К текущему проекту доба- вим Web-форму. Для этого в пункте меню Project выберем команду Add New Item и в появившемся окне дважды щелкнем на шаблоне Web Form. Далее, попав в конструктор Web-формы, из панели элементов Toolbox перетащим кнопку Button, текстовое поле TextBox для вывода строки с данными XML и метку Label для вывода на нее значения температуры. Теперь наступает ключевой момент, а именно— подключение ссылки на удаленную Web-службу, содержащую класс с необходимыми методами. Для этого в пункте меню Project выберем команду Add Web Reference (эту команду можно также выбрать в контекстном меню окна Solution Explorer). В результате получим интерфейс, показанный на рис. 12.3, здесь в поле URL введем адрес Web-службы и щелкнем на кнопке Go. i Navigate to a web service URL and dick Add Reference to add al! the available services. i Uhl: httc-:.’7ww^.webservice> net/gfoba'weather.asmx J \ Start Browsing for Web Services < Use ths page as a starsnq per-: to fnd Web se*’v<es did tne inks ’J bee-a or tyee a known URL ;rro th- address hy I Browse to: j . • V/lloueryicxts Ofl.tl’U AQ-COj Hij?uHipy i • BmytsyA/OQlheryyru on nrjwvfk Рис. 12.3. Поиск нужной Web-службы в Сети
Создание Web-служб и их клиентов 299 Теперь в окне под полем URL мы увидим оба метода данного сервиса в том виде, как это было на рис. 12.2 (после нажатия на кнопку Go). При этом ста- нет доступной кнопка Add Reference. Щелкнем на этой кнопке, после этого в окне Solution Explorer появилась новая папка Web References со ссылкой на удаленный класс net.webservicex.www (рис. 12.4). Solution Explorer •+: -.Й МУ Project Web References neLvvebservicex.www gbbalweather.disco :g| gfobeb/eather. wsdl i£ Wj Reference.map it .... obj It.- Web.config ;it JJj WebFor m 1. aspx Рис. 12.4. В окне Solution Explorer появилась ссылка на удаленный класс Теперь этот класс, содержащий необходимую нам удаленную Web-службу, мы можем использовать в своем программном коде (листинг 12.2). Листинг 12.2. Web-приложение, обращающееся к сервису j удаленной Web-службы прогноза погоды ’ Web-приложение, потребляющее сервис удаленной Web-службы прогноза ’ погоды. Приложение демонстрирует XML-строку с параметрами погоды для 1 города, указанного во входных параметрах при обращении к Web-службе Public Class WebForml Inherits System.Web.UI.Page Protected Sub Page_Load(ByVai sender As Object, ByVai e As System.EventArgs) Handles Me.Load ’ Это Web-приложение Buttonl.Text = "Выяснить погоду" : Labell.Text = Nothing TextBoxl.TextMode = TextBoxMode.MultiLine End Sub Private Sub Buttonl_Click(ByVai sender As Object, ByVai e As System.EventArgs) Handles Buttonl.Click
300 Глава 12 ’ Создаем клиентское приложение Web-службы: ’ http://www.webservicex.net/globalweather.asmx ' Создание экземпляра прокси-класса Dim ПОГОДА As New Net.webservicex.www.GlobalWeather ’ Функция GetWeather запрашивает строковые параметры с ’ названием города и страны и возвращает строку с XML-документом Dim Строка_ХМЬ As String = ПОГОДА.GetWeather(’’Moscow”, "Russia") ’ Dim Строка_ХМЬ As String = ПОГОДА.GetWeather("Kyiv", "Ukraine") TextBoxi.Text = Строка_ХМЬ Dim Документ = New System. Xml .XmlDocument ’ Загрузка строки XML в XML-документ Документ.LoadXml(Строка_ХМЬ) Dim Узел As System. Xml .XmlNode Dim Элемент As System.Xml .XmlElement Узел = Документ.ChildNodes.Item(l) Элемент = Узел("Temperature") Labeli.Text = "Температура воздуха в Москве: " & Элемент.InnerText End Sub End Class Как видно, в программном коде при обработке события ’’щелчок на кнопке” Выяснить погоду создается экземпляр класса удаленной Web-службы. Далее происходит непосредственное обращение к методу класса GetWeather с вход- ными параметрами город и страна, метод GetWeather возвращает строку с XML-документом. Данную строку выводим в текстовое поле TextBoxi. Для ее ’’расшифровки” загружаем эту строку в XML-документ. Значение температу- ры находим в содержимом элемента "Temperature", затем выводим значение температуры на метку Labeli. Фрагмент работы программы показан на рис. 12.5. Таким образом, продемонстрировано создание клиентского Web-приложения, потребляющего сервис Web-службы. Замечу, что аналогичным образом мож- но создавать и Windows-приложения (настольные приложения), которые также, будучи клиентами какой-либо Web-службы, могут получать, напри- мер, справочную информацию в онлайновом режиме. Убедиться в работоспособности программы можно, открыв соответствующий файл решения в папке Погода-Web.
Создание Web-служб и их клиентов 301 Рис. 12.5. Работа клиента Web-службы "Прогноз погоды" Пример 95. Создание простейшей Web-службы А теперь, когда мы убедились, что создать клиентское приложение, потреб- ляющее сервис Web-службы, не сложно, поставим задачу создать самую про- стую Web-службу, чтобы убедиться, что это тоже простая задача. Автор по- нимает, что сейчас наступил очень деликатный момент, что задача, реали- зующаяся в данной Web-службе, должна быть максимально простой. Например, пользователю предлагается ввести два числа, а Web-служба берет на себя функцию сложения этих двух чисел и вывода (возврата) суммы. При этом необходимо произвести диагностику вводимых данных. От такой Web- службы нет особенной пользы, но на этой маленькой задачке нам будет удобно продемонстрировать все возможности. Здесь, так же как и при отлад- ке активных Web-страниц из предыдущей главы, при отладке данной Web- службы в качестве удаленного серверного компьютера и клиентского компь- ютера мы будем использовать один ваш локальный компьютер. Для решения этой задачи запускаем VB2010, выбираем шаблон ASP.NET Web Service Application, выбираем папку и имя. Сразу после этого попадаем на вкладку готовой Web-службы HelloWorld, и уже ее можно тестировать. Однако HelloWorld— это другая задача, разработчики Visual Studio 2010
302 Глава 12 включили ее для облегчения освоения данной технологии. Нас интересует наша задача, поэтому изменим файл программной поддержки, как показано в листинге 12.3. Imports System.Web.Services Imports System.Web.Services.Protocols Imports System.ComponentModel ' To allow this Web Service to be called from script, ' using ASP.NET AJAX, uncomment the following line. ' <System.Web.Script.Services.Scriptservice()> _ <System.Web.Services.WebService(Namespace:=”http://tempuri.org/")> _ <System.Web.Services.WebServiceBinding(ConformsTo:=WsiProfiles. BasicProfilel_l)> _ <ToolboxItem(False) > _ Public Class Servicel Inherits System.Web.Services.WebService <WebMethod()> _ Public Function Сумма(ByVai Число1 As String, ByVai Число2 As String) As String ' Входные параметры объявляем типа String, чтобы принимать ' от пользователя любые символы, их анализировать, и при ' "плохом вводе" сообщать по-русски. ' Пользователь может использовать при вводе данных как ' десятичную точку, так и запятую. Если введет точку, то ' заменим на запятую: Число1 = Число1.Replace(".", ",") Число2 = Число2.Replace(".", ",") Dim X, Y, Z As Decimal If IsNumeric(Число1) = True Then X = CType(Число1, Decimal) Else Return "В первом поле должно быть число" If IsNumeric(Число2) = True Then Y = CType(Число2, Decimal) Else Return "Во втором поле должно быть число" Z = X + Y Return "Сумма = " & Z.ToString End Function End Class
Создание Web-служб и их клиентов 303 Как видно из текста программы, мы не программировали никакой пользова- тельский интерфейс. У нас здесь нет ни формы, ни кнопок, ни текстовых полей. Уже отсюда понятно, что Web-служба — это удаленный класс, к кото- рому можно подключиться через Интернет из своего, например, Windows- или Web-приложения. На вход функции Сумма пользователь Web-службы по- дает два числа, которые принимаются функцией как две строки. Если при этом пользователь использовал десятичную точку, то функция Replace меняет эту точку на запятую. Функция isNumeric проверяет, числовые ли символы содержатся во введенных строках, и если это так, то с помощью функции стуре происходит преобразование строковых переменных в переменные типа Decimal. Теперь можем протестировать данную Web-службу, для этого нажмем кла- вишу <F5>. При этом Web-браузер откроет ASMX-файл. Здесь мы увидим единственный метод этой Web-службы — сумма. Щелчок указателем мыши на этой гиперссылке обеспечит возможность тестирования нашей Web- службы (рис. 12.6). Мы можем вводить в данные поля нечисловые символы, числа с десятичной точкой или запятой и тем самым тестировать поведение нашей программы. Заметьте, что мы не программировали эти поля, система сама предоставила нам такую возможность для тестирования программируемой нами Web- службы.
304 Гпава 12 Убедиться в работоспособности данной Web-службы можно, открыв в папке WebS_my соответствующий файл решения. Пример 96. Создание Windows-приложения, потребителя сервиса Web-службы Теперь напишем Windows-приложение (т. е. создадим ЕХЕ-файл), который будет обращаться к Web-службе, написанной в предыдущем разделе. Такое приложение можно называть клиентским. Для этого запустим VB2010, выбе- рем шаблон Windows Forms Application (можно даже Console Application). Из панели Toolbox перенесем в форму кнопку, и вся работа с удаленной Web- службой будет происходить при обработке события ’’щелчок на кнопке” Пуск. Чтобы сделать Windows-приложение потребителем сервиса Web-службы, не- обходимо в его проекте создать Web-ссылку на удаленный класс. Для этого выберем в пункте меню Project команду Add Service Reference, это приведет к появлению диалогового окна Add Service Reference. В этом окне щелкнем кнопку Advanced, а затем в следующем окне кнопку Add Web Reference. Поскольку мы отлаживаем и Web-службу, и его клиентское приложение на одном локальном компьютере, в поле URL пишем виртуальный адрес ASMX- файла. Этот адрес мы можем получить, запустив нашу Web-службу из пре- дыдущего раздела, а затем скопировав в буфер обмена его URL-адрес. Для локального компьютера, на котором автор отлаживал данный пример, URL- адрес был таким: http://localhost:1611/Servicel.asmx. Затем щелкаем на кнопке Go и тем самым получаем доступ к кнопке Add Reference, после щелчка на которой в окне Solution Explorer добавится зна- чок ссылки на класс localhost, обеспечивающий доступ к Web-службе (рис. 12.7). Рис. 12.7. Добавление ссылки на класс localhost
Создание Web-служб и их клиентов 305 Если посмотреть на этот класс через браузер объектов View in Object Browser (используя контекстное меню в окне Solution Explorer), то можно увидеть все свойства, методы и события, которые содержатся в этом классе. Теперь, когда в наш проект добавлена ссылка на удаленный класс, мы можем вызывать методы этого класса в нашей программе (листинг 12.4). ' Клиентское Windows-приложение, потребляющее сервис Web-службы ' предыдущего примера WebS_my. Public Class Forml Private Sub Forml_Load(ByVai sender As System.Object, ByVai e As System.EventArgs) Handles MyBase.Load Buttonl.Text - "Пуск" End Sub Private Sub Buttonl_Click(ByVai sender As System.Object, ByVai e As System.EventArgs) Handles Buttonl.Click ' Чтобы добавить Web-службу к обычному Windows-приложению: ' Project - Add Service Reference — Advanced -«Add Web Reference, ' затем в поле URL пишем виртуальный адрес Web-службы ' http://localhost:1611/Servicel.asmx ’ Создаем экземпляр удаленного класса: Dim Удаленный As New localhost.Servicel Dim Sum As String = Удаленный.Сумма("23.5", "11,4") MsgBox(Sum) End Sub End Class Как видно из программного кода, при обработке события "щелчок мышью" на кнопке Пуск создаем экземпляр удаленного класса и обращаемся к его функции (методу) Сумма. При этом при вводе чисел специально одно из них пишем через десятичную точку, а другое — через запятую для тестирования возможности ввода чисел обоими способами. Результат работы программы представлен на рис. 12.8. Убедиться в работоспособности программы можно, открыв соответствующий файл решения SLN в папке Win_client. II Зак.145
306 Глава 12 Рис. 12.8. Обращение Windows-приложения к Web-службе Пример 97. Web-служба "Торговая рекомендация на рынке Forex" Создадим Web-службу, обеспечивающую торговой рекомендацией участни- ков международного валютного рынка Forex. Как известно, любой желающий через Интернет, используя соответствующее программное обеспечение, мо- жет подключиться к этому рынку и совершить либо покупку какой-либо валютной пары (например, евродоллар, EURUSD), либо ее продажу. И в за- висимости от правильно выбранного направления движения цены либо полу- чить прибыль, либо убыток. Существует множество сайтов, где выкладыва- ются рекомендуемые торговые стратегии работы на рынке Forex на текущую европейскую или американскую сессию. Например, мы доверяем ка- кому-нибудь из таких сайтов, скажем, сайту http://www.forex-rdc.ru/ subscribers.php?action=prognoz, и решаем руководствоваться его рекомен- дациями. Кроме того, мы создаем Web-службу, которая с помощью синтак- сического разбора указанной выше Web-страницы будет извлекать торговую стратегию, рекомендованную данным сайтом на текущий день. Поскольку в нашей книге мы должны привести очень краткий и выразительный пример, то ограничимся торговой рекомендацией только для одной валютной пары EURUSD. Для решения этой задачи запускаем VB2010, выбираем шаблон ASP.NET Web Service Application, выбираем папку и имя, например, WebS_Forex. Содержимое файла программной поддержки приведено в листинге 12.5. I Листинг 12.5. Web-служба "Торговая рекомендация на рынке Forex" .. ' Web-служба, которая с помощью синтаксического разбора Web-страницы 1 http://www.forex-rdc.ru/subscribers.php?action=prognoz 1 извлекает торговую рекомендацию на рынке Forex для валютной пары ’ EURUSD, предлагаемую данным сайтом на текущий день, и выводит ее ’ потребителю сервиса Web-службы в виде строки. Imports SysteiruWeb.Services Imports System.Web.Services.Protocols Imports System.ComponentModel
Создание Web-служб и их клиентов 307 ' То allow this Web Service to be called from script, ' using ASP.NET AJAX, uncomment the following line. ' <System.Web.Script.Services.Scriptservice()> _ <System.Web.Services.WebService(Namespace:="http://tempuri.org/")> _ <System.Web.Services.WebServiceBinding(ConformsTo:=WsiProfiles. BasicProfilel_l)> _ <ToolboxItem(False)> _ Public Class Servicel Inherits System.Web.Services.WebService <WebMethod()> _ Public Function Sovet() As String ’ Создаем объект для чтения Web-страницы: Dim КЛИЕНТ As New System.Net.WebClient ’ Чтобы русские буквы читались нормально, ' объявляем объект Кодировка: Dim Кодировка As System.Text.Encoding = System.Text.Encoding.GetEncoding(1251) Dim ПОТОК As 10.Stream Dim СТРОКА As String Try ’ Попытка открытия Web-pecypca: ПОТОК = КЛИЕНТ.OpenRead( "http://www.forex-rdc.ru/subscribers.php?action=prognoz") Catch ex As Exception СТРОКА = String.Format( "Ошибка открытия www.forex-rdc.ru{0}{1}", ControlChars.NewLine, ex) Return СТРОКА End Try ' Чтение HTML-разметки Web-страницы: Dim Читатель As New 10.StreamReader(ПОТОК, Кодировка) ' Копируем HTML-разметку в строковую переменную: СТРОКА = Читатель.ReadToEnd ' Ищем в разметке страницы фрагмент с указанной строкой: Dim i As Integer = СТРОКА.IndexOf("Торговая стратегия:") ' Ищем стратегию только для EURUSD: СТРОКА = СТРОКА.Substring(i, 120) ’ Удаляем HTML-разметку: i = СТРОКА.IndexOf("</р>")
308 Глава 12 СТРОКА = СТРОКА.Remove(i) СТРОКА = СТРОКА.Replace("</Ь>", ”") ’ Вставляем текущую дату: СТРОКА = СТРОКА.Replace("стратегия:”, "стратегия для EURUSD на " + Format(Now, "d ММММ, уууу") + + ControlChars.NewLine) ПОТОК.Close() Return СТРОКА End Function End Class Как видно из программного кода, данная Web-служба содержит в себе один метод soveto, который не имеет входных параметров. В начале метода соз- даем экземпляр класса webclient для чтения и последующего синтаксическо- го разбора Web-страницы. Вообще говоря, Web-страница может быть записа- на на машинном носителе в какой-либо кодировке. Чаще всего это Unicode (UTF-8), русскоязычные сайты часто имеют кодировку Windows 1251. Чтобы выяснить, в какой кодировке записана Web-страница, следует в браузере в контекстном меню навести указатель мыши на пункт меню Кодировка. При чтении Web-страницы создаем объект поток, используя URL-адрес страницы, и объект Кодировка для корректного отображения кириллицы. После копиро- вания HTML-разметки страницы в строковую переменную ищем в разметке страницы раздел с торговой стратегией для EURUSD с помощью строковых операций. Рис. 12.9. Отображение ASMX-файла в браузере
Создание Web-служб и их клиентов 309 Теперь запустим созданную Web-службу, нажав клавишу <F5>. Если фор- мальных ошибок нет, мы получим отображение ASMX-файла в браузере (рис. 12.9). Щелкнув в этом окне на изображении единственного метода данной Web- службы sovet, мы попадаем на другую страницу, где получаем возможность его тестировать. Для этого щелкнем на кнопке Invoke. В итоге тестирования получим в браузере результат работы данного метода Web-службы в формате XML-сообщения (рис. 12.10). Рис. 12.10. XML-сообщение, как результат работы Web-сервиса Убедиться в работоспособности программы можно, запустив соответствую- щее решение в папке WebSForex. Пример 98. Клиентское приложение, потребляющее сервис Web-службы "Торговая рекомендация на рынке Forex" Теперь напишем клиентское Windows-приложение, использующее Web- службу, созданную нами в предыдущем разделе. Для этого запустим VB2010, выберем шаблон Windows Forms Application. Из панели элементов Toolbox перенесем в форму метку Label, куда будем помещать строку торговой реко- мендации, полученную от Web-службы ’’Торговая стратегия на рынке Forex”. Далее необходимо в проекте создать Web-ссылку на удаленный класс Web- службы. Для этого выберем в пункте меню Project команду Add Service Reference, это приведет к появлению диалогового окна Add Service Reference. В этом окне щелкнем кнопку Advanced, а затем в следующем окне кнопку Add Web Reference. Теперь в поле URL пишем виртуальный адрес ASMX-файла используемой Web-службы. Этот адрес мы можем получить, запустив нашу Web-службу из
310 Гпава 12 прошлого раздела, а затем скопировав в буфер обмена его URL-адрес. На вкладке программного кода набираем простейшую программу (лис- тинг 12.6). [Листинг 12.6. Клиентское приложение, потребляющее сервис Web-службы i "Торговая рекомендация на рынке Forex" ' . ’ Клиентское Windows-приложение, потребляющее сервис Web-службы ’ предыдущего примера WebS_Forex. Public Class Forml Private Sub Forml_Load(ByVai sender As System.Object, ByVai e As System.EventArgs) Handles MyBase.Load ’ Создаем клиентское приложение Web-службы: ’ http://localhost:1042/Servicel.asmx ’ Создаем экземпляр удаленного класса: Dim Forex As New localhost.Servicel Me.Text = ’’Рынок Forex” Labell.Text = Forex.Sovet() End Sub End Class Как видно из программного кода, при обработке события загрузки формы создаем экземпляр удаленного класса Web-службы, затем обращаемся к его методу sovet Скопируем получаемую строку в метку Labell. Фрагмент рабо- ты программы приведен на рис. 12.11. | Т орговая ст рзт егня д л я Е U R U $ D на 13 ноября - 2009: j покупка от 1.4900 стоп 1 4830 ТР 1.5050, продажа от 1.4830 стол 1.4900 TP 1 4Б50 ; Рис. 12.11. Результат работы клиентского приложения Убедиться в работоспособности программы можно, запустив соответствую- щее решение в папке Forex Win.
Создание Web-служб и их клиентов 311 Пример 99. Клиентское Web-приложение, потребляющее сервис Web-службы "Морфер" Создадим клиентское Web-приложение не для Web-службы, написанной на- ми, а для удаленного Web-сервиса. Различных готовых Web-служб много, их можно посмотреть, протестировать на сайтах http://uddi.xml.org/, http://www.xmethods.org/, http://www.webservicelist.com/ и др. Выберем од- ну из русскоязычных Web-служб, а именно Web-службу склонения сущест- вительных "Морфер", ее адрес в Сети следующий: http://www.morpher.ru/ WebServices/Morpher.asmx. Эта Web-служба предназначена для автоматизированной обработки текстов на русском языке. В частности, метод GetA115 Web-службы обеспечивает склонение слов и словосочетаний на русском языке. На вход функции (мето- да) GetAiis данной Web-службы подаем слово в именительном падеже, функ- ция возвращает массив строк, в которых записано это слово в различных пяти падежах: родительном, дательном, винительном, творительном и предлож- ном. Для испытания этой Web-службы запустим VB2010, выберем шаблон Empty ASP.NET Web Application. К текущему проекту добавим Web-форму. Для этого в пункте меню Project выберем команду Add New Item и в появившем- ся окне дважды щелкнем шаблон Web Form. В конструкторе формы из пане- ли элементов Toolbox перенесем текстовое поле TextBox и кнопку Button. Далее, чтобы добавить ссылку на удаленный класс, в пункте меню Project выберем команду Add Web Reference, в поле URL введем ссылку на Web- службу: http://www.morpher.ru/WebServices/Morpher.asmx. При этом кнопка Add Reference станет доступной, а после щелчка на ней в окне Solution Explorer появится ссылка на удаленный класс: ru.morpher.www. Теперь мы можем использовать эту ссылку в нашем про- граммном коде (листинг 12.7). Листинг 12.7. Клиентское Web-приложение, потреблявшее сервис ' Клиентское Web-приложение, потребляющее сервис Web-службы склонения ’ существительных "Морфер". На вход метода Web-службы подаем слово на ’ русском языке, на выходе получаем это слово в различных пяти падежах Public Class WebForml Inherits System. Web.UI.Page Protected Sub Page_Load(ByVai sender As Object, ByVai e As System.EventArgs) Handles Me.Load
312 Гпава 12 Buttoni.Text = "Просклонять” TextBoxi.TextMode = TextBoxMode.MultiLine End Sub Private Sub Buttonl_Click(ByVai sender As Object, 'ByVai e As System.EventArgs) Handles Buttoni.Click ’ Создаем клиентское приложение Web-службы: ’ http://www.morpher.ru/WebServices/Morpher.asmx ’ Создаем экземпляр удаленного класса: Dim Склонение As New ru.morpher.www.Morpher Dim Падежи() As String = Склонение.GetAl 15 (’’Зиборов Виктор Владимирович”) Падежи(4) = ”0 " + Падежи(4) ’ Перевод каретки vbCrLf в конце каждого склонения: For Each С As String In Падежи TextBoxi.Text = TextBoxi.Text & C & vbCrLf Next End Sub End Class Как видно из текста программы, при обработке события ’’щелчок на кнопке” Просклонять создаем экземпляр удаленного класса склонение и далее ис- пользуем метод GetAiis класса для получения возможных склонений. Метод GetAilb возвращает массив строк с пятью возможными склонениями. Цикл Рис. 12.12. Склонение слов обеспечивает Web-сервис
Создание Web-служб и их клиентов 313 For Each обеспечивает символ конца строки vbCrLf в конце каждой строки текстового поля. Фрагмент работы программы представлен на рис. 12.12. Убедиться в работоспособности программы можно, запустив соответствую- щий файл решения в папке Client Morpher. Пример 100. Получение данных от Web-службы Центрального банка РФ Web-приложением Центральный банк Российской Федерации (ЦБРФ) предоставляет Web- службу для получения ежедневных экономических данных (курсы валют, учетные цены драгоценных металлов и пр.). Сервис данной Web-службы можно получать по адресу: http://www.cbr.ru/scripts/Root.asp?Prtid=DWS. Поставим задачу создания клиентского Web-приложения для получения ежедневных курсов валют. Такой сервис предлагается на сайте Цент- рального банка Российской Федерации по адресу: http://www.cbr.ru /DailyInfoWebServ/DailyInfo.asmx. Мы воспользуемся функцией (методом) GetSeidCursOnDate данной Web- службы, на вход которой подают дату, а на выходе функции получают еже- дневные курсы валют в виде DataSet (табличные данные). Для решения этой задачи запустим VB2010, выберем шаблон Empty ASP.NET Web Application. К текущему проекту добавим Web-форму. Для этого в пункте меню Project выберем команду Add New Item и в появившем- ся окне дважды щелкнем шаблон Web Form. В конструкторе формы перета- щим в форму кнопку и элемент сетки данных GridView, поскольку намерева- емся с его помощью отображать табличные данные типа DataSet. Далее в пункте меню Project выберем команду Add Web Reference и в появившем- ся окне в поле URL введем адрес Web-сервиса: http://www.cbr.ru/DailyInfoWebServ/DailyInfo.asmx При этом станет доступной кнопка Add Reference. Щелкнем на этой кнопке, после этого в окне Solution Explorer появится новая папка Web References со ссылкой на удаленный класс ru.cbr.www. Теперь в нашем программном коде мы сможем воспользоваться этим удаленным классом (листинг 12.8). | Листинг 12.8. Получение данных от Web-службы Центрального банка РФ ' Клиентское Web-приложение, потребляющее сервис Web-службы Центрального ' банка России для получения ежедневных курсов валют. На выходе ' приложения получаем таблицу курсов валют.
314 Гпава 12 Public Class WebForml Inherits Systern.Web.UI.Page Private Sub Buttonl_Click(ByVai sender As Object, ByVai e As System.EventArgs) Handles Buttoni.Click ’ Создаем клиентское приложение Web-службы: ’ http://www.cbr.ru/DailyInfoWebServ/DailyInfo.asmx ’ Создаем экземпляр удаленного класса: Dim Валюта As New ru.cbr.www.Dailyinfo Dim Дата As Date = Now ’ Получение ежедневных курсов валют: GridViewl.DataSource = Валюта.GetSeldCursOnDate(Дата) GridViewl.DataBind() End Sub End Class Как и при создании предыдущих клиентов Web-служб, при обработке собы- тия "щелчок на кнопке" создаем экземпляр удаленного класса, в данном слу- чае мы назвали его валюта. На вход его метода GetSeldCursOnDate подаем 1 СИ » * £ httcj/tocaihcst: 1481 (WebForml,ssdx X Вид— Д' т ? ‘.Button Д Vnatne Yu от Years Vcode Veil С ode 5 Азербайажанааш манат И1|!11И1О1И1И |ЖЯ31 944 AZN | ИИ 3L4690 |i|||| ALL Алла-фскнй динар 100 40.4886 12 DZD з Ангольская кванза 345226 9"3 АОА 5? Аргенхинское песо pis' Армянский драм 1000 [жйй 51 AMD | АфганскиГг афгани до(01. 09 2004) 100 605098 ''Uw"'""" iliiliilliiliie ;4i BHD т“ | йдлгдрсгжт лев 22 09 S1 9"5 BGN t Боливийский боливиано 4 150(5 6$ BOB | Ботсванская пула BUT | Брунейский доллар в 20J063 96 BND Рис. 12.13. Ежедневные курсы валют Web-сервиса ЦБРФ
Создание Web-служб и их клиентов 315 текущую дату. Этот метод возвращает данные типа DataSet, которые мы ука- зываем в качестве источника данных Datasource для элемента управления "сетка данных" GridViewl. Фрагмент работы программы показан на рис. 12.13. Убедиться в работоспособности программы можно, открыв решение в папке ВалютыРоссия. В заключение отмечу, что подобную Web-службу имеют также банки других стран, например, Web-служба Национального банка Рес- публики Беларусь расположена по адресу: http://www.nbrb.by/Services/ ExRates.asmx. Пример 101. Получение данных от Web-службы Национального банка Республики Беларусь Windows-приложением Web-служба, предоставляющая текущие курсы валют, есть и у Национально- го банка Республики Беларусь. На примере потребления сервиса Web-службы этого банка создадим Windows-приложение (настольное приложение), полу- чающее справочную информацию о текущих курсах валют в онлайновом ре- жиме. Для решения этой задачи запустим VB2010, выберем шаблон Windows Forms Application. В конструкторе формы добавим кнопку и элемент управ- ления DataGridView. Мы намереваемся на сетку данных DataGridView вы- вести данные с курсами валют. Элемент управления DataGridView в Windows-приложении играет ту же роль, что и GridView в Web-приложении. Методы этих классов похожи, хотя есть и отличия. Следующим этапом разработки клиентского приложения является добавле- ние ссылки на удаленный класс искомой Web-службы. Для этого выберем в пункте меню Project команду Add Service Reference, это приведет к появле- нию диалогового окна Add Service Reference. В этом окне щелкнем кнопку Advanced, а затем кнопку Add Web Reference. В появившемся диалоговом окне Add Web Reference в поле URL введем адрес Web-службы: http://www.nbrb.by/Services/ExRates.asmx и нажмем кнопку Go. В окне ни- же увидим список доступных методов данного сервиса, после этого щелкнем на кнопке Add Reference. При этом в окне Solution Explorer появится ссылка на удаленный класс: by.nbrb.www. Теперь мы можем использовать эту ссыл- ку в программном коде (листинг 12.9).
. 316 Глава 12 : Листинг 12.9. Получение данных от Web-службы Национального банка ' Клиентское Windows-приложение, потребляющее сервис Web-службы ' Национального банка Республики Беларусь для получения ежедневных ' курсов валют. На выходе приложения получаем таблицу курсов валют. Public Class Forml Private Sub Buttonl_Click(ByVai sender As System.Object, ByVai e As System.EventArgs) Handles Buttonl.Click ’ Создаем клиентское приложение Web-службы: ' http://www.nbrb.by/Services/ExRates.asmx ' Создаем экземпляр удаленного класса: Dim Валюта As New by.nbrb.www.ExRates ' А этот сайт я нашел на сайте: ' http://ivbeg.bestpersons.ru/feed/post3279396/ ' Здесь есть ссылки на другие русскоязычные сервисы Dim Дата As Date = Now Dim ds As DataSet = Валюта.ExRatesDaily(Дата) DataGridViewl.DataSource = ds.Tables("DailyExRatesOnDate") End Sub End Class В программном коде выполняем обычные уже в данной главе действия. При обработке события "щелчок на кнопке" Buttonl создаем экземпляр удаленно- го класса, а затем обращаемся к методу класса ExRates, подавая на вход мето- да текущую дату. Этот метод возвращает таблицу курсов валют в формате DataSet. Эту таблицу, называемую DailyExRatesOnDate, указываем в качестве источника данных DataSource ДЛЯ сетки данных DataGridViewl, которую МЫ используем для визуализации таблицы курсов валют. Фрагмент работы программы представлен на рис. 12.14. Убедиться в работоспособности программы можно, открыв решение в папке ВалютЫ-Win. Такое же Web-приложение, решающее такую же задачу вывода на сетку данных курсов валют, можно тестировать, запустив соответствую- щий файл решения в папке BantOTbi Win.
Создание Web-служб и их клиентов 317 Рис. 12.14. Ежедневные курсы валют Web-службы НБРБ Желаю вам, уважаемые читатели, получить не только удовольствие от про- цесса программирования на Visual Basic, но и зарабатывать достойные вас деньги. Извините, всё.

ПРИЛОЖЕНИЕ Описание компакт-диска Перечень проектов с описанием и указанием номеров примеров представлен в табл. П1. Таблица П1. Описание компакт-диска Папка Описание программы Номер примера Hover Простейшая программа с экранной формой, меткой, командной кнопкой и диалоговым окном, отслеживание события MouseHover 1 и2 consojnput Простейшая программа, консольное приложение, кото- рое приглашает пользователя ввести два числа, прове- ряет, ввел ли пользователь числовые данные, осущест- вляет проверку типа введенных данных, складывает введенные числа и выводит результат вычислений в диалоговое окно Зи4 sqrt Программа, которая вводит через текстовое поле число, при нажатии командной кнопки извлекает из него квад- ратный корень и выводит результат на метку Label. В случае ввода не числа сообщает пользователю об этом, очищая текстовое поле. Есть еще одна кнопка — Очистка — для обнуления текстового поля у метки 5 passport Программа для ввода пароля в текстовое поле, причем при вводе вместо вводимых символов некто, "находя- щийся за спиной пользователя", увидит только звездочки 6 CheckBoxI Программа, которая управляет стилем шрифта текста, введенного на метку Label, посредством флажка CheckBox 7 CheckBox2 Совершенствование предыдущей программы. Побито- вый оператор Хог 8
320 Приложение Таблица П1 (продолжение) Папка Описание программы Номер примера Vkladki Программа, позволяющая выбрать текст из двух вари- антов, задать цвет и размер шрифта для этого текста на трех вкладках TabControl с использованием переключа- телей RadioButton 9 Хог Программа пишет в метку Label некоторый текст, а пользователь с помощью командной кнопки делает этот текст либо видимым, либо невидимым. Здесь использо- вано свойство visible. При зависании мыши над кноп- кой появляется подсказка "Нажми меня" (свойство ToolTip) 10 ComboBox_Calc Программа, реализующая функции калькулятора. Здесь для отображения вариантов выбора арифметических действий используется комбинированный список ComboBox 11 Link Программа, которая обеспечивает ссылку для посеще- ния почтового сервера www.mail.ru, ссылку для про- смотра папки C:\Windows\ и ссылку для запуска тексто- вого редактора Блокнот с использованием элемента управления LinkLabel 12 Unico Программа, которая демонстрирует возможность выво- да в форму, а также в диалоговое окно MessageBox гре- ческих букв. Программа приглашает пользователя вве- сти радиус /?, чтобы вычислить длину окружности 13 Sobytie Программа показывает, как создать собственный класс, содержащий процедуру оценки введенной пользовате- лем строки: может ли данное выражение рассматри- ваться как число? Свой негативный ответ процедура сообщает, вызывая событие "плохой ввод" Badinput 14 NewButton Программа создает командную кнопку в форме "про- граммным" способом, т. е. с помощью написания непо- средственно программного кода, не используя при этом панель элементов управления Toolbox. Программа за- дает свойства кнопки: ее видимость, размеры, положе- ние, надпись на кнопке и подключает событие "щелчок на кнопке" 15 Monitoring Программа отображает координаты курсора мыши отно- сительно экрана и элемента управления. Программа содержит форму, список элементов ListBox и два тек- стовых поля. Программа заполняет список ListBox дан- ными о местоположении и изменении положения курсо- ра мыши. В текстовых полях отображаются координаты положения курсора мыши относительно экрана и эле- мента управления ListBox 16
Описание компакт-диска 321 Таблица П1 (продолжение) Папка Описание программы Номер примера Handles Ассоциация нескольких элементов управления с одним событием с помощью Handles. В форме три командные кнопки, и при нажатии указателем мыши любой из них получаем номер нажатой кнопки. При этом в программе предусмотрена только одна процедура обработки собы- тий 17 Ca_my Программа Калькулятор, в которой реализована обра- ботка нескольких событий от разных объектов одной процедурой 18 Key Обработка событий клавиатуры. Программа информи- рует пользователя о тех клавишах и комбинациях кла- виш, которые нажал пользователь 19 Numbers Программа анализа символов, вводимых пользователем в текстовое поле формы. Если символ не является чи- словым, то текстовое поле получает запрет на ввод та- кого символа 20 TXTJJnicode Программа чтения/записи текстового файла в кодировке Unicode 21 TXT_1251 Программа для чтения/записи текстового файла в коди- ровке Windows 1251 22 TXT_edit Простой текстовый редактор. Открытие и сохранение файла с помощью стандартных диалоговых окон. Событие формы Closing 23 RTF-edit Простейший RTF-редактор 24 TXT_print Печать текстового документа. Программа позволяет открыть через стандартный диалог Windows текстовый файл, просмотреть его в текстовом поле программы без возможности изменения текста (Readonly) и при жела- нии пользователя вывести этот текст на принтер 25 Read-Write-bin Чтение/запись бинарных файлов с использованием потока данных 26 SimpleJ mage 1, Simple-lmage2 и Simplejmage3 Программа вывода в форму растрового изображения из графического файла 27 RiS-Form Рисование на форме при нажатой левой или правой кнопке мыши 28 RiS-Figur Рисование в форме графических примитивов: окружно- сти, отрезка, прямоугольника, сектора, текста, эллипса и закрашенного сектора. Выбор того или иного графиче- ского примитива осуществляется с помощью элемента управления ListBox 29
322 Приложение Таблица П1 (продолжение) Папка Описание программы Номер примера SelectColor_my1 и SelectColor_my2 Изменение цвета фона формы BackColor путем пере- бора констант цвета, предусмотренных в VB, с помощью элемента управления ListBox 30 PrintGra Печать графических примитивов 31 print_BMP Печать графического файла формата BMP 32 Clipboard Запись текстовых данных в буфер обмена и их чтение 33 Clip_Picture Запись растрового изображения в буфер обмена и чте- ние его. Работа с элементом управления PictureBox 34 PictureBox__my1 Программа для отображения GIF-анимации 34 Clip_Print Имитация нажатия клавиш <Alt>+<PrintScreen> с помощью функции Microsoft Windows API, а также методом Send класса SendKeys 35 Clip_Save Запись графического содержимого буфера обмена в ВМР-файл 36 Timer Демонстрация использования таймера Timer 37 Clip_Save_Timer Запись каждые 5 секунд текущего состояния экрана в файлы Pic1.BMP, .... Pic5.BMP 38 ТаЬГГХТ Формирование таблицы из двух строковых массивов в текстовом поле, используя функцию String.Format. Результат выводится в окно Блокнота 39 Tabl_TXT_print Программа формирования таблицы на основании двух массивов переменных с двойной точностью. Данную таблицу программа демонстрирует пользователю в тек- стовом поле TextBox. Есть возможность распечатать таблицу на принтере 40 Tabl_HTM_my Вывод таблицы в Internet Explorer 41 TabGrdWin Формирование таблицы с помощью элемента управле- ния DataGridView 42 Tabl_GRD_XML Табличный ввод данных с помощью элементов управ- ления DataGridView, DataTable, DataSet и запись в XML-файл 43 Gaus_grd Программа для решения системы линейных уравнений. Ввод коэффициентов предусмотрен через элемент управления DataGridView 44 Iexplorer__my2 Отображение HTML-таблицы с помощью элемента управления WebBrowser 45 lexplorerjny Отображение Flash-файлов с помощью элемента управления WebBrowser 46
Описание компакт-диска 323 Таблица П1 (продолжение) Папка Описание программы Номер примера Split Отображение Web-страницы и ее HTML-кода с помощью элемента управления WebBrowser 47 wrd Программа проверки орфографии с помощью функции Checkspelling объектной библиотеки MS Word 48 wrdjable Программа вывода таблицы средствами MS Word 49 Excel Обращение к функциям MS Excel из VB2010. Вывод в заголовке формы числа л 50 Excel3 Использование финансовой функции Pmt () объектной библиотеки MS Excel для вычисления суммы периоди- ческого платежа на основе постоянства сумм платежей и постоянства процентной ставки 51 Excels Решение системы линейных алгебраических уравнений с помощью функций объектной библиотеки MS Excel 52 Excel-Grafik Построение графика (диаграммы) средствами объектов компонентной библиотеки MS Excel 53 ACADm Построение средствами объектов библиотеки AutoCAD элементарного чертежа из отрезков и некоторого текста, а затем сохранение этого чертежа в файле формата DWG 54 BD_sdf_3 Отображение таблицы базы данных SQL Server в экран- ной форме 56 BD_mdb Отображение таблицы базы данных MS Access в экран- ной форме 59 DataReaderBDI Чтение всех записей из таблицы БД MS Access на кон- соль с помощью объектов Command и DataReader 60 Sozd_BD2 Создание пустой (без таблиц) базы данных MS Access new_BD.mdb во время работы программы 61 Connect Запись структуры таблицы в пустую базу данных MS Access 62 WritrelnBD Добавление записи в таблицу базы данных MS Access во время работы программы с помощью SQL-запроса на вставку новой записи в таблицу БД 63 DataReaderBD2 Чтение всех записей из таблицы базы данных с помощью объектов Command, DataReader и элемента управления DataGridView 64 DataSet_Grid Чтение таблицы из БД в сетку данных DataGridView С использованием объектов Command, Adapter и DataSet 65 Update Обновление записей в таблице базы данных MS Access 66
324 Приложение Таблица П1 (продолжение) Папка Описание программы Номер примера DelFromDB Удаление записей из таблицы БД с использованием SQL-запроса и объекта Command 67 RegEx2 и RegEx3 Проверка данных, вводимых пользователем, на досто- верность. Программы осуществляют синтаксический разбор введенной пользователем текстовой строки на соответствие ее фамилии на русском языке, а также разбор строки на соответствие ее положительному ра- циональному числу 68 Opacity Управление прозрачностью формы 69 time Вывод времени по Гринвичу в полупрозрачной форме 70 Значок_в_области_ уведомлений Перевод работы программы в фоновый режим и обратно 71 Mov_Form Перемещение формы мышью не только за заголовок, но и за любое место формы 72 Player Реализация функции проигрывателя Windows Media Player 11 73 help Контекстная справка к элементам формы 74 Summa Создание простейшей активной Web-страницы на VB2010, способной складывать числа, введенные поль- зователем 76 Valid 1 Проверка введенных пользователем числовых данных на Web-странице с помощью валидаторов 77 Validations Проверка достоверности ввода имени, адреса e-mail, URL-адреса и пароля пользователя и при успешной проверке направление пользователя на другую, уже разрешенную для него, Web-страницу 78 Login Регистрация и аутентификация пользователя с помощью базы данных MS Access. Данный пример включает в себя две Web-формы: Registration.aspx и Login.aspx. Первая форма приглашает пользователя ввести регист- рационные данные, проверяет правильность ввода имени пользователя и пароля с использованием вали- даторов, регистрирует пользователя в базе данных MS Access и перенаправляет пользователя на уже раз- решенный после регистрации ресурс Secret.aspx. Вто- рая форма Login.aspx запрашивает имя пользователя и пароль, проверяет наличие пользователя с таким име- нем и паролем в ба,зе данных, если такового пользова- теля не оказалось, то пользователь отправляется на регистрацию Registration.aspx, а если есть, то он получает доступ к ресурсу Secret.aspx 79
Описание компакт-диска 325 Таблица П1 (продолжение) Папка Описание программы Номер примера tab Таблица с переменным числом ячеек, управляемая двумя раскрывающимися списками DropDownList 80 Menu Организация перехода на разные страницы сайта (гиперссылки) с помощью раскрывающегося списка DropDownList 81 Ssylka Передача данных между Web-страницами через пара- метры гиперссылки 82 Передача Ввод данных на одной Web-странице и по щелчку на командной кнопке передача их другой странице; обра- ботка и отображение полученных данных второй стра- ницей 83 Передача2 На начальной Web-странице находятся командная кноп- ка ПЕРЕХОД и текстовое поле, которое заполняет поль- зователь. После щелчка на кнопке происходит переход на другую Web-страницу. На новой странице отобража- ется содержимое текстового поля и надпись на кнопке из предыдущей страницы 84 / TabGrdWeb Вывод табличных данных в Web-форму с помощью элемента управления GridView 85 Hash_Grid Вывод в Web-форму хэш-таблицы с помощью элемента управления GridView 86 RWJxt Чтение/запись текстового файла Web-приложением 87 Counter Web-приложение, реализующее счетчик посещений сайта с использованием базы данных и объекта Session 88 Cookie Чтение/запись cookie-файлов 89 Web-изображения Здесь решены две задачи. Первая задача — увеличе- ние изображения при щелчке по нему кнопкой мыши. Вторая задача — смена изображения при наведении на него курсора мыши 90 Текст__Накл_ЗЛ/еЬ Формирование Web-страницей файла изображения ме- тодами класса Graphics, вывод на изображение тексто- вой строки, наклоненной к горизонту на 356°, и демонст- рация этого файла изображения в форме 91 Гостевая_книга Создание гостевой книги сайта 92 AJAX_Timer Web-страница демонстрирует время на метке Labell. На эту метку каждую секунду копируется новое время, но обновляется при этом не вся форму, а только метка с помощью технологии AJAX 93 Погода-Web Web-приложение, потребляющее сервис удаленной Web-службы прогноза погоды 94
326 Приложение Таблица П1 (окончание) Папка Описание программы Номер примера WebSjny Простейшая Web-служба, на вход которой пользователь подает два числа, а метод Web-службы Сумма обеспе- чивает диагностику вводимых данных и вывод суммы введенных чисел 95 Win__client Клиентское Windows-приложение, потребляющее сервис Web-службы из предыдущего примера 96 WebS_Forex Web-служба, которая с помощью синтаксического раз- бора одной из Web-страниц с торговой стратегией на рынке Forex, извлекает торговую рекомендацию для валютной пары EURUSD, предлагаемую данным сайтом на текущий день, и выводит ее потребителю сервиса в виде строки 97 Forex_Win Клиентское Windows-приложение, потребляющее сервис Web-службы из предыдущего примера 98 Client_Morpher Клиентское Web-приложение, потребляющее сервис Web-службы склонения существительных ’’Морфер" 99 Валюты_Россия Клиентское Web-приложение, потребляющее сервис Web-службы Центрального банка РФ для получения ежедневных курсов валют 100 Валюты_\Мп Клиентское Windows-приложение, потребляющее сервис Web-службы Национального банка Республики Беларусь для получения ежедневных курсов валют 101 На компакт-диске также содержатся файлы картинок, баз данных и Flash- ролик, используемые при разработке рассмотренных в книге примеров.
Предметный указатель А s ADO.NET 137, 180 AJAX 292 ASP.NET 228 Screen shot 114 Simple Object Access Protocol (SOAP) 295 SQL Server: С 0 база данных, создание 171 0 таблица, отображение 173 Cookie 275 D w DataSet 137 DataTable 137 Web-сервис 295 Web-служба 295 0 "Морфер"311 м 0 "Прогноз погоды" 297 0 "Торговая рекомендация на рынке Microsoft Access 185 0 создание БД 175 0 таблица 178 Microsoft Excel 156, 158, 161, 165 Microsoft Word 154 Forex" 306 0 валют 313, 315 0 создание 301 Web-хостинг 223 Windows Media Player 212 R RTF-редактор 80
328 Предметный указатель А Аутентификация пользователя 236 Б База данных: О MS Access: ° регистрация и аутентификация пользователя 236 ° создание 175, 182 О SQL Server, создание 171 О чтение записей на консоль 180 Буфер обмена: О изображение 111 О текст 109 в Валидатор 228, 231 Видимость, свойств 38 Вкладка 35 Время: 0 вывод в Web-форму 292 0 вывод в Windows-форму 203 г Гостевая книга 287 График 165 Графический примитив 99, 105 д Данные: О передача с Web-страницы на Web-страницу 254, 258 О проверка 199 ° с помощью валидатора 228 Диаграмма 165 и Изображение: О вывод в форму 93 О смена в Web-форме 282 О увеличение в Web-форме 279 О формирование на Web-странице 284 Инсталляционный пакет 218 к Калькулятор 60 Клавиатура 64, 67 Кнопка, программное создание 53 Кодировка: 0 ANSI 72 0 Unicode 69 0 Windows 1251 73 Комбинированный список 40 Курсор мыши 55 м Метод 15 0 OnPaint 93 н Навигация по Web-страницам 248 О Объект 13 п Переключатель 35 Печать: 0 графического примитива 105 0 графического файла 106 0 файла 84 Приложение, консольное 20 Проверка вводимых данных 199 р Регистрация пользователя 236 с Свойство 13 0 Visible 38
Предметный указатель 329 Сеанс пользователя 274 Сервер 223 Сессия 274 Система: О линейных алгебраических уравнений 161 О линейных уравнений 140 Снимок экрана 114 Событие 51, 57 О клавиатуры 64, 67 О от разных объектов 60 Справочная система 216 Счетчик сообщений сайта 270 Таблица 123 О MS Access: ° заполнение 187 ° отображение в форме 178 ° редактирование в VB2010 176 0 MS Word 154 0 SQL Server, отображение в форме 173 О в Web-форме 261 О вывод в Internet Explorer 130 О обновление записей 194 О переменное число ячеек 245 О создание в пустой БД 185 О удаление записей 197 О чтение записей 189 Текстовый редактор 74 Точка останова 25 ф Файл: О графический: ° вывод в форму 93 ° печать 106 О двоичный, чтение/запись 89 О открытие 74 О сохранение 74 О текстовый: ° печать 84 ° чтение/запись 69, 73, 266 О формат: ° ASMX296 ° СНМ218 □ SWF 147 Фигура: О печать 105 О рисование на форме 99 Флажок 31 Форма 11 О нестандартная 210 О перемещение мышью 210 О прозрачность 202 X Хост 223 Хостинг 223 Хэш-таблица 263 ц Цвет 102 э Элемент управления 57 О Button 53 О CheckBox 31 О ComboBox 40 О DataGridView 136, 189 О DropDownList 248 О GridView261 О HyperLink 251 О ListBox 55 О Microsoft Web Browser 111 О PictureBox 111 О ProgressBar 121 О RadioButton 35 О TabControl 35 О TextBox 26 О Timer 119 О WebBrowser 145

bhv издательство z~~ БХВ-Петербург Издательство одно из старейших на рынке компьютерной литературы, основано в 1993 году. В настоящее время специализируется на выпуске книг не только но и технической и естественно-научной тематики Книги издательства предназначены для широкого круга читателей и объединены в серии, ориентированные на конкретные возрастные и профессиональные категории: • Для студента * Учебное пособие/Учебник i • Азы информатики | • Учебно-методический комплект по информатике и ИКТ . . I для 8™9 классов Л Соловьевой • : • Для начинающих . • На примерах */ Наглядный самоучитель ., .- ♦ Самоучитель .-Щ •' Экспресс-едс/Бьютрый старт • Аппаратные средства * Библио гека Линуксцен i ра • В подлиннике * Глазами хакера * Мастер * Народные сове гы • Недостающее руководство * Профессиональное программи|жание * Системный админис граюр Наши книги можно приобрести во всех крупных магазинах в более чем 100 городах России и СНГ, а также в Германии, США, Израиле. www.bhv.ru Санкт-Петербург, 190005, Измайловский пр., 29 Тел.: +7 (812) 251-42-44, 320-06-42 Факс: (812) 320-01-79 E-mail: opt@bhv.spb.ru Москва, Московская область, г. Видное. Промзона, ксфпус Ж 48 Тел,: *7 (495) 933-32-74 E-mail: bhv@bhvm.ru
bhv® Учебная литература издательства "БХВ-Петербург в продаже: Магазин "Новая техническая книга": СПб., Измайловский пр., д. 29, тел.: (812) 251-41-10 www.techkniga.com Отдел оптовых поставок: e-mail: opt@bhv.spb.su Герман О., Герман Ю. Программирование на Java и C# Дунаев В. Базы данных. Язык SQL для студента, 2-е изд. 320 с. Едомский Ю. Техника Web-дизайна 400 с. Магда Ю. UNIX для студента 480 с. Пахомов Б. С и Borland C++ Builder для студента 448 с. Побегайло А. C/C++ для студента 528 с. Половко A. Derive для студента 352 с. Половко А., Бутусов П. MATLAB для студента 320 с. Половко A. Mathematica для студента 368 с. Пономаренко С. Adobe Photoshop CS2 для студента 464 с. Рудикова Л. Microsoft Excel для студента 368 с. Рудикова Л. Базы данных. Разработка приложений 496 с. Рудикова Л. Microsoft Word для студента 400 с. Скотт К. Java для студента 448 с. Федорова A. CorelDRAW для студента 528 с. Федорова A. Adobe Illustrator для студента 640 с. Серия "На примерах" Богданов М. Visual Basic 2005 на примерах 592 с. Васильев A. Mathcad 13 на примерах 528 с. Васильев A. Excel 2007 на примерах 656 с. Дударева Н. SolidWorks 2007 на примерах 528 с. Кашаев С. Программирование в Microsoft Excel на примерах 320 с. Кашаев С. 1С:Предприятие 8. Учимся программировать на примерах 336 с. Кирьянов Д. Adobe Premiere Pro 2 на примерах 240 с. Кирьянов Д. Pinnacle Studio Plus 11 на примерах 224 с. Кузнецов М. MySQL на примерах 592 с. Климов A. JavaScript на примерах 256 с. Левковец Л. Autodesk Inventor. Базовый курс на примерах 400 с. Левковец Л. AutoCAD 2008. Базовый курс на примерах 480 с.
Левковец Л. Adobe Photoshop CS3. Базовый курс на примерах 592 с. Левковец Л. Adobe InDesign CS3. Базовый курс на примерах 512 с. Мержевич В. HTML и CSS на примерах 448 с. Пестриков В., Маслобоев A. Delphi на примерах 496 с. Пирогов В. Ассемблер на примерах 416 с. Погорелов В. AutoCAD 2008 на примерах 256 с. Поляк-Брагинский А. Администрирование сети на примерах, 2-е изд. 432 с. Потопахин В. Язык С. Освой на примерах 320 с. Сибрина Т. Adobe Photoshop CS3 на примерах 496 с. Слепченко О. Macromedia Flash Professional 8 на примерах 416 с. Слепченко К. Flash CS3 на примерах 480 с. Талалай П. КОМПАС-ЗО V9 на примерах 592 с. Серия "В задачах и примерах" Культин Н. Delphi .NET в задачах и примерах 256 с. Культин Н., Цой Л. C/C++ Builder в задачах и примерах 336 с. Культин Н. Turbo Pascal в задачах и примерах 256 с. Культин Н. C# в задачах и примерах 240 с. Сафронов И. Бейсик в задачах и примерах 400 с. Сафронов И. Visual Basic в задачах и примерах, 2-е изд. 320 с.
www.bhv.ru Дейтел П., Дейтел X., Эйр Г. Просто о Visual Basic 2008 Обучение на практических примерах 3-е издание Магазин "Новая техническая книга": СПб., Измайловский пр., д. 29, тел.: (812) 251-41-10 Отдел оптовых поставок: e-mail: opt@bhv.spb.su Увлекательный способ изучения Visual Basic. Советы и пошаговые ин- струкции позволяют читателям быстро приступить к разработке про- граммных приложений L1NQ WPF and XAML ASP.NET 3.5 ASP.NET AJAX Silverlight™ для Windows Vista® и Windows® XP Книга посвящена разработке приложений в среде Visual Basic 2008. Материал излагается в виде 32 уроков, подготовленных в соответствии с мето- дикой обучения программированию компании Deitel & Associates. На примере разработки более 100 готовых приложений рассматриваются: среда разработки, визуальное программирование, библиотека классов .NET Framework Class Library, эле- менты управления WinForm, обработка событий, отладчик, управляющие операторы, массивы, классы, объекты, базы данных, Web-приложения и др. Показано применение технологий LINQ, ASP.NET 3.5, ASP.NET AJAX, WPF, XAML и Silverlight. На DVD размещен дистрибутив Microsoft Visual Studio 2008 Express Edition, содержащий Visual Basic 2008 Express Edition и другие компоненты пакета.
www.bhv.ru Культин Н., Цой Л. Visual Basic для студентов и школьников Магазин "Новая техническая книга": СПб., Измайловский пр., д. 29, тел.: (812) 251-41-10 Отдел оптовых поставок: e-mail: opt@bhv.spb.su • Среда программирования Visual Basic • Язык программирования Visual Basic • Практикум программирования на Visual Basic • Компоновка материала в соответствии с учебным процессом • Контрольные вопросы и задачи для самостоятельного решения • Программа тестирования ’’Экзаменатор” В книге рассматривается процесс создания программ различного назначения на языке программирования Visual Basic — от простейших до программ работы с графикой и базами данных. Последовательность изложения, дозировка мате- риала, а также наличие контрольных вопросов и задач для решения соотносят- ся с учебным процессом. Демонстрируется среда разработки Visual Basic, при- водится описание языка программирования Visual Basic, рассматриваются основные алгоритмические структуры, операции со строками, одномерными и двухмерными массивами и файлами, большое внимание уделено практике про- граммирования, что позволит полноценно подготовиться к ЕГЭ по информати- ке по разделам, касающимся алгоритмизации и программирования. Приложе- ние содержит справочник по языку программирования Visual Basic и базовым компонентам. На компакт-диске приводятся рассматриваемые в книге примеры программ и программа Экзаменатор, позволяющая автоматизировать процесс контроля и самоконтроля знаний.
Магазин-салон 190005, Санкт-Петербург, гз... 5$ по компьютерным технологиям, радиотехнике и электронике, физике и математике, строительству и архитектуре, транспорту, машиностроению и другим естественно-научным и техническим направлениям Низкие цены Ежедневное пополнение ассортимента Подарки и скидки покупателям Тея.: (812) 251-41-10, e-mail: trade@techkniga.com www.bhv.ru
w Я слышу и забываю. Я вижу и запоминаю. Я делаю и понимаю. Конфуций Visual Basic НА ПРИМЕРАХ ОВ АВТОРЕ Зиборов Виктор Владимирович, кандидат технических наук, доцент кафедры геоинформатики и фотограмметрии Киевского национального университета строительства и архитектуры Автор более 50 научных и учебно-методических работ В книге подробно рассмотрено более сотни типичных примеров, встречающихся в практике реального программирования для платформы NET Framework в среде Microsoft Visual Basic 2010. Примеры расположены в порядке от простого к сложному: простейшие программы с экранной формой и элементами управления, инициирование и обработка событий мыши и клавиатуры, чтение/запись текстовых и бинарных файлов, редактирование графических данных, управление буфером обмена, ввод и вывод табличных данных, использование функций MS Word. MS Excel и AutoCAD, обработка баз данных с использованием технологии ADO.NET, создание веб-служб и их клиентов, программирование веб-приложений и др. Последовательное изучение примеров позволит начинающим быстро освоить новую среду разработки, а опытные пользова- тели найдут готовые решения для использования в своих приложениях О Компакт-диск содержит исходные коды примеров, приведенных в книге. НВ-ПЕТЕРБУРГ 190005, Санкт-Петербург, Измайловский пр., 29 E-mail; mail@bhv.ru Internet: www.bhv.ru Тел. (812)251-42-44 Тел ./факс: (812) 251-12-95