В подавляющем большинстве случаев при программировании для Office можно обойтись без использования API, но иногда только вызов API-функции может привести к достижению нужного результата. Скажем, вам надо обеспечить вызов разных макросов при простом нажатии мышью кнопки на какой-либо панели инструментов Word и в случае одновременного нажатия этой кнопки и клавиши Shift или Control. Вот фрагмент кода, делающего это:
Declare Function GetAsyncKeyState Lib "user32.dll" (ByVal kState As Long) As Integer
Sub Program()
GetAsyncKeyState (vbKeyShift Or vbKeyControl)
If GetAsyncKeyState(vbKeyShift) Then
Call macroclass="underline" Exit Sub
Elself GetAsyncKeyState(vbKeyControl) Then
Call macro2: Exit Sub
End If
Call macro 3
End Sub
Первая строчка — это как бы "резервирование" функции API для использования в программе на VBA. Видно, что вызывается функция GetAsyncKeyState из библиотеки (файла, содержащего программы, предназначенные только для использования другими программами) user32.dll, причем в эту функцию передается номер клавиши, а возвращает она целое число (а именно — 0, если клавиша с соответствующим номером не нажата, и -32767 или 1, если нажата). Любую функцию или процедуру, вызываемую из библиотек, не относящихся к VBA, необходимо так резервировать с помощью команды Declare.
Фраза vbKeyShift в команде — это заменитель кода клавиши Shift (его значение — 16), a vbKeyControl, как нетрудно понять — заменитель кода клавиши Control. Структура инструкций "If… Then", думается, ясна[240], а если нет посмотрите в справке VBA. Команда Call перед именем макроса, как вы помните, означает его запуск.
В Интернете есть русские сайты, посвященные API[241]. Посетите их, чтобы узнать больше об этом наборе функций.
Рис. 8.9. Это окно вызывается функцией API.
Но помните, что программы, использующие функции API, в принципе не смогут быть мультиплатформенными, — об использовании их в Microsoft Office for Macintosh придется забыть.
НЕМНОГО О ПАРОЛИРОВАНИИ И ШИФРОВАНИИ
Защита доступа с помощью пароля — самый распространенный способ хранения всяческих секретов на компьютере. Однако о принципах такой защиты большинству пользователей известно плохо. В чем же ее основы? И как можно преодолеть такую защиту?
Ниже рассказывается об этом. Кроме того, вы узнаете, как можно сделать на VBA простейшую программу для шифрования и расшифровывания простых текстовых сообщений.
Среди математических логических функций, таких, как И, ИЛИ и других, есть весьма примечательная функция XOR. Команда, выполняющая эту функцию, есть практически во всех языках программирования. Ее действие отражено в следующей таблице:
Иными словами, это некое подобие функции ИЛИ[242], которая в отличие от настоящей ИЛИ возвращает 0, если на входы было подано сразу две единицы.
А теперь — приглядитесь повнимательнее и обратите внимание на интереснейшую вещь: если на вход функции XOR подать значение 1 входа и результат, то получится значение 2-го входа! И то же самое — со значением 2 входа и результатом: получается значение 1-го входа. Следовательно, зная итог функции XOR и значение на любом из входов, можно получить значение на другом входе, то есть функция XOR обратима.
А отсюда вытекает и принцип парольного шифрования. Берем некий текст, который должен быть зашифрован и некое слово, служащее паролем. Любой текст — это последовательность букв-байтов, а любой байт равен восьми битам, что позволяет представить текст как последовательность битов — нулей и единиц:
11010101010110101001101010111110101010111110101010001…
Представляем так же пароль:
10010101010011 и сопоставляем последовательности битов шифруемого текста и пароля, повторив пароль несколько раз так, чтобы у каждого бита шифруемого текста был соответствующий ему бит пароля:
11010101010110101001101010111110101010111110101010001…
10010101010011100101010100111001010101001110010101010…
И теперь — шифруем: применяем к этим двум последовательностям функцию XOR:
01000000000101001100111110000111111111110000111111011…
Все — шифрование закончено! Полученную последовательность можно хранить в качестве зашифрованного паролем файла. Ну, а когда потребуется расшифровка, то будет необходимо просто применить ту же самую функцию XOR к этой последовательности вместе с паролем, и тогда в результате получится исходный текст. Преобразовать же последовательность нулей и единиц обратно в текст труда не составит.
Нетрудно понять, что, зная зашифрованный текст и часть незашифрованного, соответствующую определенной части зашифрованного, можно с помощью той же функции Хог определить пароль, и затем с его помощью расшифровать остальную часть текста. Поэтому в современных системах защиты текста паролем используются более сложные способы, например, повторение пароля не подряд, а с определенными промежутками, с обратным расположением символов в пароле, с двойным шифрованием — результат первого шифрования снова шифруется другим паролем. Но принцип — использование функции XOR — остается неизменным, именно из-за ее обратимости.
Функция XOR, разумеется, присутствует и в VBA. Вот пример кода, реализующего возможности шифрования с ее помощью.
Sub encrypt()
Dim а, b, с, d As String
Исходный текст для шифрования — запрашивается от пользователя, к примеру:
а = "secret text from kgb agent from newyork rezidentura…"
Пароль: может запрашиваться от пользователя: b = "password"
Итог шифрования: с = ""
Узнаем длины каждой из строк — пароля и исходного текста:
lentext = Len(а)
lenpass = Len(b)
Собственно шифрование:
For cn = 1 То lentext
В этой строке попробуйте разобраться самостоятельно. Здесь выполняется функция Хог с каждым символом исходной строки и соответствующим символом пароля, как бы "повторенным" на всю длину исходного текста. Mid берет из середины строки символ, Asc — превращает его в ASCII-код, Str — превращает число в строку, Trim — удаляет пробелы:
d = Trim(Str(Asc(Mid(a, cn, 1)) Xor Asc(Mid(b, ((cn — 1) Mod lenpass) + 1, 1))))
А теперь сделаем так, чтобы каждый символ занимал ровно три позиции, вне зависимости от величины его ASCII-кода. А иначе как потом при расшифровке разбивать строку на символы?
Select Case Val(d)
Case 0 To 9
d = "00" + d
Case 10 To 99
d = "0" + d
End Select
с = с + d
Ну вот и все, и так — с каждым символом из исходной строки:
Next cn
Теперь в переменной с — шифрованная строка, каждой исходной букве соответствует 3 символа. Ее можно записать, например, в документ:
Selection.TypeText Text:=c
End Sub
А теперь — программа расшифровки данных. Точно так же разберем ее по строкам.
Sub decrypt()
Dim а, b, с, d As String
Строка для расшифровки:
с = "003004016001018027082016021025007083017029029009"
Пароль:
b = "password"
Итог расшифровывания: а = ""
Узнаем длины каждой из строк:
lentext = Len(с)
lenpass = Len(b)
Собственно расшифровывание (попробуйте разобраться самостоятельно в структуре команды — это не так сложно):
For cn = 1 То lentext Step 3
а = а + Chr(Val(Mid(с, cn, 3)) Xor Asc(Mid(b, (Int(cn / 3) Mod lenpass) + 1, 1)))
Next cn
В итоге в переменной а — расшифрованная строка, ее можно записать в любое место — в документ, к примеру:
Selection.TypeText Text:=a
End Sub
Можно, конечно, еще добавлять в этот простой код всевозможные дополнения, например, функцию перевода строки цифр в строку символов, чтобы зашифрованный текст выглядел как бессмысленный набор букв. Но это — уже по желанию.
ОТКРЫТЫЙ И ЗАКРЫТЫЙ КОДЫ
Наверняка все слышали такие фразы: "Шифрование с открытым ключом", "Шифрование с закрытым ключом", "Публичный ключ". О том, что они означают, можно писать большие книги, однако стоит вкратце описать ситуацию для полноты изложения.