Создание диалоговых окон
Чтобы вывести собственное диалоговое окно, создайте форму, задайте ее свойствам ControlBox,
MinimizeBox и MaximizeBox значение False, а свойству Modal — значение True. Форму следует выводить методом ShowDialog в режиме модального диалогового окна. Если при этом задать свойство TopMost равным True, диалоговое окно будет располагаться поверх всех окон на экране (и вам уже не придется использовать функцию API SetWindowPos).
Однако поведение стандартных кнопок несколько изменилось по сравнению с VB6. Свойства Default и Cancel не поддерживаются, поэтому соответствующие элементы-кнопки назначаются свойствам AcceptButton и Cancel Button:
Me.AcceptButton = btnOK Me.Cancel Button = btnCancel
После вызова ShowDialog программа может узнать, какая кнопка была нажата на форме, при помощи свойства Dial ogResult кнопки или самой формы (нажатие кнопки с заданным свойством DialogResul t приводит к автоматическому закрытию формы, на которой эта кнопка находится).
Размещение
элементов на форме во время выполнения
1 Private Sub Forml_Load(ByVal sender As System.Object,ByVal e As _
2 System.EventArgs) Handles MyBase.Load
3 Dim newButton As New System.Windows.Forms.Button()
4 ' Задать свойства newButton
5 With newButton
6 .Visible =True
7 .Size =New Size(l00.l00)
8 ' .Text ="I'm a new button"
9 ' Обычно здесь задаются и другие свойства
10 End With
11 Me.Controls.Add(newButton)
12 AddHandler newButton.Click.AddressOf Me.newButton_Click
13 End Sub
14 Public Sub newButton_Click(ByVal sender As _
15 System.Object.ByVal e As System.EventArgs)
16 MsgBox("You clicked on my new button")
17 End Sub
В строке З создается новая кнопка, а в строках 5-10 удобная сокращенная запись With используется для задания ряда свойств объекта newButton. Только в строке 11 новая кнопка размещается на форме. Строка 12 снова демонстрирует замечательную гибкость механизма обработки событий .NET: код, содержащийся в строках 14-17, назначается обработчиком события для кнопки. Возможный результат выполнения программы показан на рис. 8.15.
Рис.
8.15. Создание кнопки во время выполнения программы
Прежде всего следует сказать, что «визуальное наследование», часто упоминаемое в рекламных материалах по VB .NET, существует лишь в больном воображении специалистов по маркетингу. На самом деле речь идет о том, что формы, созданные в программе, могут использоваться как основа для определения новых форм посредством наследования. Конечно, это весьма удобно и полезно, но ничего принципиально нового в таком наследовании нет. Класс формы, производный от Windows. Forms. Form и дополненный специализированными свойствами, методами и событиями, в дальнейшем может использоваться в качестве базового для определения новых классов.[ История с «визуальным наследованием» как нельзя лучше демонстрирует тупость специалистов по рекламе. Возможно, эффектный термин поразит некомпетентноге менеджера, но у программистов он лишь вызывает раздражение. ]
Предположим, вы хотите создать для своей организации окно-заставку (splash screen), которое отдельные подразделения будут дополнять своими данными. Базовая форма создается следующим образом:
- Выполните команду File
> New > Project.
- Выберите тип приложения
Windows Application, введите в поле Name строку SplashScreeriBase и нажмите
кнопку ОК.
- Щелкните правой кнопкой
мыши в строке SplashScreenBase окна решения и выберите в контекстном меню
команду Properties.
- Выберите в раскрывающемся
списке Output Type строку Class Library (вместо Windows Application). Нажмите
кнопку ОК.
- Сконструируйте форму,
разместите на ней нужные элементы, реализуйте свойства, методы и события.
- Откомпилируйте программу.
Public Class Form1
Inherits SplashScreenBase. Form1
Все остальное за вас сделает механизм наследования! Этот способ особенно хорош тем, что работа дизайнера автоматически синхронизируется с унаследованной формой.
Построение
нестандартных элементов на базе наследования
Public Class PositivelntegerTextBox
Inherits System . Windows . Forms . TextBox
Остается лишь запрограммировать поле на нужное поведение. В оставшейся части этого раздела будет показано, как класс Positi velntegerTexBox наполняется специализированными свойствами, событиями и методами.
Итак, создайте новую библиотеку классов и включите в решение ссылку на сборку Windows.Forms.dll.
Начнем с переопределения событий базового класса. Например, событие OnChange поможет предотвратить ввод в поле всего, что не является целым числом. Следующий обработчик разрешает вводить или вставлять из буфера только положительные целые числа:
1 Public Class PositivelntegerTextBox
2 Inherits System.Windows.Forms.TextBox
3 Protected Overrides Sub OnTextChanged(ByVal e As EventArgs)
4 MyBase.OnTextChanged(e)
5 If Not (IsNumeric(Me.Text))Then
6 Me.Text - String.Empty
7 Else
8 Dim temp As Decimal
9 temp = CType(Me.Text.Decimal)
10 If temp - Math.Round(temp.0) <> 0 Then
11 Me.Text = String.Empty
12 End If
13 End If
14 End Sub
15 End Class
В строках 1 и 2 объявляется специализированная версия обычного текстового поля. Поскольку при специализации на базе наследования сохраняются все члены базового класса, которые не подверглись явным изменениям, вам не придется прибегать к услугам программы-мастера (как в VB6), чтобы решить вопрос с неизменными свойствами — например, с основным цветом. При переопределении событий в производном классе обычно вызывается обработчик базового класса, как в строке 4. Необходимость этой строки связана с тем, что мы не программируем обработку этого события от начала и до конца, а хотим воспользоваться унаследованными аспектами поведения базового класса. В строках 5-6 предотвращается ввод нечисловых данных типа 32Skiddoo. В строках 9-12 из текстового поля удаляются дробные числа; при помощи встроенной функции Round программа убеждается в том, что округленное число совпадает с исходным. Следует заметить, что простое уничтожение введенного текста выглядит несколько жестоко по отношению к пользователю. В более изощренной программе следовало бы сохранить предыдущий текст, чтобы восстановить его при необходимости. В этом случае одна ошибка ввода не будет приводить к полной потере введенных данных.
На этой стадии приведенный выше фрагмент можно откомпилировать в DLL и получить вполне работоспособный элемент. Чтобы протестировать элемент после компиляции, создайте новое приложение Windows и поместите элемент на панель элементов:
- Выполните команду Tools
> Customize Toolbox (или нажмите Ctrl+T).
- Перейдите на вкладку
.NET Framework Components.
- Нажмите кнопку Browse
и выберите DLL нужнопа^лемента (библиотека находится в подкаталоге \bin основного
каталога решения).
Рис.
8.16. Нестандартный элемент на вкладке .NET Framework Components
Рис.
8.17. Нестандартный элемент на панели элементов
Добавить поддержку нового события в элемент ничуть не сложнее, чем включить обработчик события в класс (эта тема рассматривалась в главе 6). Предположим, каждый раз, когда пользователь вводит нечто отличное от положительного целого числа, элемент должен инициировать событие BadDataEntered. Новый код класса выделен жирным шрифтом:
Public Class PositivelntegerTextBox Inherits System.Windows.Forms.TextBox Public Event BadDataEntered(ByVal Sender As Object, _ ByVal e As EventArgs)
Protected Overrides Sub OnTextChanged(ByVal e As EventArgs) MyBase.OnTextChanged(e)
If Not (IsNumeric(Me.Text)) Then Me.Text = String.Empty
RaiseEvent BadDataEntered(Me. New System.EventArgs()) Else
Dim temp As Decimal temp = CType(Me.Text,Decimal) If temp = Math.Round(temp.0) <> 0 Then Me.Text = String.Empty
RaiseEvent BadDataEntered(Me, New System.EventArgs()) End If End If End Sub End Class
В элементах VB существует понятие события по умолчанию (default event). Событие по умолчанию срабатывает автоматически при двойном щелчке на экземпляре элемента в дизайнере форм. Событие по умолчанию задается при помощи специального атрибута. Атрибуты соответствуют экземплярам класса System.Attribute; атрибут Def aul tEvent входит в пространство имен System. ComponentModel. В программе атрибуты заключаются в угловые скобки, а при установке атрибута Defaul tEvent указывается имя события в кавычках. Чтобы назначить событие BadDataEntered событием по умолчанию для данного элемента, приведите начало класса к следующему виду:
Imports System.ComponentModel <DefaultEvent("BadDataEntered")> Public Class _
PositivelntegerTextBox Inherits System.Windows.Forms.TextBox