Balloon.Color = Red
Balloon.Diameter = 10
Balloon.Inflated = True
Balloon.Inflate
Balloon.Deflate
Balloon.Rise 5
Sub Ballon_Puncture()
Balloon.Deflate
Balloon.MakeNoise "Bang"
Balloon.Inflated = False
Balloon.Diameter = 1
End Sub
Dim Имя_переменной As Имя_типа
Dim i As Integer 'объявляется переменная i целого типа
Dim s As String 'объявляется переменная s типа строки символов
Dim a(500) As Integer
a(i) = a(i)+1 'Увеличили i-ый элемент массива на 1
j = a(80*(m-1)+n) 'В скобках после а - индексное выражение
Dim i As Integer
Перейдем теперь непосредственно к программированию набора операндов.
Private Sub cmdNum_Click(Index As Integer)
End Sub
представляющая собой "процедурные скобки": строку заголовка процедуры и строку ее завершения. Тело процедуры пока пусто; эту пустоту мы и должны заполнить нужным нам кодом.
Private Sub cmdNum_Click(Index As Integer)
If Index < 10 Then
txtOp(i).Text = txtOp(i).Text & Index 'Приписываем цифру,
Else
txtOp(i).Text = txtOp(i).Text & "." 'или точку
End If
End Sub
Несмотря на свою простоту, текст приведенного обработчика нуждается в ряде замечаний.
Если Index < 10 То
txtOp(i).Text = txtOp(i).Text & Index
Иначе
txtOp(i).Text = txtOp(i).Text & "."
На языке Visual Basic это предложение записывают тем же самым образом, но ключевые слова Если, То, Иначе пишутся по-английски: If, Then, Else. Кроме того, мы должны как-то указать окончание второй ветви (после Иначе). В естественном языке для этого мы используем точку. В тексте программы на VB используют словосочетание Конец Если
(End If
).
Dim i As Integer ' - Секция общих объявлений (деклараций)
Private Sub cmdCos_Click() 'Косинус
txtOp(i).Text = Cos(Val(txtOp(i).Text))
End Sub
Private Sub cmdCube_Click() 'Возведение в куб
txtOp(i).Text = Val(txtOp(i).Text) ^ 3
End Sub
Private Sub cmdDevide_Click() 'Деление
If Val(txtOp(1).Text) <> 0 Then
lblRes.Caption = Val(txtOp(0).Text) / Val(txtOp(1).Text)
Else
lblMes.Caption = "Делить на 0 не умею!!!"
End If
lblRes.BackColor = &H80000009
lblOper.Caption = "/"
lblOper.BackColor = &H80000009
End Sub
Private Sub cmdMinus_Click() 'Вычитание
lblRes.Caption = Val(txtOp(0).Text) - Val(txtOp(1).Text)
lblRes.BackColor = &H80000009
lblOper.Caption = "-"
lblOper.BackColor = &H80000009
End Sub
Private Sub cmdMod_Click() 'Остаток от деления
lblRes.Caption = Val(txtOp(0).Text) Mod Val(txtOp(1).Text)
lblRes.BackColor = &H80000009
lblOper.Caption = "mod"
lblOper.BackColor = &H80000009
End Sub
Private Sub cmdMult_Click() 'Умножение
lblRes.Caption = Val(txtOp(0).Text) * Val(txtOp(1).Text)
lblRes.BackColor = &H80000009
lblOper.Caption = "*"
lblOper.BackColor = &H80000009
End Sub
Private Sub cmdOpposit_Click() 'Противоположное
txtOp(i).Text = -Val(txtOp(i).Text)
End Sub
Private Sub cmdPlus_Click() 'Сложение
lblRes.Caption = Val(txtOp(0).Text) + Val(txtOp(1).Text)
lblRes.BackColor = &H80000009
lblOper.Caption = "+"
lblOper.BackColor = &H80000009
End Sub
Private Sub cmdPower_Click() 'Возведение в степень
If Val(txtOp(0).Text) = 0 And Val(txtOp(1).Text) <= 0 Then
lblMes.Caption = "Думай, что делаешь!"
Else
lblRes.Caption = Val(txtOp(0).Text) ^ Val(txtOp(1).Text)
lblRes.BackColor = &H80000009
lblOper.Caption = "^"
lblOper.BackColor = &H80000009
End If
End Sub
Private Sub cmdReverse_Click() 'Обратное
If Val(txtOp(i).Text) <> 0 Then
txtOp(i).Text = 1 / Val(txtOp(i).Text)
Else
lblMes.Caption = "Делить на 0 не умею!!!"
End If
End Sub
Private Sub cmdRoot_Click() 'Квадратный корень
If Val(txtOp(i).Text) < 0 Then
lblMes.Caption = "Корень из отрицательного - это круто!"
Else
txtOp(i).Text = Sqr(Val(txtOp(i).Text))
End If
End Sub
Private Sub cmdSin_Click() 'Синус
txtOp(i).Text = Sin(Val(txtOp(i).Text))
End Sub
Private Sub cmdSquare_Click() 'Возведение в квадрат
txtOp(i).Text = Val(txtOp(i).Text) ^ 2
End Sub
В последнем фрагменте мы оформляем присвоение начального значения глобальной переменной i, хранящей индекс поля ввода, бывшего в фокусе последним. Начальные присвоения делаются обычно при загрузке формы (событие Load):
Private Sub Form_Load() 'Загрузка формы
i = 0 'Присвоение начального значения переменной i
End Sub
В процессе же работы калькулятора значения этой переменной будут присваиваться при каждом получении фокуса тем или иным полем ввода (а возможные предупреждающие сообщения от предыдущей операции гасятся):
Private Sub txtOp_GotFocus(Index As Integer) 'Получение
lblMes.Caption = "" 'фокуса полем ввода
i = Index 'Запоминаем в i индекс поля ввода, получавшего фокус последним
End Sub
При любых изменениях в полях ввода восстанавливается первоначальный цвет фона у ярлыков операции и результата:
Private Sub txtOp_Change(Index As Integer) 'Изменение поля
lblOper.BackColor = &H8000000A 'ввода
lblRes.BackColor = &H8000000A
End Sub
Для быстрой очистки полей ввода мы используем двойной клик:
Private Sub txtOp_DblClick(Index As Integer) 'Очистка поля
txtOp(i).Text = "" 'ввода
End Sub
И, наконец, запрограммируем кнопку выхода (хотя всегда есть возможность выйти путем закрытия окна программы стандартным средством управления окном):
Private Sub cmdExit_Click()
End
End Sub
Первая версия калькулятора создана! В ней всего 60 строк кода, введенного нами с клавиатуры.
Private Sub cmdNum_Click(Index As Integer)
txtOp(i).SelText = "" 'Удаляем выделенное (если оно есть) перед
'его заменой
txtOp(i).SetFocus
If Index < 10 Then
txtOp(i).Text = txtOp(i).Text & Index
SendKeys Index 'Приписываем цифру
Else
txtOp(i).Text = txtOp(i).Text & "."
SendKeys "." 'или точку
End If
End Sub
Private Sub cmdBksp_Click()
txtOp(i).SetFocus
SendKeys "{BKSP}"
End Sub
Private Sub cmdDel_Click()
txtOp(i).SetFocus
SendKeys "{DEL}"
End Sub
Private Sub cmdToClip_Click()
Clipboard.SetText lblRes.Caption 'Запоминаем результат в буфере
End Sub
а метод GetText - копирует в строку из буфера обмена в строковую переменную (в том числе, свойство):
Private Sub cmdFromClip_Click()
txtOp(i).Text = Clipboard.GetText 'Копируем из буфера обмена
End Sub
№ п/п |
Наименование товара |
Единица измерения |
Количество единиц |
Учетная цена ед. (руб.) |
Номер склада |
1 |
Дискеты 3,5'' |
Коробка |
5 |
400 |
3 |
2 |
Дискеты 3,5'' |
Коробка |
28 |
400 |
5 |
3 |
Дискеты 5,25'' |
Коробка |
1 |
200 |
1 |
4 |
Дискеты 5,25'' |
Коробка |
2 |
200 |
2 |
5 |
Дискеты 5,25'' |
Коробка |
1 |
200 |
3 |
№ п/п |
Наименование товара |
Единица измерения |
Учетная цена ед. (руб.) |
Идентификационный номер товара |
1 |
Дискеты 5,25'' |
Коробка |
200 |
103 |
2 |
Дискеты 3,5'' |
Коробка |
400 |
102 |
№ п/п |
Идентификационный номер товара |
Единица измерения |
Количество единиц |
Номер склада |
1 |
103 |
Коробка |
1 |
1 |
2 |
103 |
Коробка |
2 |
2 |
3 |
102 |
Коробка |
5 |
3 |
4 |
103 |
Коробка |
1 |
3 |
5 |
102 |
Коробка |
28 |
5 |
EnglWord |
RusWord |
Image |
Wave |
DOG |
Собака |
<ссылка на файл> |
<ссылка на файл> |
DOLPHIN |
Дельфин |
<ссылка на файл> |
<ссылка на файл> |
DONKEY |
Осел |
<ссылка на файл> |
<ссылка на файл> |
Private Sub cmdBrows_Click()
Static i
i = i + 1
If i Mod 2 = 1 Then
Drive1.Visible = True 'Делаем видимыми элементы броузера,
Dir1.Visible = True
File1.Visible = True
Image1.Visible = False 'а отображение графики отключаем
cmdBrows.Caption = "OK"
Else
Drive1.Visible = False 'После настройки - наоборот
Dir1.Visible = False
File1.Visible = False
Image1.Visible = True
'Генерируем случайный индекс:
li = li_o = Int(lsbRus.ListCount * Rnd)
'Отображаем соответствующее ему русское слово:
lblWord.Caption = lsbRus.List(li)
'И картинку:
Image1.Picture = LoadPicture(File1.Path + "\" + _
Mid(Str(lsbRus.ItemData(li)), 2) + ".jpg")
cmdBrows.Caption = "Обзор..."
End If
End Sub
Dim li As Integer, li_o As Integer, t As Integer, _
n As Integer, nf As Integer
' li - индекс очередного элемента в списке русских слов
' li_o - индекс предыдущего -//-
' t - счетчик секунд теста
' n - число ответов во время теста
' nf - из них правильных
Private Sub Drive1_Change()
Dir1.Path = Drive1.Drive 'Свойство Drive - текущий диск,
End Sub 'Path - текущий каталог на текущем диске
Private Sub Dir1_Change()
File1.Path = Dir1.Path
lblPath.Caption = Dir1.Path 'Отображаем текущий путь
End Sub
Private Sub File1_Click()
'Собственно, при работе с броузером файл выбирать нам не
'требуется, но если кликнем его, отобразится картинка.
Image1.Visible = True
Image1.Picture = LoadPicture(File1.Path + "\" + _
File1.filename)
End Sub
Private Sub cboEngl_Click()
n = n + 1
If cboEngl.ItemData(cboEngl.ListIndex) = _
lsbRus.ItemData(li) Then
MMControl1.filename = File1.Path + "\" + _
Mid(Str(lsbRus.ItemData(li)), 2) + ".wav"
Else
lblFault.Visible = True
'Ошибку сопровождает звуковой сигнал:
MMControl1.filename = File1.Path + "\" + "ugly.wav"
nf = nf + 1
End If
'Запускаем таймер tmrDelay:
tmrDelay.Enabled = True
'Команда "sound" определена для устройства WaveAudio и
'не требует его предварительного открытия:
MMControl1.Command = "sound"
End Sub
Private Sub tmrDelay_Timer()
li = Int(lsbRus.ListCount * Rnd)
'Если очередной индекс совпал с предыдущим:
If li = li_o Then
If li = lsbRus.ListCount - 1 Then
li = li - 1
Else
li = li + 1
End If
End If
'Отображаем случайно выбранное слово:
lblWord.Caption = lsbRus.List(li)
'И соответствующую картинку:
Image1.Picture = LoadPicture(File1.Path + "\" + _
Mid(Str(lsbRus.ItemData(li)), 2) + ".jpg")
'А сам таймер после этого останавливаем:
tmrDelay.Enabled = False
'И считаем, что очередная итерация стала уже предыдущей:
lblFault.Visible = False
li_o = li
End Sub
Private Sub tmrSec_Timer()
t = t + 1
cmdStart.Caption = Str(t) + " сек."
End Sub
Private Sub cmdStart_Click()
t = 0 'Обнуляем счетчик секундомера
n = 0 'Количество ответов во время теста
nf = 0 'Из них правильных
Drive1.Visible = False
Dir1.Visible = False
File1.Visible = False
li = Int(lsbRus.ListCount * Rnd)
If li = li_o Then
If li = lsbRus.ListCount - 1 Then
li = li - 1
Else
li = li + 1
End If
End If
lblWord.Caption = lsbRus.List(li)
Image1.Visible = True
Image1.Picture = LoadPicture(File1.Path + "\" + _
Mid(Str(lsbRus.ItemData(li)), 2) + ".jpg")
tmrSec.Enabled = True
tmrTest.Enabled = True
li_o = li
End Sub
Select Case Выражение Case Диапазон_1 Блок_1 Case Диапазон_2 Блок_2 ........................ Case Диапазон_n Блок_n Case Else Блок_default End Select
Is Оператор Выражение где Оператор - один из 6 операторов сравнения: < (меньше) <= (меньше, либо равно) > (больше) >= (больше, либо равно) = (равно) <> (не равно)
Private Sub tmrTest_Timer()
Dim e As Integer
cmdStart.Caption = "Запуск теста (60 сек.)"
tmrDelay.Enabled = False
tmrSec.Enabled = False
lblFault.Visible = False
Select Case n - nf
Case Is > 9
If nf = 0 Then
e = 5
Else
e = 4
End If
Case 7 To 9
If nf = 0 Then
e = 4
Else
e = 3
End If
Case 4 To 6
If nf = 0 Then
e = 3
Else
e = 2
End If
Case Else
e = 2
End Select
MsgBox "Дано " & n & " ответов; число Ваших ошибок:" & _
nf & Chr(13) & "Отметка: " & e, vbInformation,"ТЕСТ"
tmrTest.Enabled = False
End Sub
В приведенном обработчике можно отметить также обращение к функции MsgBox, которая выводит на экран заданную программистом информацию в специальном окне сообщений (Message Box). Окно сообщений является диалогом, причем модальным: программа (либо даже операционная система) не будут продолжать работу до тех пор, пока пользователь не щелкнет по какой-либо кнопке, расположенной в окне диалога.
MsgBox(Текст_сооб., Признак, Текст_заг., Имя_файла_спр., Номер_разд.)
MsgBox Текст_сооб., Признак, Текст_заг., Имя_файла_спр., Номер_разд.
Слагаемое в аргумент Признак | Отображаемый набор кнопок |
---|---|
0 | Отображается только кнопка "ОК" |
1 | Отображаются кнопки "ОК" и "Отмена" (Cancel) |
2 | Отображаются кнопки "Прервать" (Abort), "Повторить" (Retry) и "Пропустить" (Ignore) |
3 | Отображаются кнопки "Да" (Yes), "Нет" (No) и "Отмена" (Cancel) |
4 | Отображаются кнопки "Да" (Yes) и "Нет" (No) |
5 | Отображаются кнопки "Повторить" (Retry) и "Отмена" (Cancel) |
Слагаемое в аргумент Признак | Кнопка, на которую первоначально направлен фокус |
---|---|
0 | Первая |
256 | Вторая |
512 | Третья |
768 | Четвертая |
Кнопка | OK | Cancel | Abort | Retry | Ignore | Yes | No |
---|---|---|---|---|---|---|---|
Значение | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
Private Sub Form_Load()
Dim s As String
Randomize
Drive1.Visible = False
Dir1.Visible = False
File1.Visible = False
lblPath.Caption = Dir1.Path
s = Dir1.Path
If InStr(s, "_PIC_WAV") <> 0 Then
Image1.Visible = True
li = li_o = Int(lsbRus.ListCount * Rnd)
lblWord.Caption = lsbRus.List(li)
Image1.Picture = LoadPicture(File1.Path + "\" + _
Mid(Str(lsbRus.ItemData(li)), 2) + ".jpg")
End If
End Sub
SELECT Cписок_полей FROM Cписок_таблиц [, Отношения_между_ними]
SELECT a.Author, a.Au_ID, b.Title, b.[Year Published],
b.ISBN, b.PubId, d.[Company Name], d.City
FROM Authors As a, Titles As b, [Title Author] As c, Publishers As d,
a INNER JOIN c ON a.Au_ID = c.Au_ID,
b INNER JOIN c ON b.ISBN = c.ISBN,
b INNER JOIN d ON b.PubId = d.PubId
a INNER JOIN b ON a.Au_ID = b.Au_ID
EnglWord |
RusWord |
Image |
Wave |
DOG |
Собака |
<ссылка на файл> |
<ссылка на файл> |
DOLPHIN |
Дельфин |
<ссылка на файл> |
<ссылка на файл> |
DONKEY |
Осел |
<ссылка на файл> |
<ссылка на файл> |
SELECT * FROM Subject ORDER BY EnglWord
Здесь "*" означает "все записи", а ORDER BY - сортировку (по умолчанию - в порядке возрастания, т.е. "по алфавиту").
У связанных элементов - OLE1, OLE2, txtRus, lblEngl установим для свойства DataSource значение
Dim li As Integer, ii_o As Integer, t As Integer, _
n As Integer, nf As Integer, rc As Integer
' rc - количество записей в БД
Public Sub NewSelect() 'Случайный выбор очередного предмета
li = Int(rc * Rnd)
If li = li_o Then
If li = rc - 1 Then
li = li - 1
Else
li = li + 1
End If
End If
Data1.Recordset.AbsolutePosition = li
li_o = li
End Sub
Private Sub CheckChoice() 'Проверка ответа обучаемого
n = n + 1
If lblEngl.Caption = dbcEngl.Text Then
OLE2.DoVerb
Else
Call OutFault(True)
OLE3.DoVerb
nf = nf + 1
End If
tmrDelay.Enabled = True
End Sub
Private Sub OutFault(boo As Boolean) 'Управление надписью
Dim j As Integer ' "Неверно!"
For j = 0 To 6
lblFault(j).Visible = boo
Next
End Sub
Отметим использование следующих новых программных элементов.
К ним относится упоминавшийся ранее объект RecordSet, к которому мы обращаемся через одноименное свойство элемента Data1. Свойство AbsolutePosition этого объекта возвращает или устанавливает номер текущей записи в нем (от 0 до rc-1, где rc - число записей в RecordSet). (Значение переменной rc, как мы увидим, устанавливается ранее в обработчике загрузки основной формы с помощью свойства RecordCount, возвращающего полное число записей в RecordSet. Причем для определения значения этого свойства, необходимо вначале "пролистать" все записи, перейдя к последней с помощью метода MoveLast).
Private Sub Form_Load() 'Инициализация набора записей
Data1.DatabaseName = App.Path & "/obuchalka.mdb"
Data1.Refresh
Data1.Recordset.MoveLast
rc = Data1.Recordset.RecordCount
Randomize
Call NewSelect
End Sub
После инициализации объекта RecordSet число записей в наборе определяется, как мы видим, с помощью метода MoveLast и свойства RecordCount этого объекта.
Private Sub dbcEngl_Click(Area As Integer) 'Клик слова-
Call CheckChoice 'перевода в списке
End Sub
Private Sub dbcEngl_KeyPress(KeyAscii As Integer) 'Ввод
If KeyAscii = 13 Then 'слова-первода в поле списка
Call CheckChoice
End If
End Sub
¤ Для двух новых кнопок - прерывания теста и вызова формы для корректировки таблицы БД - появились два новых обработчика:
Private Sub cmdAdd_Click() 'Изменение состава БД
Call cmdBreak_Click
frmEnter_DB.Show
End Sub
Private Sub cmdBreak_Click() 'Прерывание теста
cmdStart.Caption = "Запуск теста (60 сек)"
tmrDelay.Enabled = False
tmrSec.Enabled = False
Call OutFault(False)
tmrTest.Enabled = False
Call NewSelect
dbcEngl.SetFocus
End Sub
Использованный для вызова формы метод Show (Показать), во-первых, загружает форму, если она не была загружена, а во-вторых, делает ее видимой. Снова скрывает форму (но не выгружает ее, т.е. программный доступ к ней сохраняется) метод Hide (Скрыть).
Private Sub cmdStart_Click() 'Запуск теста
t = 0
n = 0
nf = 0
frmEnter_DB.Hide
Call NewSelect
dbcEngl.SetFocus
tmrSec.Enabled = True
tmrTest.Enabled = True
End Sub
Private Sub tmrDelay_Timer()
Call NewSelect
tmrDelay.Enabled = False
Call OutFault(False)
End Sub
Private Sub tmrSec_Timer()
t = t + 1
cmdStart.Caption = t & " сек"
End Sub
Private Sub tmrTest_Timer()
Dim b As Integer
cmdStart.Caption = "Запуск теста (60 сек)"
tmrDelay.Enabled = False
tmrSec.Enabled = False
Call OutFault(False)
Select Case n - nf
Case Is > 8
If nf = 0 Then
b = 5
Else
b = 4
End If
If nf = 0 Then
b = 4
Else
b = 3
End If
Case 3 To 5
If nf = 0 Then
b = 3
Else
b = 2
End If
Case Else
b = 2
End Select
MsgBox "Дано " & n & " ответов; число Ваших ошибок: " _
& nf & Chr(13) & "Отметка: " & b, vbInformation
tmrTest.Enabled = False
Call NewSelect
End Sub
¤ Последнее что мы сделаем, это заменим в обработчике события Click для кнопки Close формы frmEnter_DB вызов метода Unload Me (при его выполнении курсор "заклинивает" на форме песочных часов), выгружающего эту форму по окончании работы с ней, на следующий код:
Hide
frmObuchalka.dbcEngl.ReFill 'обновления содержимого связанного
'списка и его перерисовка после корректировки БД
frmObuchalka.dbcEngl.SetFocus
Кроме того, чтобы фокус гарантированно передавался после загрузки формы frmObuchalka сразу на поле ввода комбинированного списка, создадим обработчик:
Private Sub txtRus_GotFocus()
dbcEngl.SetFocus
End Sub
=•=•=•=•=•=•=•=•=•=•=•=•=•=•=•=•=•=•=•=•=•=•=•=•=•=•=•=•
Dim dbName As Database, recName As Recordset
Set dbName = OpenDatabase("Путь к файлу БД")
Set recName = dbName.OpenRecordset("Имя таблицы, " _
"запроса, либо инструкция SELECT")
Созданный таким образом набор можно, далее, передать для управления и отображения в связанных элементах элементу Data (с именем datName):
Set datName.Recordset = recName
Преимущество такого подхода очевидны: мы можем формировать передаваемый элементу Data набор записей в фазе выполнения приложения по тому или иному запросу пользователя.
Person.FindFirst "PhoneNumber = '" + gsOldNumber + "'"
'Параметром метода FindFirst является строковое выражение,
'изображающее операцию сравнения. Обратите внимание на
'ее специфический синтаксис
If Person.NoMatch Then
MsgBox "Запись отсутствует"
Else
Person.Edit
Person("PhoneNumber") = gsNewNumber
Person.Update
End If
Помимо модификации БД объекты DAO позволяют создавать новые БД в процессе работы приложения (а также менять структуру БД). Это бывает нужно при коммерческой поставке приложения, когда громоздкую БД,с которой работает приложение, проще создать "по месту", чем включать в поставку.
Dim dbName As Database, tblName As TableDef, fldF1 As Field
Set dbName = WorkSpace(0).CreateDatabase("Путь_к_файлу_БД", _
Порядок)
Set tblName1 = dbName.CreateTableDef("Таблица_1")
Set fldF1 = tblName1.CreateField()
fldF1.Name = "Поле_1"
fldF1.Type = Тип_поля 'Задается именованной константой
fldF1.Size = Размер_поля '(Существует не для всякого типа поля)
tblName1.Fields.Append fldF1 'Добавление описанного поля
'в таблицу методом Append
Если с типами и размерами полей мы уже познакомились при создании БД obuchalka.mdb, то параметр Порядок метода CreateDatabase нам еще не знаком. Он определяет (заданием именованной константы) язык (кодовую страницу), по алфавиту которого будут браться символы при сравнении строк. Значение dbLangGeneral задается для использования англо-американской кодовой страницы; для сравнения в соответствии с русским алфавитом используется константа dbLangCyrillic.
Word.Documents.Add
или, если коллекция Documents единственна в списке глобальных членов при выбранном пункте
Documents.Add
=•=•=•=•=•=•=•=•=•=•=•=•=•=•=•=•=•=•=•=•=•=•=•=•=•=•=•=•
Dim objVar As Object
Во второй форме объявляется объектная переменная определенного объектного класса, которая может ссылаться только на объекты того же типа (класса), например:
Dim objVar As Word.Selection
Такой вариант объявления является предпочтительным, так как, во-первых, компилятор обнаружит связь переменной с классом еще во время написания кода приложения-клиента и обеспечит программисту сервис List Members (список членов объекта в ответ на ввод навигационной точки после имени переменной), а во-вторых, - компилятор использует в этом случае раннее связывание клиента с объектом (во время компиляции, а не выполнения, как при позднем), что предпочтительнее для отладки и по быстродействию.
Set objVar = CreateObject(“Word.Selection”)
Второй вариант использует ключевое слово New:
Set objVar = New Word.Selection
Таким же образом можно создавать и несерверные объекты.
Set objVar = GetObject(“”, "Word.Selection")
(Если бы первый аргумент был опущен, данная инструкция устанавливала бы ссылку на уже существующий объект выполняемого приложения Word, либо, при отсутствии последнего, генерировала бы ошибку.)
Отметим, что если тип сервера OLE-автоматизации внепроцессный, как в случае приложения Word, то для создания в клиенте его объектов он должен быть открыт (запущен на выполнение). Сделать это можно путем создании его объекта Application.
Private Sub cmdWord_Click()
Dim objWord As Object 'Объявляем объект
On Error Resume Next '- Обратите внимание на эту инструкцию:
'"В случае ошибки (On Error) продолжать (Resume) со
' следующей (Next) инструкции"
'Открываем объект, установив ссылку на активный объект Word:
Set objWord = GetObject(, "Word.Application")
'Если такого объекта не оказалось,
If objWord Is Nothing Then
'то открываем его, запустив Word на выполнение:
Set objWord = New Word.Application
'(То же можно сделать, например, так:
'Set objWord = CreateObject("Word.Application") )
'Если и после этого ссылка не удалась,
If objWord Is Nothing Then
'то распишемся в своем бессилии:
MsgBox "Создать объект не удается!"
End If
End If
objWord.Visible = True ' - Иначе окна приложения не увидим!
'Откроем, пожалуй, наш документ:
objWord.Documents.Open "C:\Мои документы\MyDoc.doc"
'Уничтожаем объект (“Знак хорошего вкуса и традиций пример”):
Set objWord = Nothing
End Sub
Для завершения работы с Word 97 в клиенте необходимо использовать метод Quit объекта Application.
Option Explicit 'Контроль за явной объявленностью
'переменных
Private objElem As Stack
¤ Создать свойство можно двумя способами:
Public Child As Stack
Для задания свойства Value вызовем командой Add Procedure пункта Tools главного меню соответствующий диалог и установим в нем имя свойства “Value”, а также опции Property и Public:
Public Property Get Value() As Variant
End Property
Public Property Let Value(ByVal vNewValue As Variant)
End Property
Конечно, сами эти заготовки не способны хранить значение свойства. Для этого в декларациях объявляют специальную переменную уровня модуля:
Private mvar_Value As Variant
После этого в процедуру Property Get Value помещается следующая инструкция, обеспечивающая считывание из приложения значения хранимого свойства:
Value = mvar_Value
(Заметим, что если бы мы создавали свойство только для чтения, то заготовку Property Let Value надо было бы удалить, а вместо специальной переменной использовать для присвоения значения свойству константу, представляющую это значение).
Public Property Get Value() As Variant
Value = mvar_Value
End Property
Public Property Let Value(ByVal vNewValue As Variant)
mvar_Value = vNewValue
End Property
¤ Говоря о создании событий класса, важно подчеркнуть различие между событиями возникающими (внутри класса) и событиями возбуждаемыми (в приложении, где создан объект класса). Когда говорят о создании событий класса имеют в виду именно возбуждаемые события.
Public Event Initilize()
Public Event Terminate()
Public Event Void()
После этого, в заготовки обработчиков событий Initilize и Terminate (событий, получаемых модулем класса от операционной системы) помещаем инструкции RaiseEvent Initilize и RaiseEvent Terminate соответственно. Что же касается инструкции RaiseEvent Void, то ее мы поместим в тело инструкции If, проверяющей внутри процедуры Pop наличие у текущего объекта ссылки на его сыновний (если таковой нет, то событие вызывается, а процедура Pop заканчивает работу по инструкции Exit - “выход”).
Option Explicit
Private objElem As Stack
Public Child As Stack
Private mvar_Value As Variant
Public Event Initilize()
Public Event Terminate()
Public Event Void()
Public Property Get Value() As Variant
Value = mvar_Value
End Property
Public Property Let Value(ByVal vNewValue As Variant)
mvar_Value = vNewValue
End Property
Public Sub Push()
Set objElem = New Stack 'Создаем новый объект со ссылкой objElem
Set objElem.Child = Me.Child 'Ссылаемся сыном нового объекта
'на сына текущего объекта
objElem.Value = Me.Value 'Копируем данное из текущего-в новый
Set Me.Child = objElem 'Ссылаемся сыном текущего на новый
End Sub
Public Sub Pop()
If Me.Child Is Nothing Then
RaiseEvent Void
Exit Sub
End If
Set objElem = Me.Child 'Сохраняем ссылку на сына текущего объ.
Set Me.Child = Nothing 'Уничтожаем сына текущего объекта
Set Me.Child = objElem.Child 'На место сына подставляем внука
Me.Value = objElem.Value 'В текущий копируем данное, бывшее в
Set objElem = Nothing 'уничтоженном сына и уничтожаем ссылку
End Sub 'на этого сына
Private Sub Class_Initialize()
RaiseEvent Initilize
End Sub
Private Sub Class_Terminate()
RaiseEvent Terminate
End Sub
В коде методов обратите внимание на два новые конструкции.
Dim WithEvents Elem As Stack
Dim i As Integer, j As Integer 'i - натуральный ряд, заносимый в стек
'j - флаг, устанавливаемый при чтении из пустого стека
Private Sub cmdClass_Click()
Set Elem = New Stack
Elem.Value = -1 'При пустом стеке объект хранит -1
cmdClass.Enabled = False
End Sub
Private Sub cmdPop_Click()
Elem.Pop
If j = 1 Then
MsgBox Str(Elem.Value)
i = i - 1
End If
End Sub
Private Sub cmdPush_Click()
If j = 0 Then
j = 1
End If
i = i + 1
Elem.Push 'При каждом вызове в стек заносятся числа
Elem.Value = i
End Sub
Private Sub Elem_Void()
MsgBox "Стек пуст"
j = 0
End Sub
При первом “проталкивании” в стек заносится содержащаяся в объекте -1, при последующих - числа 1, 2, 3... и так далее. В любой момент эти числа можно извлекать из стека в обратном порядке, что контролируется выдачей их на печать.
Implements ИмяАбстрактногоКласса
Private Sub ИмяАбстрактногоКласса_ИмяЧленаАбстрактногоКласса
'Код метода для абстрактного класса Szivotnye
Public Sub Sound(ByVal Tone As Double, _
ByVal Duration As Double, ByVal Sort As Integer)
'Здесь какой-то код, представляющий общую реализацию метода
End Sub
'Один из классов сервера, использующий абстрактный класс Szivotnye:
Implements Szivotnye 'Объявляем класс Szivotnye интерфейсом
Private objSziv As Szivotnye 'Объявляем переменную класса интерфейса
'Обработчик инициализации объекта класса сервера:
Private Sub Class_Initilise()
Set objSziv = New Szivotnye 'Создание объекта интерфейса
End Sub
'Переопределение метода:
Private Sub Szivotnye_Sound(ByVal Tone As Double, _
ByVal Duration As Double, ByVal Sort As Integer)
'Сначала - повторное использование кода общей реализации:
Call objSziv.Sound(Tone, Duration, Sort)
'А потом - можно добавить и дополнительный код
End Sub
Важно отметить, что представленное использование интерфейса для реализации полиморфизма основано не на позднем, а на раннем, то есть на этапе компиляции, связывании: обнаружив в классе инструкцию Implements, компилятор, с помощью библиотеки типов интерфейса и стандартного COM-интерфейса IDispatch (подробности мы опускаем), обеспечивает переход на используемые сервером члены интерфейса. Это дает существенный выигрыш по времени по сравнению с поздним связыванием.
Private Sub UserControl_Resize()
With lblTime
.Font.Size = UserControl.ScaleHeight * 41 / 79.8
.Left = (UserControl.ScaleWidth - .Width) / 2
.Top = (UserControl.ScaleHeight - .Height) / 2
End With
End Sub
Подобный код (он написан, конечно, уже после того, как мы “поиграли” внешним видом нашего ПЭУ с расположенным на нем ярлыком-циферблатом) почти всегда необходим, так как он обеспечивает сохранение пропорций визуальной составляющей ПЭУ при его размещении в приложении-клиенте. Обратим внимание, что у объекта-контейнера UserControl (как и в том случае, если бы вместо него использовался его праобраз - экранная форма) используются размерные свойства с присоединением “Scale”, что указывает на действительность представляемых ими размеров именно в единицах внутренней области контейнера.
Private Sub tmrSec_Timer()
Static strs As String, tmr As Date
tmr = Time
strs = Format(tmr, "hh:nn:ss")
lblTime.Caption = strs
End Sub
Здесь текущее время, возвращаемое стандартной функцией Time при каждом событии Timer таймера, преобразуется из “американского” 12-часового формата в строку 24-часового формата стандартной функцией Format (см. в Приложении I “Преобразование типов данных”).
Сохраним изменения в проекте User_Clock и закроем его, после чего перейдем на форму тестового проекта. Наш ПЭУ предстанет на ней примерно в таком виде:
Option Explicit
Event Change()
Event Timer()
Public Property Get Enabled() As Boolean
Enabled = UserControl.Enabled
End Property
Public Property Let Enabled( _
ByVal New_Enabled As Boolean)
UserControl.Enabled() = New_Enabled
PropertyChanged "Enabled"
End Property
Public Property Get TimeCaption() As String
TimeCaption = lblTime.Caption
End Property
Public Property Let TimeCaption( _
ByVal New_TimeCaption As String)
lblTime.Caption() = New_TimeCaption
PropertyChanged "TimeCaption"
End Property
Public Property Get Interval() As String
Interval = txtInt.Text
End Property
Public Property Let Interval( _
ByVal New_Interval As String)
txtInt.Text() = New_Interval
PropertyChanged "Interval"
End Property
Public Property Get Font() As Font
Set Font = lblTime.Font
End Property
Public Property Set Font(ByVal New_Font As Font)
Set lblTime.Font = New_Font
PropertyChanged "Font"
End Property
Public Property Get BackColor() As OLE_COLOR
BackColor = lblTime.BackColor
End Property
Public Property Let BackColor( _
ByVal New_BackColor As OLE_COLOR)
lblTime.BackColor() = New_BackColor
PropertyChanged "BackColor"
End Property
Public Property Get ForeColor() As OLE_COLOR
ForeColor = lblTime.ForeColor
End Property
Public Property Let ForeColor( _
ByVal New_ForeColor As OLE_COLOR)
lblTime.ForeColor() = New_ForeColor
PropertyChanged "ForeColor"
End Property
Public Property Get TypeInterval() As Boolean
TypeInterval = optType(0).Value
End Property
Public Property Let TypeInterval(ByVal New_TypeInterval As Boolean)
optType(0).Value() = New_TypeInterval
PropertyChanged "TypeInterval"
End Property
Public Function Start() As Variant
End Function
Public Function Stopp() as Variant
End Function
Public Function Check() As Variant
End Function
Private Sub UserControl_ReadProperties( _
PropBag As PropertyBag)
UserControl.Enabled = PropBag.ReadProperty( _
"Enabled", True)
lblTime.Caption = PropBag.ReadProperty( _
"TimeCaption", "00:00:00")
txtInt.Text = PropBag.ReadProperty( _
"Interval", "00:00:00")
optType(0).Value = PropBag.ReadProperty( _
"TypeInterval", True)
Set Font = PropBag.ReadProperty( _
"Font", Ambient.Font)
lblTime.BackColor = PropBag.ReadProperty( _
"BackColor", &HC0C0C0)
lblTime.ForeColor = PropBag.ReadProperty( _
"ForeColor", &H8000&)
End Sub
Private Sub UserControl_WriteProperties( _
PropBag As PropertyBag)
Call PropBag.WriteProperty( _
"Enabled", UserControl.Enabled, True)
Call PropBag.WriteProperty("TimeCaption", _
lblTime.Caption, "00:00:00")
Call PropBag.WriteProperty( _
"Interval", txtInt.Text, "00:00:00")
Call PropBag.WriteProperty( _
"TypeInterval", optType(0).Value, True)
Call PropBag.WriteProperty( _
"Font", Font, Ambient.Font)
Call PropBag.WriteProperty( _
"BackColor", lblTime.BackColor, &HC0C0C0)
Call PropBag.WriteProperty( _
"ForeColor", lblTime.ForeColor, &H8000&)
End Sub
Sub About1()
frmAbout.Show
End Sub
• В диалоге Procedure Attributes (Tools_Procedure Attributes..._Advanced>>) выберем в списке Procedure ID пункт AboutBox вместо None.
После этого для размещенного в форме ПЭУ Clock в окне свойств появится строка свойства About.
Форму About мы можем, далее, редактировать как обычную форму, изменяя компоновку составляющих элементов, в том числе положение и надпись кнопки cmdSysInfo, а также удалив ярлыки lblVersion и lblTitle. Посредством окна свойств введем требуемые строковые данные (надпись на форме, название ПЭУ и его описание), а также укажем файлы с картинками для свойств элементов PicIcon.Picture и frmAbout.Icon:
Dim i As Integer, f As Integer
Dim t_txtInt As Date
Dim sh As Single, sw As Single
'i - счетчик переходов между функциями Часы/Будильник
'f -флаг задания начала отсчета в функции Будильника
'sh, sw - хранители размеров ПЭУ на форме клиента для их
'восстановления после работы в режиме установки
't_txtInt - величина заданного интервала для Будильника
Const C_height = 1596 'Проектная высота UserControl
Const C_width = 3324 'Проектная ширина UserControl
Const C_koef = 41 / 79.8 'Коэффициент отношения высот
'шрифта отображения времени в ПЭУ Clock и самого ПЭУ
Const С_interv = 100 'интервал таймера tmrSec
Заметим, что в обработчик UserControl_Resize(), который мы уже создали, необходимо внести изменение, используя объявленную константу C_koef. “Магических чисел” (смысл которых понятен только разработчику в период разработки) в программе быть не должно!
Private Sub UserControl_DblClick()
'Запоминаем размер ПЭУ
sh = UserControl.Height
sw = UserControl.Width
'Устанавливаем проектный размер “изнанки” ПЭУ
UserControl.Height = C_height
UserControl.Width = C_width
SSTab1.Visible = True
txtInt.Visible = True
cmdStart.Visible = True
cmdStop.Visible = True
cmdCheck.Visible = True
lblTime_1.Visible = True
Label3.Visible = True
Label4.Visible = True
optType(0).Visible = True
optType(1).Visible = True
End Sub
Private Sub SSTab1_DblClick()
SSTab1.Visible = False
'Возврат к исходному размеру ПЭУ
UserControl.Height = sh
UserControl.Width = sw
End Sub
Обратим внимание, что установка значения False свойству Visible контейнера SSTab распространяется и на видимость составляющих элементов управления, а установка значения True - не распространяется.
Private Sub cmdCheck_Click()
If i Mod 2 = 0 Then 'Функция будильника
cmdCheck.Caption = "В режим часов"
cmdStart.Enabled = True
optType(0).Enabled = True
optType(1).Enabled = True
f = 0
If optType(0).Value = True Then
tmrSec.Interval = 0
lblTime.Caption = "00:00:00"
lblTime_1.Caption = "00:00:00"
End If
Else 'Функция часов
cmdCheck.Caption = "В режим будильника"
cmdStart.Enabled = False
optType(0).Enabled = False
optType(1).Enabled = False
tmrSec.Interval = С_interv
End If
i = i + 1
End Sub
Private Sub cmdStart_Click()
cmdStart.Enabled = False
cmdCheck.Enabled = False
cmdStop.Enabled = True
t_txtInt = CDate(txtInt.Text)
tmrSec.Interval = С_interv 'Включаем таймер
End Sub
Private Sub cmdStop_Click()
cmdStart.Enabled = True
cmdCheck.Enabled = True
cmdStop.Enabled = False
End Sub
Public Function Start() As Variant
Call cmdStart_Click
End Function
Public Function Check() As Variant
Call cmdCheck_Click
End Function
Public Function Stopp() As Variant
Call cmdStop_Click
End Function
¤ В функции будильника становятся доступны (для изменения формы задания интервала) радиокнопки optType(0)-(1). При задании интервала граничным значением (optType(1).Value= True) таймер работает, и ПЭУ отображает системное время.
Private Sub optType_Click(Index As Integer)
optType(Index).Value = True
optType(1 - Index).Value = False
If optType(1).Value = True Then
tmrSec.Interval = С_interv 'Включаем таймер
Else
tmrSec.Interval = 0
lblTime.Caption = "00:00:00"
lblTime_1.Caption = "00:00:00"
End If
End Sub
Private Sub tmrSec_Timer()
Static strs As String, tmr As Date, tmr0 As Date, tmrt As Date
tmr = Time
If cmdStop.Enabled = True Then
If optType(0).Value = True Then
If f = 0 Then
tmr0 = tmr
f = 1
Else
tmrt = tmr - tmr0
lblTime.Caption = Format(tmrt, "hh:nn:ss")
lblTime_1.Caption = lblTime.Caption
If tmrt >= t_txtInt Then 'Событие Timer произошло
'при интервале, заданном длительностью
f = 0
cmdStart.Enabled = True
cmdCheck.Enabled = True
cmdStop.Enabled = False
tmrSec.Interval = 0
RaiseEvent Timer
End If
End If
Else
lblTime.Caption = Format(tmr, "hh:nn:ss")
lblTime_1.Caption = lblTime.Caption
If tmr >= t_txtInt Then 'Событие Timer произошло
'при интервале, заданном границей
cmdStart.Enabled = True
cmdCheck.Enabled = True
cmdStop.Enabled = False
RaiseEvent Timer
End If
End If
Else
If f = 1 Then 'Когда приостанавливается интервальный секундомер
tmr0 = tmr - tmrt 'кнопкой "Стоп", системные часы продолжают
End If 'идти, и вслед за ними должна смещаться
'начальная точка отсчета времени
If optType(1).Value = True Then
lblTime.Caption = Format(tmr, "hh:nn:ss")
lblTime_1.Caption = lblTime.Caption
End If
End If
If optType(0).Enabled = False And optType(1).Enabled _
= False Then
lblTime.Caption = Format(tmr, "hh:nn:ss")
lblTime_1.Caption = lblTime.Caption
End If
End Sub
Несколько десятков строк самостоятельно написанного кода - и мы реализовали довольно-таки разветвленную логику работы нашего ПЭУ. Он готов к использованию и распространению!
Option Explicit
Dim i As Integer, j As Integer
Dim a(1, 99) As Integer 'В этом массиве хранятся 2 "карты":
'простановки крестиков и ноликов; по этим картам проверяется
'условие победы тех или других
DefInt d-z 'Целый тип назначается всем переменным модуля,
'начинающимся с букв из заданного диапазона
Private Sub chkTime_Click()
Static c As Integer
If c Mod 2 = 0 Then
chkTime.Value = 1
Else
chkTime.Value = 0
End If
c = c + 1
End Sub
Private Sub clcSec_Timer(Index As Integer)
If chkTime.Value = 0 Then
If Index = 0 Then
lblTablo.Caption = "Победа 'Ноликов'!"
Else
lblTablo.Caption = "Победа'Крестиков'!"
End If
Call cmdFin_Click
End If
End Sub
Private Sub cmdField_Click(Index As Integer)
i = i + 1
j = i Mod 2
If cmdStart.Enabled = False And cmdFin.Enabled = True Then
If cmdField(Index).Caption = "" Then
cmdField(Index).Caption = Mid("OX", j + 1, 1) 'Изображением
'нуля служит (для красоты) буква О
If Proverka(Index, j, a()) = 1 Then
Exit Sub
End If
clcSec(1 - j).Stopp
clcSec(j).Start
If j = 0 Then
lblTablo.Caption = "Ход 'Крестиков'"
Else
lblTablo.Caption = "Ход 'Ноликов'"
End If
End If
End If
End Sub
Private Sub cmdField_GotFocus(Index As Integer)
If cmdSet(0).Enabled = True Then
cmdSet(0).SetFocus
End If
End Sub
Private Sub cmdFin_Click()
Dim x, y As Integer
clcSec(j).Stopp
clcSec(1 - j).Stopp
cmdStart.Enabled = True
cmdFin.Enabled = False
For x = 0 To 1
For y = 0 To 99
a(x, y) = 0
Next
Next
End Sub
Private Sub cmdSet_Click(Index As Integer)
lblTablo.Caption = ""
clcSec(Index).Check
clcSec(Index).Visible = True
txtSet(Index).Visible = True
cmdSet(Index).Enabled = False
If cmdSet(0).Enabled = False And cmdSet(1).Enabled = False Then
cmdStart.Enabled = True
End If
End Sub
Private Sub cmdStart_Click()
Dim x, y
If (txtSet(0).Text = "00:00:00" Or txtSet(1).Text = "00:00:00") _
And chkTime.Value = 0 Then
Exit Sub
End If
i = 0
clcSec(j).Check
clcSec(1 - j).Check
clcSec(j).Check
clcSec(1 - j).Check
clcSec(j).Visible = True
clcSec(1 - j).Visible = True
cmdSet(j).Enabled = False
cmdSet(1 - j).Enabled = False
For x = 0 To 99
cmdField(x).Caption = ""
Next
For x = 0 To 1
For y = 0 To 99
a(x, y) = 0
Next
Next
clcSec(0).Start
cmdStart.Enabled = False
cmdFin.Enabled = True
lblTablo.Caption = "Ход 'Крестиков'"
End Sub
Private Sub Form_Load()
lblTablo.Caption = "Добро пожаловать!"
End Sub
Private Sub txtSet_Change(Index As Integer)
clcSec(Index).Interval = txtSet(Index).Text
End Sub
Private Function Proverka(ind As Integer, ind0 As Integer, _
a() As Integer) As Integer
Dim x, y, z, zz, u, d, dx, mx, ind1, k, s
'Здесь реализована проверка чьей-либо победы,
'но понять КАК это сделано труднее, чем написать эту
'функцию самому
a(ind0, ind) = 1 'Отображается очередной знак на карте
For z = 0 To 1 'Сначала проверяем горизонтали и вертикали
For x = 0 To 9
s = 0
k = 0
For y = 0 To 9
If z = 0 Then
ind1 = x + 10 * y
Else
ind1 = y + 10 * x
End If
s = s + a(ind0, ind1)
k = k + 1
If s = k Then
If s = 5 Then
If ind0 = 0 Then
lblTablo.Caption = "Победа 'Ноликов'!"
Else
lblTablo.Caption = "Победа'Крестиков'!"
End If
Call cmdFin_Click
Proverka = 1
Exit Function
End If
Else
s = 0
k = 0
End If
Next
Next
Next
For u = 0 To 1 'Потом проверяем диагонали
For z = 0 To 5
If u = 0 Then
d = 55 - 11 * z
zz = z + 4
Else
d = 45 - 9 * z
zz = 5 - z
End If
If d = 0 Then
mx = 0
Else
mx = 1
End If
For x = 0 To mx
dx = d * x
s = 0
k = 0
For y = 0 To z + 4
If u = 0 Then
ind1 = zz + 9 * y + dx
Else
ind1 = zz + 11 * y + dx
End If
s = s + a(ind0, ind1)
k = k + 1
If s = k Then
If s = 5 Then
If ind0 = 0 Then
lblTablo.Caption = "Победа 'Ноликов'!"
Else
lblTablo.Caption = "Победа'Крестиков'!"
End If
Call cmdFin_Click
Proverka = 1
Exit Function
End If
Else
s = 0
k = 0
End If
Next
Next
Next
Next
Proverka = 0
End Function
Option Explicit
Dim i As Integer
Private Sub cmdStart_Click()
On Error Resume Next 'При установке связи часты внепрограммные сбои
If i Mod 2 = 0 Then
cmdStart.Caption = "CTOП"
cmdStart.Enabled = False
brwWB.Navigate "http://www.mkids.ru/"
Else
cmdStart.Caption = "Вход в детскую сеть"
cmdStart.Enabled = True
brwWB.Stop
End If
i = i + 1
End Sub
¤ Нажатия на кнопки "Назад" и "Вперед" вызывают (при доступности соответствующей кнопки) методы GoBack и GoForward соответственно элемента-броузера:
Private Sub cmdBF_Click(Index As Integer)
If Index = 0 Then
brwWB.GoBack
Else
brwWB.GoForward
End If
End Sub
¤ Каждый вызов методов GoBack или GoForward вызывает событие CommandStateChange. Соответствующий обработчик отслеживает, какая команда вызывалась, и управляет доступностью кнопок "Назад" и "Вперед":
Private Sub brwWB_CommandStateChange(ByVal Command As Long, _
ByVal Enable As Boolean)
Select Case Command
Case CSC_NAVIGATEBACK 'Внутренняя константа WebBrowser
cmdBF(0).Enabled = Enable
Case CSC_NAVIGATEFORWARD 'Внутренняя константа WebBrowser
cmdBF(1).Enabled = Enable
End Select
End Sub
¤ Обработка начала и окончания загрузки Web-страницы:
Private Sub brwWB_DownloadBegin()
cmdStart.Enabled = True
End Sub
Private Sub brwWB_DownloadComplete()
cmdStart.Enabled = False
lblURL.Caption = brwWB.LocationName
End Sub
В начале загрузки Web-страницы кнопка "Стоп" становится доступной для прекращения загрузки; в конце загрузки доступность с нее снимается и выводится заголовок страницы в ярлык lblURL.
Private Sub Form_Resize()
If Me.WindowState <> vbMinimized Then
brwWB.Height = ScaleHeight - 2 * lblURL.Height - lblURL.Top
brwWB.Width = ScaleWidth - 1.5 * cmdStart.Width - lblURL.Left
lblURL.Width = brwWB.Width
cmdStart.Left = lblURL.Left + lblURL.Width + 0.25 * cmdStart.Width
cmdBF(0).Left = cmdStart.Left
cmdBF(1).Left = cmdStart.Left
End If
End Sub
=•=•=•=•=•=•=•=•=•=•=•=•=•=•=•=•=•=•=•=•=•=•=•=•=•=•=•=•
Option Explicit
Dim strURL(50) As String
Private Sub cboOthers_Click()
On Error GoTo Er 'Если возникнет ошибка в процессе соединения, то
'то процедура заканчивает работу без последствий
UserDocument.Hyperlink.NavigateTostrURL(cboOthers.ItemData(cboOthers.ListIndex))
On Error GoTo 0 'Отключаем описанную обработку ошибки
Er:
End Sub
Private Sub UserDocument_Initialize()
strURL(0) = "http://www.uic.nnov.ru/~edu/school_13.htm"
strURL(1) = "http://www.cacedu.unibel.by/partner/sch54"
strURL(2) = "http://into.nit.spb.su/eng/school/sc56/main.htm"
strURL(3) = "http://www.pmg17vstu.vinnica.ua"
'strURL(3) = "http://127.0.0.1/Game.htm" 'Используем для отладки
End Sub
Произведем отладку созданного документа ActiveX таким же образом, как и предыдущего, преобразованного нами из проекта Game.vbp. Затем, описанным ранее образом создадим на локальном сервере программу его установки для распространения по гиперсети. Теперь мы будем иметь, по-существу, Web-страницу с гиперссылками, созданную средствами VB5:• Композиция (а): <Процедура 1> <Процедура 2> • Ветвление (б): если <условие> <Процедура 1> иначе <Процедура 2> • Цикл I (в): пока <условие> делать <Процедура> • Цикл II (г): делать <Процедура> пока <условие>
<Процедура 2> пуста:
если <условие>
<Процедура>
Dim strFamily As String, mintLength As Integer
'Объявлены переменные строкового и целого типов
Те же самые типы имели бы эти переменные и без явного объявления при добавлении к их именам соответствующих окончаний: strFamily$ и mintLength% (эти окончания можно добавлять и к числовым константам - для явного указания формата их хранения). Не используйте в одной процедуре имена переменных, различающиеся только окончанием, в Visual Basic это запрещено!
Проверим: 47 = 00000000 00101111 Инвертируем: 11111111 11010000 Добавляем 1: 11111111 11010001 = -47 Складываем с 47: 00000000 00101111 00000000 00000000
#17:04:23# 'Время суток
#January 27, 1993# ' Дата
#11/30/1998#
#3-6-93 13:20#
#March 27, 1993 1:20am#
#Apr-2-93#
#4 April 1993#
Данное типа Date (константа или переменная) хранится в памяти так, как хранилось бы числовое значение типа Double, у которого при записи его "с фиксированной точкой" целая часть давала бы число дней, на которое дата в данном типа Date отличается от 1 января 1900 года (более ранняя - отрицательна), а дробная - долю от полных суток (24 часа), содержащегося в данном типа Date времени суток (0 - полночь; 0.5 - полдень).
Dim Arr(20) As String 'Массив размером в 21 строковую величину
Dim Koef(3 To 43) As Double 'Массив в 41 величину типа Double
Dim Point() As Long 'Динамический массив длинных целых
Dim Obj(20) As String, Obj1(20) As String 'Два массива типа String
Dim Obj(20), Obj1(20) As String 'Первый массив типа Variant (по
'умолчанию), второй - String
Если при объявлении одномерного массива на месте индекса (в круглых скобках после имени массива) стоит константа (возможно константное выражение), то ее значение определяет верхнюю границу массива; нижняя граница при этом по умолчанию равна 0. Изменить значение нижней границы массивов по умолчанию в пределах текущего модуля можно предварительным включением в код модуля инструкции Option Base 1. Можно, однако, задать обе границы измерения явно, как это было сделано во втором примере, с использованием ключевого слова To между заданными константами нижней и верхней границами. Таким образом, при объявлении массива на месте индекса задается диапазон его значений.
Dim Tab(20, 30) As Integer 'Массив размером в 21*31 целую величину
Dim K_01(14, -3 To 43, 2) As Byte 'Массив размером в 15*47*3 байт
Заметим следующее.
Dim var As Variant, arrDate(1000) As Date
var=arrDate()
После этого переменная var, "содержащая" массив arrDate, будет занимать весь объем, выделенный массиву (8*1001+24), и еще 16 байт, из которых 4 байта содержат ссылку на массив: адрес байта, с которого начинается область памяти, занимаемая массивом. То есть никакой пересылке элементов массива при присваивании его переменной типа Variant не производится. Ссылочный механизм используется и при присваивании переменной типа Variant строковых и объектных значений (присваивание значения типа Object делается с использованием ключевого слова Set). Это позволяет эффективно сортировать размещаемые в строках, объектах или массивах списки данных больших объемов, так как при этом реально переприсваиваются только адресующие эти списки 4-байтовые значения.
Lbound(Имя_Массива [, Номер_измерения]) Ubound(Имя_Массива [, Номер_измерения])
Array([Список_аргументов])
Dim arrWeek, newDay
arrWeek = Array("Пн", "Вт", "Ср", "Чт", "Пт", "Сб", "Вс")
newDay = arrWeek(2) 'присвоение значения "Ср" переменной newDay
Если список аргументов пуст, создается массив нулевой длины.
Список_аргументов представляет разделенный запятыми список значений, присваиваемых элементам массива, содержащегося внутри значения типа Variant. Если аргументы не указываются, создается массив нулевой длины.
Dim Y As String
Y = "7"
Print "6" + Y, "6" & Y 'Будет напечатано: 67 67
Print 6 + Y, 6 & Y 'Будет напечатано: 13 67
Когда другие числовые данные конвертируются в тип Date, целая часть значения представляет информацию о дате, в то время как дробная часть время. Полночь интерпретируется как 0, полдень - как 0.5. Отрицательные целые представляют даты ранее 30 декабря 1899 года. Чтобы определить, может ли аргумент дата быть преобразована к типу даты или времени, следует использовать функцию IsDate. При преобразовании числа в дату переводится целая часть числа. Любая дробная часть числа преобразуется во время суток, отсчитываемое от полуночи.
Для явного преобразования строки цифр в число используется функция Val; явное обратное преобразование (в тип Variant) осуществляет функция Str (вместо которой более гибкое использование допускает функция Format, приведенная ниже). Обе эти функции не допускают иных десятичных разделителей, кроме точки.
Dim MyTime As Date, MyDate As Date, MyStr As String
MyTime = #5:04:23 PM# 'Краткий формат даты
MyDate = #1/27/98# 'Краткий формат времени
MyStr = Format(MyTime, "h:m:s") 'Возвращает "17:4:23"
MyStr = Format(MyTime, "hh:mm:ss AMPM") 'Возвращает "05:04:23"
MyStr = Format(MyDate, "dddd, mmmm d yyyy") ' Возвращает
'"Среда, Январь 27 1993"
'Если формат не указан, возвращается строка
MyStr = Format(23) 'Возвращает "23"
'Специальные форматы
MyStr = Format(5459.4, "##,##0.00") 'Возвращает "5 459.40"
MyStr = Format(334.9, "###0.00") 'Возвращает"334.90"
MyStr = Format(5, "0.00%") 'Возвращает "500.00%"
MyStr = Format("ПРИВЕТ", "<") 'Возвращает "привет"
MyStr = Format("Вот он какой", ">") 'Возвращает "ВОТ ОН КАКОЙ"
n - Integer c - Currency d - Double b - Boolean y - Byte l - Long g - Single t - Date o - Object s - String v - Variant e - Enum u - тип, определяемый пользователем
Оператор Синтаксис Результат + операнд1+операнд2 Сумма операндов - операнд1-операнд2 Разность между операндами - -операнд Противоположный операнд * операнд1*операнд2 Произведение операндов / операнд1/операнд2 Частное от деления операндов \ операнд1\операнд2 Целая часть частного от деления Mod операнд1 Mod операнд2 Остаток от целочисленного деления ^ операнд1^операнд2 <Операнд1> в степени <операнд2>
<операнд1> <оператор cравнения> <операнд2> <операнд1> Is <операнд2> <операнд1> Like <операнд2>
Специальные | Совпадающие |
символы | символы |
? | Любой одиночный символ |
* | Любое (с нулевого) количество символов |
# | Любая одиночная цифра (0-9) |
[список] | Любой одиночный символ из списка |
[!список] | Любой одиночный символ вне списка |
"BAU123khg" Like "B?[N-TV-X]*" 'Вырабатывается значение False.
Const MyNumber = 1001
Public Const MyString = "Вторая школа"
Private Const MyInt As Integer = 5
Const MyStr = "1001 ночь", MySalary As Double = 1E-50
DefBool - Boolean DefByte - Byte DefInt - Integer DefLng - Long DefCur - Currency DefSng - Single DefDbl - Double DefDate - Date DefStr - String DefObj - Object DefVar - Variant
DefInt A-Z
Dim MyVar As Double
Dim AnotherVar, Choice As Boolean, BirthDate As Date
Dim MyMatrix(1 To 5, 4 To 9, 3 To 5) As Double
Dim MyArray() 'Динамический массив типа Variant
[Public | Private] Enum Имя_типа Имя_элемента [= Выражение] Имя_элемента [= Выражение] ... End Enum
[Public | Private] [Static] Function Имя[(Список_аргументов)] [As Тип] [Инструкции] End Function
Type GroupData
GroupMember String * 50
Marks(15) As Integer
End Type
'Объявляем массив с элементами пользовательского типа:
Dim Group(1 To 25) As GroupData
Group(3).Marks(10) = 4 'Присвоение значения его структурной составляющей.
Do [{While | Until} Условие] [Инструкции] Loop Do [Инструкции] Loop [{While | Until} Условие]
Exit Do Exit For Exit Function Exit Property Exit Sub
For Each Имя_параметра In Имя_группы [Инструкции] Next [Имя_параметра]
For Параметр = Начало To Конец [Step Шаг] [Инструкции] Next [Параметр]
If Условие Then [Инструкции] [Else Инструкции_для_ложности_"Условия"] и блоковую: If Условие Then [Инструкции] [ElseIf Условие_N Then [Инструкции_для_"Условия_N"]]... [Else [Инструкции_для_ложности_всех_"Условий"]] End If
'Проверяем, какая кнопка ("Да" или "Нет") нажата в информационной панели:
If MsgBox("Хочешь съесть пирожок?", vbYesNo) = vbYes Then
MsgBox "Ешь на здоровье!"
Else
MsgBox "Ну, как хочешь"
End If
Sub RatherErroneous()
On Error GoTo ErrorHandler
...
Exit Sub
ErrorHandler:
...
Resume Next 'Передает управление на инструкцию, следующую за той,
'где возникла ошибка
End Sub
Select Case Выражение [Case Список_диапазонов-N-ой_ветви [Инструкции_N-ой_ветви]] ... [Case Else [Инструкции_по_умолчанию]] End Select
For i = 1 To 50
Select Case i
Case 1 To 3, 7 To 11, 15, 17, Is > 20
Beep
End Select
Next
Следует отличать оператор сравнения Is от ключевого слова Is, используемого в инструкции Select Case.
While Условие [Инструкции] Wend
ReDim [Preserve] Имя[([Список_диапазонов])] [As Тип] [, Имя[([Список_диапазонов])] [As Тип]]...
Dim A(100, 100)
...
ReDim Preserve A(100, 1000) 'Увеличение размера массива без потери данных
Dim MyArray(1 To 5,1 To 10) As Integer
требуется 118 байт: 18 для дескриптора (2 + 8 * 2) и 100 байт для данных (5 * 10 * 2).
VarString = String(10," ")
Get #1,,VarString
Пример
Type Record ' Тип, определенный пользователем.
ID As Integer
Name As String * 20
End Type
Dim MyRecord As Record, Position 'Объявляет переменную
' Открывает файл произвольного доступа:
Open "TESTFILE" For Random As #1 Len = Len(MyRecord)
' Читает из файла с помощью инструкции Get:
Position = 3 'Определяет номер записи
Get #1, Position, MyRecord 'Читает третью запись
Close #1 'Закрывает файл
Dim MyString, MyNumber
Open "TESTFILE" For Input As #1 'Открывает файл для чтения
Do While Not EOF(1) 'Цикл до конца файла
Input #1, MyString, MyNumber 'Читает данные в две переменные
Debug.Print MyString, MyNumber 'Выводит данные в окно отладки
Loop
Close #1 'Закрывает файл
Put #4,,FileBuffer
Файлы с произвольным доступом Random, подчиняются следующим правилам.
Dim MyArray(1 To 5,1 To 10) As Integer
требуется 118 байт: 18 для дескриптора (2 + 8 * 2) и 100 байт для данных (5 * 10 * 2).
VarString = String(10," ")
Get #1,,VarString
Пример
Type Record 'Тип, определенный пользователем
ID As Integer
Name As String * 20
End Type
Dim MyRecord As Record, RecordNumber 'Объявляет переменную
'Открывает файл произвольного доступа:
Open "TESTFILE" For Random As #1 Len = Len(MyRecord)
For RecordNumber = 1 To 5 '5 итераций:
MyRecord.ID = RecordNumber 'Определяет номер
MyRecord.Name = "My Name" & RecordNumber 'Создает строку
Put #1, RecordNumber, MyRecord 'Записывает запись в файл
Next RecordNumber
Close #1 'Закрывает файл
SetAttr "c:\sys", vbArchive + vbHidden + vbReadOnly
Примечание. При попытке изменения атрибутов открытого файла возникает ошибка выполнения. Не нужно также пытаться сделать меткой тома файл или каталог.
Dim MyAppID, ReturnValue
AppActivate "Microsoft Word" 'Активизирует Microsoft Word
'Кроме того, можно использовать значение, возвращаемое функцией Shell
MyAppID = Shell("C:\WORD\WINWORD.EXE", 1) 'Запускает Microsoft Word
AppActivate MyAppID 'Активизирует Microsoft Word
'Кроме того, можно использовать значение, возвращаемое функцией Shell
ReturnValue = Shell("c:\EXCEL\EXCEL.EXE", 1) 'Запускает Microsoft Excel
AppActivate ReturnValue 'Активизирует Microsoft Excel
Dim t As String
Date = #12/2/98# 'Устанавливает дату 2 декабря 1998 года
a = "12/2/98"
Date = a 'Устанавливает дату 12 февраля 1998 года
'Заполнение реестра:
SaveSetting "MyApp", "Startup", "Left", 50
'Удаление из реестра раздела со всем содержимым
DeleteSetting "MyApp", "Startup"
Time = #9:28:17 PM# 'Изменяет системное время
Sub Form_Load()
Dim CX, CY, Msg, XPos, YPos ' Объявим переменные
ScaleMode = 3 ' Установим свойство ScaleMode на пикселы
DrawWidth = 5 ' Задаем "толщину" точки в пикселях
ForeColor = QBColor(4) ' Зададим красный фон
FontSize = 24 ' Установим размер шрифта
CX = ScaleWidth / 2 ' Определим горизонтальное положение центра
CY = ScaleHeight / 2 ' Определим вертикальное положение центра
Cls ' Очистим форму
Msg = "Happy New Year!"
CurrentX = CX - TextWidth(Msg) / 2
'Горизонтальное положение
CurrentY = CY - TextHeight(Msg) ' Вертикальное положение
Print Msg ' Напечатаем сообщение
Do
XPos = Rnd * ScaleWidth ' Определим горизонтальное положение
YPos = Rnd * ScaleHeight ' Определим вертикальное положение
PSet (XPos, YPos), QBColor(Rnd * 15)
'DoEvents передает управление операционной системе
'Если часть программы занимает основное процессорное время,
'следует периодически использовать функцию DoEvents для отказа
'от управления в пользу операционной системы, чтобы такие
'события как ввод с клавиатуры и нажатия кнопок мыши могли быть
'обработаны без существенной задержки
DoEvents 'Без этого вызова мы никогда не закроем приложение
Loop
End Sub
Из всех указанных в таблице методов мы рассмотрим достаточно подробно только метод Print, относящийся к объекту Debug и выводящий элементы списка печати в стандартную область отображения (контейнеры Form, UserDocument, UserControl, PropertyPage). (Для графических методов стандартной областью отображения является также элемент PictureBox.)