Формы Windows, графический вывод и печать

Почти во всех материалах по .NET-программированию, публикуемых в журналах и Интернете, основное внимание уделяется web-службам, использованию броузера как платформы программирования, ASP .NET и другим темам, так или иначе связанным с Web. Многочисленные усовершенствования в области графического Windows-программирования на стороне клиента удостаиваются разве что кратких упоминаний. Как бы странно это ни звучало для продукта Microsoft, о программировании графических приложений в Visual Studio было сказано слишком мало хорошего; а ведь в этой области появились многие новшества, которых программисты VB ждали в течение нескольких лет!

Бесспорно, программирование на платформе броузера играет все более важную роль, но и традиционные клиентские Windows-приложения умирать не собираются. В этой главе мы попытаемся исправить это упущение и познакомим читателя с основными принципами программирования, необходимого для построения графических приложений в VB .NET.

Visual Studio IDE в отличие от предыдущих версий VB в процессе работы генерирует программный код — и вы должны понимать этот код, чтобы извлечь максимум пользы из средств построения клиентских приложений в .NET.

Мы не будем тратить время на пространные рассуждения о технологиях ускоренной разработки приложений (RAD, Rapid Application Development) в IDE [ В VB .NET, как и в прежних версиях VB, поддерживается визуальное построение пользовательского интерфейса, а новые свойства (такие, как Anchor и Dock) значительно упрощают его разработку. ]и на описания свойств, методов и событий различных элементов — для нормального изложения этого материала понадобилась бы книга вдвое большего объема. Вместо этого мы взглянем на происходящее с точки зрения программиста. Надеемся, читатель досконально разберется в том, как программируются графические приложения в .NET, и в дальнейшем сможет свободно пользоваться документацией или найдет дополнительную информацию в книгах, посвященных графическому программированию.

После общих сведений о формах и элементах мы познакомимся с общими принципами графического программирования в VB .NET. В этой области новый язык несколько отличается от прежних версий VB (например, из него исчезли знакомые функции-примитивы Сircle и Line). Далее рассматривается тема печати, которая в .NET представляет собой частный случай графического вывода. Хотя новые возможности печати неизмеримо шире тех, которые поддерживались в прежних версиях VB, знакомый объект Pri nter теперь не поддерживается, и поддержка печати в программах теперь требует дополнительных усилий.

 

Немного истории

Для работы с формами в прежних версиях VB использовался механизм Ruby Forms. Он представлял собой версию программы Ruby, написанной Аланом Купером (Alan Cooper); в результате объединения Ruby с QuickBasic появился VB11. Таким образом, разработка графических приложений в прежних версиях VB зависела от механизма форм, работа которого была практически полностью скрыта от программиста. Стартовая форма, словно по волшебству, появлялась на экране, а элементы размещались на форме программистом на стадии конструирования [ В VB6 элементы могли добавляться и во время работы программы, но данная возможность почти не использовалась из-за крайне неудобного механизма перехвата событий в этих элементах. ]. В программах С/С++ процесс ручного создания окон и элементов на формах был делом в лучшем случае непростым, и в этой области VB обладал несомненными преимуществами. Впрочем, у этого волшебства была и оборотная сторона — механизм Ruby Forms был недостаточно гибким. Он плохо расширялся, и программисту приходилось мириться со всеми недочетами в его реализации. Возможности использования форм и элементов VB были ограничены; в любых нестандартных ситуациях программисту приходилось широко использовать функции API и перехватывать стандартные сообщения Windows в уродливых конструкциях с субклассированием [ Некоторые пакеты независимых фирм (например, Desa ware Spy Works) упрощали процесс субклас-сирования, но задача все равно оставалась непростой. ]. Даже такая простая задача, как создание списка с ускоренным поиском, требовала вызова функции API; стандартная операция включения новых строк в список усложнялась тем, что свойство Items списка было доступно только для чтения (к счастью, в VB .NET эти проблемы решаются элементарно [ Например, чтобы быстро заполнить список, достаточно присвоить коллекцию свойству DataSource. ]).

Более того, многие программисты не понимали, чем же в действительности были формы VB — классами или экземплярами классов? В каком-то смысле и тем и другим. В результате программа выглядела весьма странно:

Forml.Show ' Я - экземпляр

Dim newForm As New Forml ' А теперь я - класс

newForm.Show

Программисты предпочитают работать с логичными и последовательными моделями, а с точки зрения ООП механизм форм в ранних версиях часто выглядел как нагромождение искусственных и несогласованных «заплат». В VB .NET ситуация полностью изменилась. Здесь формы являются экземплярами класса Windows. Forms. Form, и поведение форм может изменяться посредством наследования точно так же, как и поведение любых других классов .NET Framework. Например, код специализированной формы может начинаться со следующего заголовка:

Public Class MyForm

Inherits System.Windows.Forms.Form

После этого форма наделяется новыми возможностями, для чего программист либо переопределяет члены родительского класса Form, либо добавляет в него новые члены, как для любого другого класса (см. главу 5).

В прежних версиях VB элементы даже не считались полноценными классами, поэтому команды вроде следующей были недопустимыми:

Dim myButton As New CommandButton

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

Возможности создания нестандартных элементов, появившиеся в VB5, были основаны на включении и делегировании, причем в этом процессе использовалась одна из самых непредсказуемых программ-мастеров (wizards) — не говоря уже о том, что элементы, построенные в VB5 и 6, несколько отличались от элементов, построенных на других языках (например, C++ и Delphi).

В .NET элементы и формы являются классами. Как будет показано ниже в этой главе, VB .NET позволяет определить новый класс текстового поля, начинающийся с заголовка следующего вида:

Public Class PositivelntegerTextBox

Inherits System.Windows.Forms.TextBox

Далее программист переопределяет или добавляет методы, как в любом другом классе, причем полученный элемент ничем не отличается от элементов, написанных на С# или управляемом C++.

Короче говоря, в предыдущих версиях VB графические приложения строились на весьма шаткой и ненадежной основе, которая к тому же не была в полной мере объектно-ориентированной. Переход к единой программной модели в рамках объектно-ориентированной версии VB потребовал коренного пересмотра этой структуры. Так появилось новое пространство имен Windows.Forms.