
- •Часть I: начало работы со скриптами
- •3.3 В Jaws for Windows появилась возможность загружать файлы
- •Void, если вам не нужно, чтобы ваша функция возвращала какое-либо
- •Insert Function Call - выводит диалог вставки функции, который
- •Insert PerformScript (вставить выполнение скрипта) - при выборе этой
- •InvisibleCursor() - активизирует невидимый курсор.
- •InvisibleCursor() ; активизируется невидимый курсор
- •InvisibleCursor () ; активизируется невидимый курсор
- •InvisibleCursor(), нажимайте Enter, чтобы вставить ее в наш скрипт.
- •Часть II
- •Include "hjglobal.Jsh"
- •IntVar на 1)
- •If (nAttributes & attrib_highlight) Then
- •Visual Basic.
- •If GetExcelVersion Then
- •If (nAttributes & attrib_highlight) then
- •1. Используйте комментарии, комментарии и еще раз комментарии!
- •InvisibleCursor() - активизирует невидимый курсор.
- •2. Диспетчер скриптов проверяет .Jsd файл на наличие строк
- •Include файлы проверяются, когда они включаются. Всегда ставьте
- •If (IsSameScript ()) Then
- •Import Macro File: используется для импорта файла макроса из ранних версий
- •If (GetAttributes() & attrib_underline) then ... (более подробное описание
- •VerbosityLevel - контролирует количество информации, произносимой jfw,
Visual Basic.
Объект Paragraph
Представляет один абзац в выделении, диапазоне или документе.
Объект Paragraph является членом коллекции Paragraphs. Коллекция
Paragraphs включает все абзацы в выделении (selection),
диапазоне (range) или документе.
Использование объекта Paragraph
Используйте Paragraphs(index), где Index является индексным
номером, чтобы возвратить один объект Paragraph.
Таким образом, после того, как свойство Paragraph возвратило
свою информацию, мы будем иметь возвращенный объект с абзацем,
который содержит курсор вставки (предполагая, что не было
выделено никакого текста) или первый абзац, который является
частью выделенного текста. (в первом случае есть только один
абзац, а во втором случае индекс (1) объекта Paragraph
возвращает первый абзац, который является частью выделения).
Далее следует свойство Range. Свойство Range возвращает объект
Range, который представляет часть документа, которая содержится
в указанном объекте. В этом случае указанным объектом является
объект Paragraph, который был возвращен свойством Paragraph
слева. Range подобен паре закладок. Первая представляет начало
диапазона, вторая - его конец. Объект Range, который
возвращается свойством Range, используя информацию из объекта
Paragraph, будет иметь начальную и конечную точки указанного
абзаца, установленные как диапазон (range). Этот окончательный
объект теперь установлен, чтобы позволить нам вытащить
информацию, которая нам нужна, чтобы озвучить текущий абзац. Вот
еще один отрывок из системы помощи по Visual Basic.
Объект Range
Представляет непрерывную область в документе. Объект Range
задается начальной и конечной позициями символа. Аналогично
тому, как закладки используются в документе, объекты Range
используются в процедурах Visual Basic, чтобы идентифицировать
конкретные порции документа. Однако, в отличие от закладки,
объект Range существует только пока работает процедура,
определившая его.
Обратите внимание, что объекты Range независимы от выделения. То
есть, вы можете определить диапазон и манипулировать им, не
изменяя выделения. Вы также можете задать в документе несколько
диапазонов (ranges), тогда как выделение в панели может быть
только одно.
Использование объекта Range
Используйте процедуру Range, чтобы возвратить объект Range,
заданный данными начальной и конечной позициями символов.
Следующий пример возвращает объект Range, который ссылается на
первые 10 символов в активном документе.
Set myRange = ActiveDocument.Range(Start:=0, End:=10)
Используйте свойство Range чтобы возвратить объект Range,
заданный началом и концом другого объекта. Свойство Range
применяется ко многим объектам (например, Paaragraph (абзац),
Bookmark (закладка) и Wtll (ячейка). Следующий пример возвращает
объект Range, который ссылается на первый абзац в активном
документе.
Set aRange = ActiveDocument.Paragraphs(1).Range
Теперь мы подходим к следующей строке в функции
GetParagraphContent, той, которая возвращает информацию в
вызывающий скрипт. Эта строка выглядит следующим образом:
return (o.Text);
Здесь o является объектом Range, который был возвращен в конце
предыдущей строки, а Text является свойством Text, которое
возвращает действительный текст, который нас интересует, из
объекта Range. (Обратите внимание, что в этом случае свойство
Text возвращает действительный текст, а не объект). Как это было
использовано здесь, свойство Text возвращает плоский,
неформатированный текст диапазона. Наконец-то мы добрались до
информации, за которой охотились. Текст, который будет возвращен
свойством Range, в этом случае будет текстом текущего абзаца.
Он, в свою очередь, будет возвращен в наш вызывающий скрипт с
помощью утверждения return в этой строке кода. Поскольку
свойство Text возвращает строку, мы возвратим строку в наш
вызывающий скрипт, точно так же, как мы указали в первой строке
нашей функции. Затем вызывающий скрипт может продолжить свою
обработку и озвучить текст, который был возвращен.
Ключ ко всем этим сложным махинациям состоит в том, что каждый
объект может использовать только определенные свойства и
процедуры (как мы сказали примерно в начале этого раздела),и не
может использовать процедуры и свойства других объектов. Чтобы
получить информацию, которую мы хотим, мы должны использовать
корректную процедуру или свойство для нашего текущего объекта, и
мы должны использовать эту процедуру или свойство таким образом,
чтобы был возвращен новый объект, который установлен должным
образом, чтобы позволить нам получить доступ к информации,
которая нам нужна, на более низком уровне в иерархии. Если мы
все сделаем правильно, в конечном итоге мы доберемся до
информации, которая нам нужна. Очень скоро мы познакомим вас с
системой помощи Visual Basic, и покажем, как ей пользоваться,
чтобы найти допустимые процедуры и свойства для объекта, с
которого вы начинаете. Однако, прежде чем мы этим займемся,
давайте выполним эксперимент, чтобы показать, как свойства,
использованные в функции GetParagraphContent, извлекают
информацию, которая нам нужна, из объекта приложения и как
изменение способа, которым мы используем эти свойства, изменяет
информацию, которую мы слышим в конечном итоге. Прежде, чем мы
продолжим, необходимо сделать предупреждение. Эксперимент
включает модификацию файлов WINWORD.JSS и WINWORD.JSB.
Настоятельно рекомендуется сделать резервные копии этих файлов,
прежде чем вносить какие-либо изменения. Это позволит вам
вытащить неповрежденные копии файлов, если вы нечаянно
что-нибудь напартачите.
Чтобы выполнить этот эксперимент, откройте файл скриптов для
Word 8 и найдите функцию GetParagraphContent. Затем спуститесь к
первой строке после того, как объявлена переменная o. Очень
скоро мы внесем в эту строку некоторые изменения, но прежде, чем
мы это сделаем, давайте на некоторое время вернем фокус в Word и
посмотрим, что делает эта функция в своем немодифицированном
состоянии. Вы должны вернуться в Word и установить курсор на
первое слово в этом абзаце. Воспользуйтесь горячей клавишей
"Прочитать абзац" (CTRL+Плюс на цифровой клавиатуре) и вы должны
услышать, как будет озвучиваться весь этот параграф. Теперь
воспользуйтесь командой Shift+Стрелка вниз, чтобы выделить
первую строку этого абзаца. Подтвердите, что вы это сделали,
прочитав выделенный текст с помощью команды Shift+Insert+Стрелка
вниз, и вы должны услышать, как озвучивается первая строка
абзаца. Теперь снова воспользуйтесь горячей клавишей "Прочитать
абзац". Вы снова должны услышать, как озвучивается абзац.
Хорошо, мы убедились в том, что функция GetParagraphContent
достаточно сообразительна, чтобы прочитать нам весь абзац, даже
несмотря на то, что мы выделили часть его. Это хорошо, потому
что именно так и должна вести себя эта функция. Теперь вернитесь
в диспетчер скриптов и удалите свойство Paragraphs(1) из строки,
которая его содержит. После того, как вы это проделаете, строка
должна выглядеть следующим образом:
let o = oWord.Selection.Range;
Сохраните и перекомпилируйте файл с помощью команды Ctrl+S.
Вернитесь в Word и поставьте курсор вставки в начало того же
параграфа, который вы читали перед этим. Убедитесь, что не
выделено никакого текста, а затем воспользуйтесь командой
"Прочитать абзац" и посмотрите, что происходит. Как интересно!
Ничего не озвучивается. А почему? Ну, поскольку ничего не
выделено, свойство Selection возвращает объект Selection,
который эквивалентен курсору вставки. Поскольку мы убрали
свойство Paragraphs, свойство Range будет оперировать прямо с
этим объектом Selection, и возвращать объект Range, который
начальная и конечная точки которого находятся в одном и том же
месте, там, где находится курсор вставки. Очевидно, диапазон,
длина которого составляет 0 символов, не может содержать
никакого текста, поэтому свойство Text в следующей строке
скрипта возвращает Null или пустую строку, и мы вообще ничего не
слышим. А теперь выполните еще один эксперимент. Снова выделите
первую строку абзаца с помощью команды SHift+Стрелка вниз, а
потом снова воспользуйтесь командой "Прочитать абзац". На этот
раз вы услышите, как будет озвучен выделенный текст. Это
происходит потому, что объект Selection, который возвращается
свойством Selection, включает весь выделенный текст, а свойство
Range теперь установит диапазон в начале и конце выделенного
текста. Свойство Text в следующей строке вернет этот текст,
который, в свою очередь, будет возвращен в вызывающий скрипт для
озвучивания. Убедитесь, что вы не забыли возвратить свойство
Paragraphs обратно в функцию, точно так же, как оно и было, и
перекомпилировать файл скриптов, чтобы функция снова работала
как положено. Теперь свойство Paragraphs будет снова будет
возвращать объект Paragraph из объекта Selection и поставлять
эту информацию свойству Range. Вы снова будете слышать, как
озвучивается абзац целиком, независимо от того, выделен ли
какой-либо текст.
И наконец, как мы и обещали, вот некоторые советы относительно
использования справочной системы Visual Basic, чтобы узнать,
какие процедуры и свойства применяются к к каждому объекту.
Приведенные ниже инструкции относятся к Microsoft Word, но
аналогичные процедуры можно использовать и для других
приложений, таких как Excel. Предполагая, что справочная система
по Visual Basic установлена, нажмите F1, находясь в Wordе, а
затем нажимайте Ctrl+Tab, пока не попадете на страницу
оглавления. Спускайтесь вниз почти до самого последнего пункта,
которым является "Справочная система Visual Basic в Microsoft
Word". Откройте эту книгу и спускайтесь к единственной теме,
"Справка по Visual Basic". Нажмите Enter, чтобы открыть эту
тему. Теперь спускайтесь ко второй книге нового списка, которая
называется тоже "Справочная система по Visual Basic в Microsoft
Word". Открывайте эту книгу и спускайтесь к третьему пункту,
который называется "Объекты". Открывайте эту книгу, и вы увидите
алфавитный список книг. Каждая из книг содержит объекты
Microsoft Word, которые начинаются с указанной буквы. Вы можете
открывать каждую книгу и изучать доступные вам объекты.
Спускайтесь к букве "R" и открывайте эту книгу. Первый объект в
этой книге - объект Range. Если вы нажмете Enter на этой строке,
вы получите описание объекта Range, то же самое, которое было
процитировано выше. Вы также обратите внимание, что около
верхней части экрана есть строка, на которой написано "см. также
свойства, процедуры, события". Именно здесь вы можете найти,
какие свойства и процедуры доступны для этого объекта. Щелкните
Jaws курсором кнопку "Свойства" и вам будет представлен список
свойств Range. Спускайтесь к свойству Text, и нажимайте Enter.
Здесь вы можете прочитать о свойстве Text, которым мы
воспользовались., чтобы возвратить действительный текст из
функции GetParagraphContent. Таким же способом можно получить
доступ к процедурам Range.
Если вы вернетесь в алфавитный список книг с объектами и
откроете книгу "A", вы найдете объект, который называется
"Объект Application". Это объект самого верхнего уровня, к
которому вы можете получить доступ. Глобальная переменная,
которой мы пользовались прежде, oWord, является объектом
application. Именно здесь вы вообще начинаете, когда будете
писать скрипты с объектами. Нажмите Enter на этом пункте, и вы
получите информацию об объекте application.Если вы щелкнете на
кнопке "Свойства" в верхней части окна, вы получите список всех
свойств, доступных для объекта application. А знаете что? Этот
список содержит свойство Selection, свойство, которое мы впервые
использовали, чтобы начать операции над объектом application,
oWord. Все возвращается на круги своя.
Подводя итог, вы начнете писать скрипты с объектами с объекта
Application, а затем выбираете процедуру или свойство из списка
доступных, щелкнув или на кнопке "Свойства", или на кнопке
"Процедуры" в верхней части окна описания объекта Application.
После того, как вы воспользуетесь процедурой или свойством,
которое вы выбрали, вы затем получите объект, который будет
иметь то же имя, что и данная процедура или свойство.
Возвращайтесь в алфавитный список книг с объектами и открывайте
ту, которая начинается на ту же букву, что и процедура или
свойство, которыми вы пользовались, поскольку объект,
возвращаемый этим свойством или процедурой, имеет то же имя.
Открывайте эту книгу и ищите строку с этим именем. Затем
открывайте этот пункт и используйте его список процедур и
свойств, чтобы выбрать следующие. Повторяйте эту процедуру, пока
не зайдете достаточно далеко, чтобы извлечь ту информацию,
которая вам нужна.
Управление потоком
Скрипты не всегда выполняются линейно, сверху вниз, где каждая
строка выполняется по порядку и только один раз. Иногда
некоторые утверждения выполняются много раз, а иногда некоторые
утверждения вообще пропускаются. Типы утверждений, которые
управляют потоком, которые управляют потоком, или
последовательностью событий утверждений скрипта обсуждаются
ниже. Поток в скрипте бывает трех типов:
Последовательный - в этом способе группа утверждений работает по
порядку, начиная с начала и продвигаясь к концу. Этот линейный
поток является самым простым форматом.
Выбор (условный) - в выборе поток действий подходит к развилке
на дороге, и должен выбрать один из двух или многих путей. Какой
путь выбирается, зависит от сравнений, или условий, которые
выполняются утверждениями скриптов. В зависимости от значения
определенных переменных., выбирается тот или иной путь. Этот
процесс называется ветвление.
Итеративный - итеративный раздел "зацикливается", то есть,
выполняет одно и то же утверждение или группу утверждений снова
и снова, или пока определенное условие является истинным, или
пока не будет выполнено определенное условие.
Скрипт может содержать любой из этих способов, или все их
вместе. Давайте рассмотрим каждый из этих видов действий.
Последовательный
Все утверждения, с которыми мы работали до сих пор, являются
последовательными утверждениями. Это означает, что каждое
утверждение действует в свою очередь, начиная в верхней части
скрипта и продвигаясь к утверждению EndScript. Ниже приводится
пример скнипта только с последовательными утверждениями:
Script SayTheAValue()
Var
Int A
Let A = 1
SayInteger (A)
EndScript
Выбор (условный)
Структура утверждения if-then предоставляет средство выбора
одного пути или другого. Для структуры if нужны три утверждения:
if, then и endif. Давайте начнем с очень простого утверждения
if-then.
If (x == 1)
Then
SayString ("You are right")
EndIf
Если, и только если переменная A равняется 1, скрипт выполнит
утверждение SayString, и произнесет слова "You are right" (Вы
правы). А вот пример посложнее.
If GetWindowName (GetCurrentWindow ()) == "Main"
Then
SayString("In the main window.")
EndIf
Функция GetWindowName, и ее параметр, GetCurrentWindow,
использованные в утверждении if, возвращает заголовок текущего
окна. А происходит следующее. Если и только если имя текущего
окна является Main, (главное), тогда выполняется функция
SayString. В остальных случаях она игнорируется. Мы выбираем
путь "Then" только в том случае, если условие If является
истинным.
Хотя утверждения If и Then по сути являются отдельными
утверждениями, часто бывает принято помещать их на одной строке.
Вышеприведенная группа утверждений может выглядеть следующим
образом:
If GetWindowName (GetCurrentWindow ()) == "Main" Then
SayString("In the main window.")
EndIf
Отныне мы будем показывать наши утверждения If-Then именно в
такой форме.
В структуре If-Then есть два опциональных утверждения,
утверждения Else и Elif. Каждое из этих утверждений
предоставляет альтернативный путь, но делают они это немного
по-разному. Утверждение Else говорит скрипту, что он должен
выполнять определенные вещи, если, и только если обнаружилось,
что предшествующее ему условие If является ложным. Например,
If GetWindowName (GetCurrentWindow ()) == "Main" Then
SayString("In the main window.")
Else
SayString("Not in a known window.")
EndIf
Эта последовательность будет выдавать одно сообщение, если вы
будете находиться в главном окне, и что-то другое, если нет. А
вот пример тройного ветвления:
If GetWindowName (GetCurrentWindow ()) == "Main" Then
SayString("In the main window.")
Else
If GetWindowName (GetCurrentWindow ()) == "Alternate" Then
SayString("In the alternate window.")
EndIf
Else
SayString("Not in a known window.")
EndIf
Здесь мы выдаем одно сообщение, если находимся в главном окне,
другое сообщение, если находимся в альтернативном окне, и мы
выдаем третье сообщение, если не находимся ни в каком из первых
двух окон.
Утверждение Elif - это более простой способ сформулировать
ветвь, которая говорит: "делай что-то другое, если истинно
другое условие". Вышеприведенную последовательность скрипта
можно переформулировать, чтобы выполнялось в точности то же
самое, используя утверждение Elif. Это показано ниже:
If GetWindowName (GetCurrentWindow ()) == "Main" Then
SayString("In the main window.")
ElIf GetWindowName (GetCurrentWindow ()) == "Alternate" Then
SayString("In the alternate window.")
Else
SayString("Not in a known window.")
EndIf
Здесь мы снова можем отправиться по альтернативным путям. Если
окно называется Main, мы идем его путем. Если окно называется
Alternate, мы идем его путем. В противном случае мы идем по пути
Else. Утверждение Elif занимает место утверждения Else, за
которым следует утверждение If. Вы можете использовать столько
утверждений Elif, сколько захотите.
Утверждения If могут быть вложенными. Это означает, что
утверждение If может быть помещено внутри другого утверждения
If. Это позволяет вам проверять какое-то условие только в том
случае, если существует другое условие. Второе условие If будет
проверяться только в том случае, если истинно первое условие.
Последовательность утверждений внутри второго блока If-Then
будет,таким образом, выполнена, только если оба условия будут
сочтены истинными. Не забудьте для любого и каждого утверждения
If, которое вы используете, добавлять утверждение Endif. Вот
пример вложенных утверждений If-Then:
If GetWindowName (GetCurrentWindow ()) == "Main" Then
If GetWindowClass (GetCurrentWindow ()) == "Edit" Then
SayString("In the main edit window.")
Else
SayString ("In the main window")
EndIf ;Is this an edit window?
Else
SayString ("Not in a known window")
EndIf ;Is this the main window?
В этом примере сначала мы проверяем, находимся ли мы в главном
(Main) окне.Если да, то мы проверяем, находимся ли мы в окне
редактирования (Edit Window). Если да, то мы говорим, что
находимся в главном окне редактирования (Main Edit Window). Если
это не окно редактирования, то мы просто говорим, что мы в
главном окне. Условие Edit будет проверяться только в том
случае, если условие Main является истинным. Обратите внимание,
что мы использовали комментарии, чтобы показать, какую If
проверку завершает утверждение Endif. Это очень полезно, чтобы
избежать путаницы при использовании вложенных утверждений
If-Then.
Итеративы
Как уже упоминалось выше,раздел итерации предоставляет функцию
цикла. Цикл используется для того, чтобы выполнить
последовательность утверждений несколько раз, сокращая таким
образом число утверждений, которые требуются. Кроме того, иногда
заранее не знаешь, сколько раз нужно повторить
последовательность, поэтому цикл позволяет определить число
повторений автоматически, в зависимости от выводов, вытекающих
из действий скрипта. Цикл выполняется с помощью
последовательности While-EndWhile.
Цикл While - это последовательность утверждения, которое
повторяется, или зацикливается, пока является истинным
какое-либо условие, или пока не станет истинным конкретное
условие. Цикл While состоит из двух частей - утверждения While,
которое задает условия, которые должны будут проверяться, и
утверждения EndWhile, которое завершает цикл. Все утверждения в
границах утверждений While и EndWhile будут выполняться
повторно, пока не будет соблюдено условие, приведенное в условии
While. Вот пример.
Давайте возьмем довольно обычную проблему. Вы работаете в
программе редакторе, которая нумерует строки пятью цифрами.
Поэтому первая строка нумеруется как 00001. Jaws тратит массу
времени, читая нули. Было бы здорово начать чтение с первой
ненулевой позиции, не правда ли? Здесь самое место для цикла
While. Рассмотрим следующий скрипт:
Script SayEditLine()
SaveCursor ()
JAWSCursor()
RouteJAWSToPC()
JAWSHome()
While (GetCharacter () == "0")
NextCharacter ()
EndWhile
SayFromCursor()
RestoreCursor ()
EndScript
Использование такого скрипта для чтения номера строки устранит
для нас начальные нули. Вот как это делается. Первые четыре
строки сохраняют позицию курсора, активизируют Jaws курсор и
перемещают его к началу строки, на которой мы находимся. Затем
цикл While просматривает каждый символ в начале строки по
очереди и смотрит, не ноль ли это. Если ноль, то он просто
переходит к следующему символу и тоже его проверяет. когда он
находит символ, который не является нулем, условие для
продолжения цикла больше не является истинным, и цикл While
завершается. Затем JFW продолжает обрабатывать оставшуюся часть
скрипта после цикла Whilt. Сюда входит чтение оставшейся части
строки от курсора до конца строки. Это избавляет от всех нулей.
Здесь нужно сделать предупреждение относительно циклов While.
Поскольку цикл выполняется до тех пор, пока условие не
становится истинным или ложным, нужно быть осторожным и не
создавать циклы с условием, которое никогда не будет
удовлетворено. Если так сделать, цикл будет длиться вечно,
бесконечный цикл. Результатом будет блокирование компьютера,
пока программа не будет завершена вручную. Внимательно
продумывайте условие, которое может завершать цикл, чтобы быть
уверенным, что когда-то это условие будет выполнено. Если вы
обнаружили, что компьютер заблокирован после того, как вы
выполнили новый скрипт с циклом While, вероятнее всего,
произошло именно это. Один из способов избежать эту проблему при
разработке циклов While - включать некоторые утверждения,
предназначенные для того, чтобы прерывать работу цикла после
некоторого числа повторений. Пример такого цикла показан ниже.
While FirstVariable < SecondVariable
Let BreakOutVariable = BreakOutVariable+1
(Rest of loop would be here.)
If (BreakOutVariable > 100) Then
Return
EndIf
EndWhile
Этот цикл задуман таким образом, что он будет работать до тех
пор, пока первая переменная не станет больше второй переменной.
Давайте представим, что мы допустили логическую ошибку, и первая
переменная никогда не будет больше второй переменной. Без
дополнительных утверждений, призванных предотвратить такой
оборот событий,цикл будет работать вечно. Однако, вторая строка
добавляет 1 к переменной BreakOutVariable всякий раз, когда цикл
повторяется. Когда значение BreakOutVariable превышает 100,
утверждение If-Then в конце цикла выполнит возврат и завершит
цикл. Если вы уверены, что цикл While работает как положено, вы
можете удалить логику прерывания.
Домашнее задание # 5
Для этого домашнего задания давайте опять воспользуемся
программой Фонограф. В прошлый раз, когда мы писали скрипт для этой
программы, мы обратили внимание, что счетчик над кнопками
показывает и время, которое прошло, и полное время звукового
файла. Напишите скрипт, используя утверждения If-Then и
утверждения Elif, который проверяет, что прошедшее время не
является нулем. Если это так, пусть выдается сообщение "В начале
записи". Если прошедшее время больше нуля, но меньше полного
времени, пусть выдается сообщение "Проигрывание завершено только
частично". Если прошедшее время равно полному времени, пусть он
говорит "Проигрывание завершено" и щелкает кнопку "Искать
начало" или обратную перемотку, чтобы вернуть счетчик к нулю.
Затем пусть скрипт сделает паузу, чтобы дать приложению время
перемотать обратно, а потом снова проверит счетчик, чтобы
посмотреть, находится ли он в нулевой позиции. Если да, пусть он
выдаст сообщение "ОБратная перемотка завершена". Если счетчик не
находится в нулевой позиции, пусть он выдаст сообщение "Обратная
перемотка невозможна. Проверьте ваши батарейки". Также
воспользуйтесь локальными переменными, чтобы хранить время в
целом и прошедшее время.
Функции, определяемые пользователем
С помощью языка скриптов можно написать или отредактировать
определяемую пользователем функцию. Разница между встроенной
функцией и функцией, определяемой пользователем,состоит в том,
что функции, определяемые пользователем, можно модифицировать, в
то время как встроенные функции модифицировать нельзя, так как
они запрограммированы в Jaws. Разница между определяемой
пользователем функцией и скриптом состоит в том, что скрипт
может быть привязан к клавише и не может предоставить возврат, а
определяемая пользователем функция не может быть привязана к
клавише и предоставляет возвраты. Определяемые пользователем
функции запускаются всякий раз, когда они вызываются из скрипта
или из другой определяемой пользователем функции.
Простые функции
Опреде-
ляемые пользователем функции обычно создаются как
самостоятельные модули скриптового кода, который предназначен
для выполнения конкретной задачи. Это особенно полезно, когда
работа, которую должна выполнить функция, должна выполняться
большое количество раз и разными скриптами. Это позволяет
повторно использовать код функции, не переписывая его несколько
раз. Все, что должен сделать пользователь, это вызвать функцию
из другого скрипта или функции, и работа будет выполнена. Затем
вызванная функция возвращает управление обратно вызывающему
скрипту или функции, который, в свою очередь, продолжает свою
работу. Простейший тип функции не принимает никаких данных
(параметров) и не возвращает никаких данных (возвратов) в
вызывающий скрипт. Давайте рассмотрим пример определяемой
пользователем функции, который взят из файла скриптов для
Microsoft Excel, EXCEL.JSS. Этот скрипт называется NextSheet, и
в его задачу входит переместить фокус к следующей таблице. Вот
код из скрипта:
Script NextSheet()
;переходит в следующую таблицу и читает номер
{CONTROL+PPAGE DOWN}
Delay (1)
SayWindowPromptAndText()
EndScript
Обратите внимание, что скрипт вызывает функцию, которая называется
SayWindowPromptAndText. Вы не найдете этой функции среди встроенных
функций Jaws. Это определяемая пользователем функция, которая была
написана программистами из Henter-Joyce и включена в EXCEL.JSS. Ниже
приводится код для SayWindowPromptAndText.
Function SayWindowPromptAndText ()
SaveCursor ()
InvisibleCursor ()
RouteInvisibleToPC ()
If (FindLastAttribute (ATTRIB_BOLD)) Then
SayChunk ()
Else
SayString (msg121) ;"bolded sheet tab not found"
EndIf
EndFunction
Давайте теперь пройдемся по процедуре создания простой определяемой
пользователем функции. В качестве цели мы будем иметь создание функции,
которая будет озвучивать наше имя, точно также, как мы это сделали в
нашем первом скрипте. Как и прежде, мы поместим эту функцию в файл
скриптов для редактора "Блокнот" (Notepad).
1. Откройте Блокнот через главное меню/Программы/Стандартные.
2. Откройте диспетчер скриптов, нажав Insert+0 или Insert+F2, после чего s и
Enter. Jaws сообщит вам, что вы находитесь в файле notepad.jss, исходном
файле скриптов для Блокнота.
3. В меню Скрипт выберите пункт Новый скрипт, или нажмите
клавишу-ускоритель, CTRL+E.
4. Появляется диалог нового скрипта, и теперь мы можем назвать нашу
функцию и написать ее документацию. Когда появляется диалог нового
скрипта, курсор находится в поле имени скрипта. Наберите SayName
(СказатьИмя). Убедитесь, что буквы S и N являются большими и не делайте
пробелов.
5. Дважды нажмите Tab, чтобы переместиться к полю Synopsis. Наберите
слова "Say our name". (пропустив блок проверки Can be attached to key
(может быть привязан к клавише) без его включения мы сказали диспетчеру
скриптов, что мы создаем функцию, а не скрипт).
6. Нажмите Tab, чтобы переместиться в поле Description (Описание) и
наберите слова "The name of the person who wrote this function." (Имя
человека, написавшего эту функцию).
7. Нажмите Tab, чтобы переместиться в поле Категория, и наберите Test. Поле
Категория - это комбобокс, в котором вы можете либо вписать название
категории, либо просто выбрать одно из имеющихся.
8. Нажмите Tab, чтобы переместиться в поле Function returns (Возвраты
функции) и спуститесь к значению Void. Мы выбираем Void, потому что
наша функция не возвращает никакой информации в вызывающий скрипт.
9. Больше нам никаких полей заполнять не нужно, поэтому клавишей Tab
перемещайтесь к кнопке OK, и нажимайте клавишу Enter, чтобы закрыть
диалог нового скрипта и вставить пустую функцию в область редактирования.
10. Теперь мы снова находимся в главной текстовой области диспетчера
скриптов и мы имеем пустую функцию, где в первой строке написано
"Void Function SayName ()", а в последней строке написано "EndFunction".
Мы помещены между двумя этими строками. Клавишей "Стрелка вверх"
поднимайтесь до первой пустой строки после первой строки, и вы готовы к
тому, чтобы написать тело функции.
11. Для этой функции вам понадобится только одна строка, и это будет та же
самая строка, которую мы использовали для нашего первого скрипта. Эта
строка будет SayString ("My name is XXX"), где XXX - ваше имя. Чтобы
вставить эту строку в вашу функцию, нажмите CTRL+I, чтобы открыть диалог
Insert function (вставить функцию). Затем наберите s,a и y. Вы должны
услышать, как Jaws скажет SayString, имя встроенной функции, которая была
выделена. Нажмите Enter, чтобы принять эту функцию.
12. Теперь вам будет предложено ввести строку, которая должна озвучиваться.
Наберите "My name is XXX", и не забудьте включить кавычки. После того,
как вы нажмете Enter, вы вернетесь в область редактирования, где ваша
функция теперь закончена.
13. Теперь на вашей странице должно быть три строки, в точности так, как
они выглядят ниже. Помните, что близко - значит недостаточно хорошо,
поскольку компьютеры ожидают, что мы будем точными и совершенными.
Кроме того, несколько пустых строк роли не играют. Jaws игнорирует пустые
строки в функциях.
Void Function SayName()
SayString ("My name is XXX")
EndFunction
14. Теперь мы должны сохранить и скомпилировать файл скриптов для
Блокнота. Нажмите CTRL+S, и вы должны услышать "Compile Complete"
(Компиляция завершена). Если что-то не так, вернитесь и вновь проследите все
шаги и попробуйте снова.
Теперь мы создали функцию, которая будет выполнять ту же самую работу,
что и наш первый скрипт. Эту функцию можно вызвать всякий раз, когда
нам понадобится озвучить наше имя. Чтобы вызвать функцию, мы должны
будем использовать скрипт, сформулированный, как показано ниже.
Script SpeakName ()
SayName ()
EndScript
Этот простой скрипт будет вызывать функцию, которая будет озвучивать наше
имя. Теперь может показаться немного глупо, проходить через все эти
проблемы, когда мы могли бы выполнить ту же самую задачу с помощью
нашего первого скрипта. Конечно, для простого случая, как этот, может быть
оно и так. Однако, функции могут быть длинными и сложными. В случаях
таких сложных функций будет очевидным, что будет проще создать код один
раз, а потом вызывать его всякий раз, когда он нам понадобится. Иначе нам
пришлось бы воссоздавать весь этот код для каждого конкретного скрипта, где
он понадобится.
Определяемая пользователем функция, которую мы обсуждали несколькими
абзацами выше, это самый простой вид определяемых пользователем функций,
потому что он не требует никаких параметров и не возвращает никаких
значений в вызывающий скрипт. Однако, определяемые пользователем
функции могут делать и то, и другое. Давайте рассмотрим примеры таких
функций.
Функции, которые требуют параметры
Первый пример - это функция, которая принимает параметры. Помните, что
параметр - это не что иное, как фрагмент информации, который вы передаете
в функцию, чтобы она использовала ее при работе. Единственная причина,
почему мы передаем эту информацию во время работы, а не включаем ее как
часть кода, состоит в том, что информация может быть различной при
каждом вызове функции. Помните, что параметр объявляется как переменная,
но помещается между скобками, следующими после имени функции, а не
после слова "var" около начала скрипта.
Function ScriptAndAppNames (string sFileName)
If (GetVerbosity() == beginner) Then
SayString(sFileName + " settings are loaded")
else
SayString (sFileName+" Settings")
EndIf
If(GetVerbosity() == beginner) Then
SayString ("The application currently being used is the ")
EndIf
SayString (GetAppFileName ())
SpellString (GetAppFileName ())
EndFunction
Вы можете подумать, что строковый параметр, sFileName, является
дверью, через которую мы можем передать имя текущего файла
скриптов в функцию, когда она вызывается. Параметр sFileName не
равен filename, он более похож на переменную, которая будет
временно хранить имя файла, чтобы имя файла можно было передать
в функцию, которая будет его использовать. Это вызывающее
утверждение будет сформулировано следующим образом:
ScriptAndAppNames ("ApplicationName")
где ApplicationName представляет имя приложения, которое вы
хотите передать в функцию. Этот вызов функции говорит, что
строка (string) "ApplicationName", должна быть передана в
функцию, ScriptAndAppNames, через параметр sFileName. Тогда
функция будет "знать" эту информацию. Следовательно, она может
быть использована в речевых сообщениях, которые содержатся в
утверждениях типа SayString. Здесь информация о параметре
соединяется с фиксированным текстом, чтобы завершить сообщения,
которые будут озвучены во время выполнения.
Давайте возьмем функцию, которую мы написали прежде, SayName, и
переформулируем ее таким образом, чтобы она принимала наше имя в
качестве параметра, вместо того, чтобы иметь наше имя в коде
функции. Выполните шаги, приведенные ниже.
1. Откройте блокнот, через главное меню/программы/стандартные.
2. Откройте диспетчер скриптов, нажав Insert+0, или нажав
Insert+F2, а затем s, а затем Enter. Jaws сообщит вам, что вы
находитесь в NOTEPAD.JSS, исходном файле скриптов для Блокнота.
Выберите New Script из меню Script, или нажмите
клавишу-ускоритель, CTRL+E.
3. Появляется диалог нового скрипта, и теперь мы можем
назвать нашу функцию и написать ее документацию. Когда
появляется диалог нового скрипта, курсор находится в поле
ScriptName (Имя скрипта). Наберите SayName. Убедитесь, что буквы
S и N являются большими, и не вставляйте пробелы между словами.
4. Дважды нажмите клавишу Tab, чтобы переместиться к полю
Synopsis. Наберите слова "Say our Name". (Пропустив блок
проверки Can be Attached to key, и не включив его, мы сообщили
диспетчеру скриптов, что создаем функцию, а не скрипт).
5. Нажмите Tab, чтобы переместиться в поле Description и
наберите слова "The name of the person who wrote this function.".
6. Нажмите Tab, чтобы переместиться в поле Категория, и наберите
слово Test. Поле Категория - это комбобокс, и категорию можно
либо вписать, либо выбрать из уже имеющихся.
7. Нажмите Enter, чтобы переместиться в поле Function Returns
(Возвраты функции) и выберите Void. Мы выбираем Void, потому что
наша функция не возвращает никакой информации в вызывающий
скрипт.
8. Нажмите CTRL+Tab, чтобы переместиться в поле Parameters
(Параметры). Вы окажетесь в поле Existing Parameters
(существующие параметры). Это поле пусто, поскольку еще не
существует никаких параметров.
9. Клавишей Tab переместитесь в поле редактирования New
Parameter (Новый параметр) и наберите "UserName".
10. Нажмите клавишу Tab дважды, пока не попадете в поле
редактирования Description (описание) и наберите "The name of the user".
11. Клавишей Tab переместитесь в список допустимых типов и
выберите String.
12. Клавишей Tab переместитесь к кнопке Add (добавить) и нажмите
пробел, чтобы добавить параметр. Вы вернетесь в поле
редактирования нового параметра, но снова мы его использовать не
будем, поскольку мы добавляем только один параметр. Клавишей Tab
переместитесь к кнопке OK и нажмите Enter.
13. Теперь мы снова находимся в главной текстовой области
диспетчера скриптов, и у нас есть пустая функция, где в первой
строке написано "Void Function SayName (String UserName)", а в
последней строке написано "EndFunction". Мы находимся между
двумя этими строками. Клавишами-стрелками поднимитесь на первую
пустую строку после первой строки и вы готовы к тому, чтобы
написать тело функции.
14. Для этой функции вам понадобится только одна строка, но она
будет немного отличаться от строки, которую мы использовали для
нашего первого скрипта и функции SayName, которую мы писали
прежде. Эта строка будет SayString ("My name is " + UserName),
где UserName является параметром, который передает ваше имя в
функцию. Чтобы вставить эту строку в функцию, нажмите Ctrl+I,
чтобы открыть диалог "Вставить функцию". Затем наберите s, a и
y. Вы должны услышать, как Jaws скажет SayString, имя встроенной
функции, которая была выбрана. Нажмите Enter, чтобы принять эту
функцию.
15. Теперь вам будет предложено ввести строку, которую нужно
озвучивать, или переменную, которая представляет строку.
Наберите "My name +UserName", и не забудьте про кавычки. После
того, как вы нажмете Enter, вы вернетесь в область
редактирования, где ваша функция теперь готова.
16. Теперь у вас на экране должны присутствовать три строки, в
точности такие, как на этой странице. Помните, что близко - это
не очень-то хорошо, поскольку компьютеры ожидают от нас, что мы
будем точными и совершенными. Кроме того, несколько пустых строк
значения не имеют. Jaws игнорирует пустые строки в функциях.
Void Function SayName(String UserName)
SayString ("My name is " + UserName)
EndFunction
17. Теперь нам нужно сохранитть и скомпилировать файл скриптов
для NotePad. Нажмите Ctrl+S, и вы должны услышать "Compile
complete". Если это не так, вернитесь и вновь проделайте все
вышеописанные шаги и попытайтесь еще раз.
Теперь мы создали функцию, которая будет выполнять ту же работу,
что и наша предыдущая функция. Однако, имя, которое нужно
озвучить, не закодировано в функцию, оно передается как
параметр. Эту функцию можно вызывать всякий раз, когда нам нужно
озвучить наше имя. Чтобы вызвать функцию, мы будем использовать
скрипт, сформулированный, как показано ниже.
Script SpeakName ()
SayName ("XXX")
EndScript
Когда вызывается функция SayName, строка "XXX", которая представляет
наше имя, передается в функцию через параметр UserName. Теперь у функции
есть эти данные и она может озвучить его как часть сообщения SayString.
Функции, которые предоставляют возвраты
Теперь давайте рассмотрим функцию, которая предоставляет возврат. Возврат -
это информация, которая посылается обратно из функции в вызывающий
скрипт или в функцию, когда она отрабатывает. Эта возвращенная
информация затем может быть использована вызывающим скриптом или
функцией. Обратите внимание, что тип возвращаемой информации (то есть,
string, Int, Object, handle, или Void) объявляется перед именем функции.
Следующая функция взята из EXCEL.JSS, файла скриптов для Microsoft Excel.
Int Function GetExcelVersion()
var
handle WinHandle
let WinHandle = GetAppMainWindow (GetFocus())
let WinHandle = GetFirstChild (WinHandle)
if (GetWindowClass (WinHandle) == "Excel4") then
return TRUE ;This is Excel 97
else
return FALSE ; this is Excel95 or earlier
EndIf
EndFunction
Вы, вероятно, догадались, что задача этой функции состоит в том, чтобы
определить, находимся мы в Excel 97 или нет. А происходит следующее:
функция выполняет тест, чтобы узнать, находимся ли мы в Excel 97. Если да,
функция возвращает, или посылает обратно, значение True, Истина, обратно в
вызывающий скрипт. Если нет, возвращается значение False, или ложь. Под
возвратом этого значения мы просто имеем в виду, что мы информируем
вызывающий скрипт о результатах определения. Вызывающий скрипт может
потом продолжать и делать что-то другое, в зависимости от того, является
значение True или False, то есть, то есть, находимся ли мы в
действительности в Excel 97 или нет. Вот пример того, как можно вызвать
эту функцию таким образом, чтобы возвращенную информацию можно было
использовать для принятия решения.
If GetExcelVersion== true Then
(Block of statements we want to execute if we're in Excel 97)
Else
(Block of statements we want to execute if we're not in Excel 97)
EndIf
Другими словами, если GetExcelVersion является истинной, то есть, возвращает
True после своего вызова, то мы выполним один набор утверждений. Если она
не является истинной, то есть возвращает после своего вызова False, то мы
выполним другой набор.
Кстати, вам пора выучить сокращение, которое авторы скриптов часто
используют в таких ситуациях, как эта. Следующее утверждение немного
короче, чем If GetExcelVersion== true Then, но оно означает абсолютно то же
самое.