Изучаем Visual Studio .NET Часть 2. Создание Windows-приложений
Использование интерфейсных элементов
Кит Франклин «VB .NET для разработчиков»
Г.Корнелл, Дж.Моррисон «Программирование на VB .NET»
В предыдущем номере мы начали знакомиться с Visual Studio .NET и обсудили основные возможности этой среды разработчика. В этой части статьи мы продолжим изучение Visual Studio .NET и расскажем о создании Windows-приложений с помощью данного средства разработки.
оздание Windows-приложений начинается с того, что мы создаем новый проект типа Windows Application, выбирая соответствующий шаблон для одного из установленных языков программирования — Visual Basic .NET, С# и т.д.
Нажатие кнопки OK приводит к загрузке выбранного нами шаблона и к появлению основных окон среды разработчика. Этими окнами являются:
- окно дизайнера форм;
- палитра компонентов;
- окно для просмотра компонентов приложения (Solution Explorer);
- окно для установки свойств (Properties).
Создание Windows-приложения заключается в расположении компонентов на форме, изменении их свойств, написании кода для обработки возникающих событий и написании кода, определяющего логику самого приложения.
Для переключения между режимом визуального проектирования формы и режимом редактирования кода используются клавиши F7 (режим кода) и Shift-F7 (режим дизайна). На следующем рисунке показана работа в режиме редактирования кода (обратите внимание на то, что вместо Solution Explorer мы включили браузер классов (Class View), который может быть полезен для быстрой навигации по исходному коду создаваемого нами приложения).
Палитра компонентов (ToolBox), вызываемая нажатием клавиш Ctrl-Alt-X, содержит все стандартные компоненты, которые мы можем использовать в Windows-приложениях. Она разделена на несколько вкладок:
- Windows Forms — здесь располагаются компоненты, реализующие различные интерфейсные элементы, используемые в Windows-приложениях;
- Components — здесь мы обнаружим компоненты, выполняющие различные сервисные функции: слежение за изменениями в файловой системе (FileSystemWatcher), регистрацию событий (EventLog), управление очередью сообщений (MessageQueue), управление процессами (Process) и т.д.;
- Data — расположенные на этой вкладке компоненты используются для создания приложений, работающих с базами данных. К таким компонентам, в частности, относятся SqlConenction, OleDbConenction, SqlCommand, OleDbCommand, DataView, DataSet и ряд других (более подробно тему использования баз данных мы рассмотрим в одной из следующих частей статьи);
- Clipboard Ring — представляет собой временное (на период разработки приложения) хранилище, куда можно помещать фрагменты кода. Эта вкладка видна только в режиме редактирования кода.
Использование интерфейсных элементов
оздание интерфейсной части приложения начинается с того, что мы перетаскиваем с палитры компонентов необходимые нам интерфейсные элементы. В таблице представлены основные категории интерфейсных элементов, располагающихся в палитре компонентов на вкладке Windows Forms.
При перетаскивании любого компонента с палитры на форму его свойства и события становятся доступными через окно редактирования свойств — окно Properties. Рассмотрим следующий пример. Допустим, что мы хотим создать программу, позволяющую просматривать графические файлы. Для этого нам потребуются следующие компоненты:
- компонент Button, который мы будем использовать для открытия диалоговой панели для выбора файлов;
- компонент OpenFileDialog, который будет использоваться для выбора графического файла;
- компонент PictureBox, в котором мы будем отображать содержимое графического файла.
Перенесем эти компоненты с палитры компонентов на форму. Обратите внимание на то, что компонент OpenFileDialog не отображается на самой форме, а присутствует в специальной панели, предназначенной для компонентов, которые не имеют визуального представления в режиме дизайна или вообще не являются визуальными.
Следующий шаг — это изменение некоторых свойств компонентов. Начнем с формы и установим значение ее свойства Text равным Graphics View. Далее изменим значение свойства StartPosition на CenterScreen — в результате наше приложение всегда будет отображаться в середине экрана. Если мы хотим, чтобы размер нашего окна нельзя было изменить, мы должны установить значение FormBorderStyle равным FixedSingle или Fixed3D. В противном случае при изменении размера окна нарушится расположение элементов внутри него.
Внутри окна находятся два интерфейсных элемента — кнопка и элемент для отображения графики. У кнопки мы должны изменить свойство Text на Open. Для элемента PictureBox мы установим трехмерную рамку (BorderStyle = Fixed3D), а также изменим свойство Anchor — с его помощью мы укажем, как должны изменяться размеры элемента в зависимости от размеров окна.
Для компонента OpenFileDialog мы изменим следующие свойства:
После того как мы установили основные свойства используемых нами компонентов, мы можем заняться написанием кода для обработчиков событий и кода, реализующего логику нашей программы.
Написание кода
ледуя логике нашей программы, каждое нажатие кнопки Open должно приводить к открытию диалоговой панели OpenFile. Выбор одного файла и нажатие кнопки Open в этой диалоговой панели вызывает отображение этого файла в компоненте PictureBox.
Мы начинаем с того, что создаем обработчик события, возникающего при нажатии кнопки Open. Для этого мы либо дважды щелкаем по кнопке в режиме дизайна, либо в режиме редактирования кода выбираем компонент Button в списке компонентов, расположенном в верхней части редактора, а затем выбираем в списке событие Click. В результате тех или иных действий мы получаем код обработчика события Click нашей кнопки. Мы добавляем в него следующий код:
Dim Bmp As Bitmap If OpenFileDialog1.ShowDialog() = DialogResult.OK Then PictureBox1.SizeMode = PictureBoxSizeMode.StretchImage Bmp = New Bitmap(OpenFileDialog1.FileName) PictureBox1.Image = CType(Bmp, Image) End If
В первой строке мы создаем переменную типа Bitmap, в которую будем загружать содержимое выбранного нами графического файла. Затем мы вызываем метод ShowDialog объекта OpenFileDialog, чтобы отобразить на экране панель выбора файлов. Если файл выбран и нажата кнопка Open, мы выполняем следующие действия:
- задаем режим отображения графики в компоненте PictureBox — в нашем примере графика должна быть «растянута» во весь размер компонента;
- создаем новый экземпляр объекта Bitmap, в который загружаем содержимое выбранного нами файла;
- отображаем содержимое объекта Bitmap в компоненте PictureBox.
Давайте изменим наше приложение и вместо кнопки будем использовать меню. Для этого удалим компонент Button и перетащим из палитры компонентов компонент MainMenu. Создадим элемент File и два подэлемента — Open и Exit. Для этого воспользуемся редактором меню, предоставляемым Visual Studio .NET и вызываемым при щелчке мышью по компоненту MainMenu.
После того как меню готово, нам необходимо написать код, который будет выполняться при выборе той или иной команды. Для этого мы дважды щелкаем мышью по соответствующей команде и попадаем в редактор кода. Для команды File | Open переносим код, созданный нами для обработчика события, связанного с нажатием на кнопку. Для команды File | Exit мы напишем следующий код:
Application.Exit()
Выполнение этого кода приведет к завершению нашего приложения и к закрытию его окна.
Создание MDI-приложений
осле того как мы освоили создание меню, давайте изменим функциональность нашего приложения таким образом, чтобы каждый выбранный графический файл открывался в новом дочернем окне, то есть превратим наше однооконное приложение в Multiple Document Interface (MDI)-приложение.
Создание MDI-приложения мы начинаем с того, что изменяем свойство IsMDIContainer нашей формы и присваиваем ему значение True. После этого мы используем команду Project | Add Windows Form для добавления к нашему проекту еще одной формы, которая будет служить в качестве дочерней формы. В диалоговой панели Add New Item мы выбираем элемент Windows Form и нажимаем кнопку Open.
Перенесем компонент PictureBox из главной формы нашего приложения в дочернюю форму. Для этого следует выбрать компонент PictureBox, нажать клавишу Ctrl-X, затем перейти на дочернюю форму и нажать клавишу Ctrl-V. Наше MDI-приложение практически готово — нам осталось лишь изменить код, выполняющийся при выборе команды File | Open, теперь он будет выглядеть следующим образом (внесенные нами изменения показаны выделенным шрифтом):
Private Sub MenuItem2_Click(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles MenuItem2.Click Dim Bmp As Bitmap Dim Child As New Form2() Child.MdiParent = Me If OpenFileDialog1.ShowDialog() = DialogResult.OK Then Child.PictureBox1.SizeMode = PictureBoxSizeMode.StretchImage Bmp = New Bitmap(OpenFileDialog1.FileName) Child.PictureBox1.Image = CType(Bmp, Image) Child.Show() End If End Sub
Сначала мы создаем переменную Child, которая имеет тип Form2 и будет использоваться для создания дочерних форм. Затем указываем родительское окно дочерней формы — ключевое слово Me используется в Visual Basic для указания текущего класса. Поскольку компонент PictureBox теперь располагается в дочернем окне, мы изменяем способ обращения к нему. После того как графика загружена, мы показываем нашу дочернюю форму на экране.
Для того чтобы сделать наше приложение более удобным, давайте показывать в заголовке дочернего окна полное имя отображаемого в нем файла. Для этого добавим в код обработчика события следующую строку:
Child.Text = OpenFileDialog1.FileName
Если же мы мы хотим отобразить только имя файла, нам надо написать такой код:
Dim FI As FileInfo ... FI = New FileInfo(OpenFileDialog1.FileName) Child.Text = FI.Name ...
и добавить ссылку на пространство имен System.IO в самом начале кода нашей программы:
Imports System.IO
Теперь давайте добавим код, который позволит нам управлять дочерними окнами. Начнем с того, что создадим еще один пункт меню — Childs и добавим в него следующие элементы: Tile Horizontal; Tile Vertical; Cascade; Arrange Icons.
Затем напишем код для каждой из команд:
' ' Команда TileHorizontal ' Private Sub MenuItem6_Click(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles MenuItem6.Click Me.LayoutMdi(MdiLayout.TileHorizontal) End Sub ' ' Команда TileVertical ' Private Sub MenuItem7_Click(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles MenuItem7.Click Me.LayoutMdi(MdiLayout.TileVertical) End Sub ' ' Команда Cascade ' Private Sub MenuItem8_Click(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles MenuItem8.Click Me.LayoutMdi(MdiLayout.Cascade) End Sub ' ' Команда ArrangeIcons ' Private Sub MenuItem9_Click(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles MenuItem9.Click Me.LayoutMdi(MdiLayout.ArrangeIcons) End Sub
Включим еще одну возможность — меню для переключения между окнами. Добавим к главному меню элемент Window и изменим значение его свойства MdiList на True.
Теперь попробуем использовать еще один компонент — ContextMenu, который позволит нам изменять способ отображения графики в компоненте PictureBox.
Добавим компонент ContextMenu к дочерней форме и создадим в нем следующие элементы: Normal; Center; Stretch; Autosize, которые повторяют все возможные значения свойства SizeMode компонента PictureBox. Установим свойство ContextMenu компонента PictureBox в ContextMenu1. Затем напишем код, который будет выполняться при вызове каждой из команд контекстного меню:
Private Sub MenuItem1_Click(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles MenuItem1.Click PictureBox1.SizeMode = PictureBoxSizeMode.Normal End Sub Private Sub MenuItem2_Click(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles MenuItem2.Click PictureBox1.SizeMode = PictureBoxSizeMode.CenterImage End Sub Private Sub MenuItem3_Click(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles MenuItem3.Click PictureBox1.SizeMode = PictureBoxSizeMode.StretchImage End Sub Private Sub MenuItem4_Click(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles MenuItem4.Click PictureBox1.SizeMode = PictureBoxSizeMode.AutoSize End Sub
После этого нам надо удалить строку:
Child.PictureBox1.SizeMode = PictureBoxSizeMode.StretchImage
из обработчика события выбора команды File | Open в главном меню нашего приложения.
Файл проекта и генерация кода
icrosoft Visual Studio .NET автоматически генерирует необходимый код для инициализации формы, добавляемых нами компонентов и т.п. Для каждой формы создается отдельный файл, который имеет то же имя, что и класс, описывающий форму. Вся информация о том, из чего состоит наше приложение, находится в файле с расширением .sln (Microsoft Visual Studio Solution File). В этом файле, в частности, написано, как называется наше приложение и какой файл проекта относится к нему. Файл проекта, имеющий расширение, отражающее выбранный нами язык программирования (WinApp.vbproj в нашем примере), — это XML-файл, содержащий все необходимые характеристики проекта. В частности, здесь есть информация о платформе, для которой создается результирующий файл (OutputType = “WinExe” в нашем примере), о начальном объекте (StartupObject = “WinApp.Form1” в нашем примере), имя корневого пространства имен (RootNamespace = “WinApp” в нашем примере). Отдельный интерес представляет список ссылок на пространства имен, доступных по умолчанию (остальные, как мы видели выше, надо указывать с помощью ключевого слова Imports), а также список импортируемых пространств имен, который для Windows-приложения выглядит так:
<Imports> <Import Namespace = "Microsoft.VisualBasic" /> <Import Namespace = "System" /> <Import Namespace = "System.Collections" /> <Import Namespace = "System.Data" /> <Import Namespace = "System.Drawing" /> <Import Namespace = "System.Diagnostics" /> <Import Namespace = "System.Windows.Forms" /> </Imports>
Список файлов, из которых состоит наше приложение, располагается в секции Files. Вид этой секции для нашего примера показан ниже (обратите внимание на различные значения атрибутов SubType, а также на автоматическое создание необходимых файлов):
<Files> <Include> <File RelPath = "AssemblyInfo.vb" SubType = "Code" BuildAction = "Compile" /> <File RelPath = "Form1.vb" SubType = "Form" BuildAction = "Compile" /> <File RelPath = "Form1.resx" DependentUpon = "Form1.vb" BuildAction = "EmbeddedResource" /> <File RelPath = "Form2.vb" SubType = "Form" BuildAction = "Compile" /> <File RelPath = "Form2.resx" DependentUpon = "Form2.vb" BuildAction = "EmbeddedResource" /> </Include> </Files>
Файл AssemblyInfo содержит всю необходимую информацию о сборке. Если мы не задали эту информацию, то используются значения по умолчанию.
Все файлы, применяемые в качестве шаблонов для Windows-приложения, располагаются в каталоге (показан пример для Visual Basic):
C:\Program Files\Microsoft Visual Studio .NET\Vb7\ VBWizards\WindowsApplication\Templates\1033
Здесь мы найдем файлы, представляющие собой «шаблон» Windows-приложения: AssemblyInfo.VB; Form.VB; WindowsApplication.vbproj.
Файл, в котором располагается код, отвечающий за функционирование формы, состоит из двух частей. Первая из них, с меткой “Windows Form Designer generated code”, содержит код, который копируется из шаблона приложения, — этот код не должен редактироваться программистами! Чтобы ограничить доступ к нему, в редакторе кода в Visual Studio .NET он помечается специальным образом, как это показано на следующем рисунке.
Код между этим блоком и завершением класса (End Class) либо создается нами, либо генерируется Visual Studio .NET — например, сюда помещается код обработчиков событий, а также код, реализующий логику нашего приложения.
Заглянув в блок “Windows Form Designer generated code”, мы обнаружим там инициализационный код, который может пояснить нам базовые принципы организации Windows-приложений, создаваемых средствами Microsoft .NET. Эту тему мы обсудим в следующем номере.
Заключение
этой части статьи мы научились с помощью Microsoft Visual Studio .NET создавать Windows-приложения. Мы рассмотрели основные элементы среды разработки, используемые в этом процессе, кратко ознакомились с типами интерфейсных элементов, а также узнали, как создать простое однооконное и MDI-приложение. Мы также рассмотрели файлы, из которых состоит проект, и ознакомились с их содержимым.
Мы продолжим знакомство с Microsoft Visual Studio .NET в следующем номере, где поговорим о базовых принципах организации Windows-приложений и приведем ряд примеров использования компонентов, реализующих интерфейсные элементы, а также компонентов, выполняющих различные серверные функции.
КомпьютерПресс 5'2002