Всё, что вы хотели знать о написании скриптов для JFW, но не знали, кого спросить

(Переработанный и дополненный вариант)
Источник:www.tiflocomp.ru
Дата публикации:2004
Twitter Facebook Vkontakte

Часть II. Создаём сложные файлы скриптов

Использование переменных

Ранее мы уже рассказали о том, какие переменные допускаются в языке Jaws и как их объявлять. В этом разделе мы обсудим, когда ими пользоваться, порекомендуем некоторые соглашения об именах и покажем, где их нужно помещать в вашем файле скриптов.

Соглашения об именах

Это щекотливый вопрос. У каждого есть свое мнение, и эти мнения часто не совпадают. Независимо от того, какого соглашения об именах вы придерживаетесь, использование такового соглашения предотвратит напрасную трату времени и раздражающие ошибки. Принимая стандарты и придерживаясь их, вы гарантируете себе, что сможете вернуться к этому коду позже и с легкостью изменить или отладить его. Мы (подразумевается Freedom Scientific - прим. сост.) проводим много времени среди инвалидов , обсуждая стандарты. У вас есть шанс внести свою лепту. Давайте рассмотрим некоторые рекомендации о создании вашего стандарта. Что должно быть в имени? Очень многое. Имеет смысл выбирать описательное имя. Самое простое - назвать свою переменную, сложив вместе описательные слова. Постарайтесь не делать имя слишком длинным, поскольку вам придется набирать эти имена, и иногда довольно много. Если вы называете глобальную переменную,начните ее имя с G_ (заглавная латинская G и символ подчеркивания) или Global. Вы также должны начинать с заглавной буквы каждое слово, когда будете соединять их вместе, чтобы Jaws смог правильно прочитать эти слова, предполагая, что опция Mixed Case (Смешанный регистр) включена в диспетчере конфигурации. Вы могли бы продолжить это и использовать Int, Str, Obj, и HND в именах, чтобы пометить переменные String, Object, Integer и Handle. Таким образом, G_Int_VariableName будет глобальной переменной типа Integer, а Str_VariableName будет локальной переменной типа String.

Где объявлять переменную

Глобальные переменные, которые используются в нескольких скриптах в вашем файле, нужно объявлять в начале файла, сразу же после операторов Include. Вы показываете начало объявления глобальных переменных, поместив на отдельной строке слово "Globals". Затем вы помещаете каждое объявление на отдельной строке. Сразу же после переменной ставится запятая, за исключением последней переменной в списке. В конце объявления добавьте комментарий, поясняющий, как используется эта переменная. Позже вы можете обратиться к этой области файла за информацией о любой переменной, с которой вы столкнулись.

Единственный случай, когда переменная объявляется внутри скрипта, когда переменная является локальной. Помните, что локальная переменная испоьзуется только в скрипте, где она определена, тогда как глобальная переменная может быть использована в любом скрипте в файле. Локальную переменную следует объявлять на первой строке скрипта, сразу же после заголовка скрипта.

Использование глобальных переменных

Помните, что переменные, которые вы намерены использовать в нескольких скриптах, объявляются как глобальные. Кроме глобальных переменных, которые вы определили для своего собственного использования, существует набор стандартных глобальных переменных Jaws, что очень полезно для создания скриптов. Эти переменные содержатся в файле HJGLOBAL.JSH, и вы можете ими пользоваться, поставив оператор include для этого файла в ваш собственный файл скриптов. Потратьте некоторое время на просмотр глобальных переменных, определённых в HJGLOBAL.JSH, поскольку они часто используются в скриптах по умолчанию. Там есть описания того, как использовать каждую из них. Помните, что значения, которые хранятся в этих переменных, часто модифицируются скриптами по умолчанию. Поэтому, если вы включите HJGLOBAL.JSH в свой файл скриптов, вы можете вызывать эти переменные, чтобы получать необходимую информацию по мере надобности. Например, проверка содержимого переменной GlobalMenuMode сообщит вам, находитесь ли вы на линейке меню или в меню. Здесь мы просто хотим сказать, что переменные, объявленные в файле HJGLOBAL.JSH постоянно используются скриптами по умолчанию в Jaws, и если вы их выучите и поймете, как ими пользоваться и будете включать их в свои собственные файлы скриптов для приложений, вы сможете вызывать значения, которые они содержат, во время выполнения своих собственных скриптов.

Также стоит упомянуть, что однажды определив глобальную переменную и присвоив ей значение в одном из ваших приложений, это значение сохраняется в памяти, даже после того, как вы закроете это приложение. Если вы потом снова откроете приложение, глобальные переменные, которые вы определили, по-прежнему будут иметь те же значения. Единственный способ, с помощью которого можно по-настоящему очистить эти глобальные переменные, состоит в том, чтобы закрыть, а потом снова загрузить Jaws.

Использование констант

Помните, что константа - это просто метка, представляющая число или строку символов, так чтобы код скрипта было легче читать и понимать. Вам следует включать файл со стандартными константами, HJCONST.JSH, в каждый свой файл скриптов, и использовать имеющиеся там константы всякий раз, когда только можно. Давайте потратим немного времени, чтобы просмотреть эти константы. Файл разбит на следующие группы:

Коды типов окна и коды подтипов - эти коды закреплены за типами окон. Помните, что даже элемент управления самого нижнего уровня квалифицируется как окно. Следовательно, каждое окно будет возвращать код типа, если его запросить. Кнопка будет возвращать код типа 1, или имя своей константы, WT_BUTTON. Существуют две функции для получения такой информации, GetWindowTypeCode и GetWindowSubtypeCode.

Рассмотрим следующее утверждение If-Then из скрипта PriorCharacter в DEFAULT.JSS. Это скрипт, который отрабатывает, когда нажимается стрелка влево. Ветвь Else этого оператора If работает, когда нет видимого PC курсора. Эта ветка предназначена для того, чтобы проверять, не находимся ли мы в меню. После каждого раздела кода мы добавили комментарии, где описано его назначение.

If CaretVisible() Then ; Если PC курсор виден
SayCharacter() ; Сказать символ, на котором он находится
Return ; Завершить работу скрипта
Else ; Если PC курсор не виден 	
; установить переменную Integer для кода типа текущего окна
Let TheTypeCode = GetWindowSubtypeCode (GetCurrentWindow())
If (TheTypeCode == WT_MENU) Then ; Если текущее окно меню
SayString (msg3) ;"Menu"
SayWindow (GetCurrentWindow(), READ_HIGHLIGHTED) ; Озвучить текущий пункт Return ; Завершить работу скрипта 	
EndIf
EndIf

А происходит следующее: скрипт решает, что озвучивать, в зависимости от кода подтипа окна, в котором мы находимся. Из этого следует, что этот набор констант и ассоциированные с ними числовые коды являются очень важными для пользователей Jaws, поскольку именно отсюда мы узнаем, с каким типом элемента управления мы имеем дело. Вы можете пожелать просмотреть эту группу констант в HJCONST.JSH, они все начинаются с WT_ (Window Type).

Идентификаторы атрибутов текста - используются для сравнения текстовых атрибутов. Все они начинаются с ATTRIB_ (Attribute).

Константы общего назначения - сюда входят типы поиска строк и графики, которые начинаются с S_, True, False, On и Off.

Режимы вывода - они еще не реализованы.

Режимы брайля и типы маркировки - все они начинаются с BRL_.

Настройки многословия - сюда входят константы, устанавливающие уровень проговаривания для различных пользователей (BEGINNER, INTERMEDIATE, ADVANCED).

Общие - сюда входят тесты на активность и успех, курсоры, различные настройки чтения, и установки опций.

Типы курсоров - это для различных форм указателя мыши. Например, если вы получаете код окна CT_Waitas, то видны песочные часы.

Разное - и наконец, мы имеем константы, используемые для статуса меню, операционной системы и текущего файла по умолчанию.

Все категории констант, описанных выше, как уже было указано, относятся к файлу заголовков HJCONST.JSH, который поставляется с Jaws. Нам не хотелось, чтобы у вас создавалось впечатление, что это единственные доступные вам константы. Конечно, вы можете и должны создавать свои собственные константы, или объявляя их где-нибудь в начале файла скриптов, или помещая их во включенный файл заголовков. Использование констант, где это возможно, облегчает понимание файлов скриптов и делает возможным изменение значений константы в любом месте файла, просто изменив одно объявление. Это гораздо легче, чем изменять значение в каждом месте, где оно появляется в файле.

Домашнее задание # 8

Предположим, вы хотите написать скрипт для приложения, которое называется SPAMKILLER.EXE. Вы будете использовать файл заголовков, файл сообщений, и два файла с глобальными переменными и константами HJ. Также вам понадобится определить три дополнительных глобальных переменных, которые будут называться GlobalSpamInteger, GlobalSpamString и GlobalSpamHandle и три дополнительных константы, заданных как SpammerOne =1, SpammerTwo = 2, и SpammerThree = 3 внутри файла скрипта. Покажите начало файла скрипта со всеми утверждениями, которые все это сделают.

Использование нескольких функций

Иногда нужно связать вместе несколько функций, чтобы достичь цели. Другие ситуации требуют "вложенных" функций, где одна функция становится параметром для другой, которая, в свою очередь, является параметром еще одной. Внутри кода это может выглядеть запутанным. Фокус в том, чтобы правильно сосчитать скобки. Они покажут вам, как функции вложены внутри друг друга. Сначала мы рассмотрим группу функций, связанных вместе ради единой цели, а затем мы рассмотрим вложенные функции.

Последовательное применение функций

Достаточно редко удается решить задачу с помощью одной функции. Обычно требуется несколько функций в соответствующем порядке. Следующий код взят из файла скриптов для Visual Basic 4.0, и его задача состоит в том, чтобы проверить, является ли панель инструментов окном с фокусом, и если нет, сделать его таковым и поставить Jaws курсор на первый ярлык. Кстати, мы использовали утилиту Home Row, чтобы узнать класс окна панели инструментов, палитры инструментов, прежде чем написали этот скрипт.

Script GoToToolBox()
; Этот скрипт передает фокус на панель инструментов и помещает Jaws курсор
; на первый инструмент панели инструментов
SayString ("Tool Box") ; Пусть пользователь знает, что происходит
While GetScreenEcho() != 2 ; Прокручивает через эхо экрана, пока не будет установлено значение "Все"
ToggleScreenEcho () ; увеличивает эхо экрана
EndWhile
If GetWindowClass (GetFocus ()) != "ToolsPalette" Then ;Если мы уже не на панели инструментов
PCCursor();
{ALT+V} ; Меню View
Pause() ; Время, чтобы появилось меню
{x};
; Выбрать панель инструментов
EndIf
Delay(10) ; Время, чтобы появилась панель инструментов
RouteJAWSToPC()
JAWSCursor()
JAWSPageUp()
JAWSHome()
PerformScript ({DOWN ARROW}) ; Обычная стрелка вниз со специальным заданием для панели инструментов
EndScript

Сначала мы убеждаемся, что находимся в режиме экрана "Say all". Затем мы проверяем, не находимся ли мы уже на панели инструментов, получая класс окна, где находится фокус, и сравнивая его со строкой, ToolsPalette, которая является известным классом окна для панели инструментов. (Этот класс окна должен был быть определен в файле включения для констант для данного файла скриптов). Если мы не находимся в панели инструментов, мы должны передать фокус этому окну, выполнив несколько функций, которые могут гарантировать конечный результат. Мы используем функцию PCCursor, чтобы активизировать PC курсор. Мы используем симуляцию клавиатуры, чтобы послать в приложение Alt+V. Появляется меню View. Помните, что все, что находится в фигурных скобках, передается приложению, как если бы вы набрали это с клавиатуры. Обратите внимание, что там есть комментарий, чтобы каждый, кто будет читать, знал, в чем назначение {Alt+V}. Затем функция Pause дает системе время показать меню, прежде чем мы продолжим. Мы используем симуляцию клавиатуры, чтобы послать в приложение X, которая является клавишей быстрого запуска для пункта меню "Панель инструментов" (Toolbox). Это тоже прокомментировано. Затем EndIf завершает нашу If-Then последовательность. Теперь мы уверены, что панель инструментов открыта и этому окну передан фокус. Затем мы активизируем Jaws курсор и устанавливаем его на первую кнопку.

Чтобы решить нашу задачу, мы использовали последовательно несколько функций.

Использование вложенных функций

А вот пример скрипта с вложенными функциями, где функции служат параметрами для других функций.

Script IsJAWSWindow()
 If (GetWindowClass (GetAppMainWindow (GetFocus())) == JFWUI2) Then
SayString (msg113) ;"This is the JAWS application window"
EndIf
EndScript

Мы можем узнать, что класс окна для окна Jaws JFWUI2 перейдя в окно Jaws и включив функции Home Row. Использование Shift+F2 переведет нас в родительское окно, а F3 будет прокручиваться через режимы вывода, пока мы не найдем класс. Затем F1 озвучит класс, который будет JFWUI2. Мы хотим сравнить наш класс окна с ним, но сначала мы должны убедиться в том, что наш скрипт ищет в нужном месте. Мы используем функцию GetWindowClass чтобы запросить класс окна. Ее параметром является дескриптор окна (Window Handle), поэтому мы даем ей AppMainWindow, которое является родителем в текущем приложении. Мы используем это, потому что Jaws является приложением, и мы хотим проверить класс окна этого приложения. AppMainWindow требует дескриптор окна в качестве параметра, поэтому функция знает, какое приложение проверять. В нашем случае мы используем функцию GetFocus, которая возвращает дескриптор окна для окна, в котором находится фокус ввода.

Домашнее задание # 9

Давайте еще раз вернемся к диалогу открытия файла в приложении WordPad. Откройте этот диалог и осмотритесь,. чтобы освежить свою память. Напишите скрипт, который будет определять, находитесь ли вы в этом диалоге. Если да, пусть ваш скрипт скажет "В диалоге открытия". Затем определите, находится ли фокус в окне редактирования имени файла. Если да, пусть скрипт также скажет "и в поле имени файла". Однако, если фокус находится на другом элементе управления, пусть скрипт вместо второго сообщения скажет "но не в поле имени файла". И наконец, если фокус даже не в окне открытия файла, пусть скрипт скажет "не в окне открытия файла".

Совет: диалог открытия файла - это действительное окно. Вспомните, что это означает, что это окно, у которого есть заголовок. Используйте этот факт, чтобы определить, находитесь ли вы в диалоге открытия файла. Используйте класс окна вашего текущего элемента управления, чтобы определить, находится ли фокус на поле имени файла. Второй совет: обратите внимание на функцию GetRealWindow в приложении C.

Выбор курсора и манипуляции с ним

Прежде чем вы попытаетесь прочитать что-нибудь на экране с помощью скрипта, есть смысл просмотреть некоторую информацию о курсорах, о чем мы уже говорили прежде. Существует три типа курсора: PC курсор, Jaws курсор и невидимы й курсор. Если вы редактируете или вводите текст, PC курсор будет находиться там, где будут появляться символы, которые вы будете набирать. (Эта форма курсора редактирования или вставки также называется курсор каретки). Однако, когда вы работаете в меню или клавишей Tab перемещаетесь по опциям,например по кнопкам в окне диалога, PC курсор является фокусом. Если вы хотите прочитать другие области окна или прочитать часть экрана, куда не может попасть PC курсор, вы можете переключиться на Jaws курсор. Jaws курсор можно двигать куда угодно в рамках текущего действительного окна, что делает возможным исследование тех областей экрана, куда PC курсор попасть не может. Поскольку Jaws курсор всегда перемещает за собой указатель мыши, указатель мыши также позиционируется, и им можно щелкнуть в том месте, где находится Jaws курсор, если вы решили это проделать. Третий вид курсора называется невидимый курсор, и в одном отношении он похож на Jaws курсор, поскольку его перемещение ограничено только рамками действительного окна, но он не имеет видимого воплощения на экране и он не таскает за собой указатель мыши.

Как же нам пользоваться этими курсорами? Было бы непрактичным, а зачастую и невозможным исследовать экран с помощью PC курсора. Поэтому, прежде чем прочитать какой-нибудь текст в окне, мы обычно сначала переключаемся на один из оставшихся курсоров. Можно использовать как Jaws, так и невидимый курсор, чтобы выполнять функции чтения, поэтому до некоторой степени это просто вопрос предпочтения. Однако, если вы намерены щелкнуть мышью или предпринять другие действия с применением мыши, необходимо будет воспользоваться Jaws курсором. Поскольку указатель мыши сопровождает Jaws курсор в его путешествиях, щелкнуть мышью оказывается очень просто, поскольку она будет уже в нужной позиции. Если вы не хотите перемещать Jaws курсор с его текущей позиции, или нигде щелкать не надо, лучшим выбором будет невидимый курсор. На ум приходит одна конкретная ситуация, когда вы уж точно не захотите перемещать "Jaws курсор/указатель мыши. Иногда в приложении Windows информационный текст будет появляться где-то на экране, обычно в строке состояния, когда указатель мыши будет находиться в каком-нибудь конкретном месте. Если вы переместите Jaws курсор чтобы прочитать текст, с ним переместится и указатель мыши и текст исчезнет. В такой ситуации чтобы прочитать текст, придется воспользоваться невидимым курсором.

В некоторых случаях необходимо переместить один из курсоров, например Jaws курсор, даже если вы хотите, чтобы после окончания работы скрипта он вернулся в первоначальное положение. Для этого существуют функции сохранения и восстановления, которыми вы можете воспользоваться, чтобы после окончания скрипта все было так, как было до начала работы скрипта.

Ниже приводится список функций, с помощью которых можно выбирать курсоры и манипулировать ими.

  • PCCursor() - активизирует PC курсор.
  • JAWSCursor() - активизирует Jaws курсор.
  • InvisibleCursor() - активизирует невидимый курсор.
  • BrailleCursor () - активизирует брайлевский курсор.
  • RouteBrailleToPc () - перемещает брайлевский курсор к PCC курсору.
  • RouteBrailleToJAWS () - перемещает брайлевский курсор к Jaws курсору.
  • RouteJAWSToBraille () - перемещает Jaws курсор к брайлевскому курсору.
  • RoutePCToBraille () - перемещает PC курсор к брайлевскому курсору.
  • RoutePCToJAWS() - перемещает PC курсор к Jaws курсору.
  • RouteJAWSToPC() - перемещает Jaws курсор к PC курсору.
  • RouteJAWSTo Invisible() - перемещает Jaws курсор к невидимому курсору.
  • RouteInvisibleToPC() - перемещает невидимый курсор к PC курсору.
  • RouteInvisibleToJAWS() - перемещает невидимый курсор к Jaws курсору.
  • SaveCursor() - сохраняет активный курсор и его позицию.
  • RestoreCursor() - снова активизирует сохраненный курсор и восстанавливает его первоначальную позицию.

Следующая группа функций используется для перемещения курсора.

  • PriorCharacter() - перемещает активный курсор на предыдущий символ.
  • PriorWord() - перемещает активный курсор к предыдущему слову.
  • PriorLine() - перемещает активный курсор на предыдущую строку.
  • NextCharacter() - перемещает активный курсор к следующему символу.
  • NextWord() - перемещает активный курсор к следующему слову.
  • NextLine() - перемещает активный курсор на следующую строку.
  • JAWSHome() - перемещает активный курсор в начало строки.
  • JAWSEnd() - перемещает активный курсор в конец строки.
  • JAWSPageUp() - перемещает активный курсор к верхнему краю окна
  • JAWSPageDown() - перемещает активный курсор к нижнему краю окна.
  • MoveTo - перемещает невидимый или Jaws курсор в координаты окна, указанные пользователем.
  • MoveToControl - перемещает активный курсор к конкретному элементу управления в окне. Если при вызове этой функции активным является PC курсор, автоматически включается Jaws курсор. В противном случае используется активный курсор.
  • MoveToFrame - перемещает активный курсор в левый верхний угол указанного фрейма. Если при вызове этой функции активным является PC курсор, автоматически включается Jaws курсор, который и перемещается в новую позицию. В противном случае используется активный курсор.
  • MoveToGraphic - перемещает Jaws курсор, невидимый курсор или брайлевский курсор в указанном направлении, чтобы найти графический символ в активном окне.
  • MoveToWindow - перемещает активный курсор в указанное окно. Если окно содержит текст, курсор позиционируется на первый символ, в противном случае он позиционируется в центре окна. Если при вызове этой функции активным является PC курсор, то активизируется Jaws курсор, который и перемещается в новую позицию.
  • PriorChunk - перемещает активный курсор к предыдущей цепочке текста. Цепочка текста - это раздел или блок текста, который пишется на экране за один раз.
  • NextChunk - перемещает активный курсор к следующей цепочке текста. Цепочка - это раздел или блок текста, который пишется на экране за один раз.

Обратите внимание, что если ваша задача состоит в том, чтобы прочитать что-нибудь на экране, то после функций перемещения обычно следуют какие-нибудь Say функции. Вот пример сохранения текущего курсора, переключения курсора, перемещения курсора прочтения некоторого текста и п следующего возвращения в первоначальную позицию с первоначальным курсором.

Script ReadBottomLine()
Var ;Объявляем локальные переменные
Int TheTypeCode ;переменная TheTypeCode типа Integer
;узнаем, в окне какого типа находимся и присваиваем код типа окна переменной TheTypeCode
Let TheTypeCode = GetWindowSubtypeCode (GetCurrentWindow())
SaveCursor() ; сохраняем текущий курсор и его позицию
InvisibleCursor() ; Переключаемся на невидимый курсор
RouteInvisibleToPC() ; Перемещаем невидимый курсор к PC курсору
If (TheTypeCode == WT_MENU) Then ; Если мы в меню
MoveToWindow (GetAppMainWindow (GetCurrentWindow())) ; Перефокусироваться на главное окно
JAWSPageDown () ; Перейти на нижнюю строку
JAWSHome() ; перейти в самую левую позицию.
NextWord() ; Перейти на слово вправо.
SayChunk() ; Озвучивает цепочку текста, которая была написана на экране
Else
JAWSPageDown() ; Перейти в нижний край
SayLine() ; Прочитать строку
EndIf
RestoreCursor() ; Вернуться к первоначальному курсору и восстановить его позицию
EndScript

Этот скрипт озвучивает нижнюю строку окна. Обычно там находится строка состояния. PC курсор в это место попасть не может, поэтому мы должны переключиться на невидимый курсор и прочитать строку с его помощью. Обратите внимание, что перед тем, как предпринять это действие, используется функция SaveCursor, а после - функция RestoreCursor. Таким образом, после чтения строки состояния все стало точно так же, как было перед этим. Этот скрипт использует код подтипа окна, чтобы определить, в каком типе окна мы находимся, и, какое утверждение скрипта надо использовать чтобы прочитать то, что нам нужно.

Посылка нажатий клавиш

Если вам нужно послать нажатие клавиши или комбинации клавиш из скрипта (то есть, если вы хотите, чтобы скрипт ввел эти клавиши, точно также, как если бы вы сами ввели их с клавиатуры), поместите название клавиши в фигурные скобки. Например, {CONTROL+H} пошлет в систему Ctrl+H. Этот способ также можно использовать, чтобы посылать буквенно-цифровые символы. Таким образом, {h} пошлет в приложение, с которым вы работаете, букву H. Каждая буква, которую вы намерены послать, должна иметь свой собственный набор фигурных скобок. Если вам нужно послать больше, чем пару символов, вы можете воспользоваться функцией TypeString, которая сразу пошлет всю строку символов в приложение.

Синхронизация документации

После того, как вы внесли какие-либо изменения в файл скриптов, особенно редактирование, которое включает добавление или удаление скриптов, путем вставки их откуда-то еще, или путем их выделения и удаления, было бы неплохо синхронизировать документацию. Каждый скрипт должен иметь соответствующую ему строку документации в файле с тем же именем и с расширением .JSD. У вас, конечно, запрашивалась эта информация, когда вы создавали новый скрипт. Но при редактировании могут появиться скрипты, у которых нет документации, или документация для скриптов, которые больше не существуют. Вот почему в меню Файл диспетчера скриптов имеется пункт Синхронизировать документацию. Ниже приведены шаги, которые предпринимает диспетчер скриптов, когда вы выбираете этот пункт меню.

  1. Диспетчер скриптов просматривает в файле >JSD строки для каждого скрипта в >JSS файле и добавляет пустые строки для каждого скрипта, у которого отсутствует документация. (вы должны просмотреть все скрипты, которые, как вам кажется, имеют пустые строки, и ввести соответствующий синопсис и описание после процесса синхронизации). Вы заметите, когда появится диалог документации, что если в файле скриптов вашего приложения есть скрипт с тем же именем, что и в файле скриптов по умолчанию, документация из скрипта по умолчанию была помещена в поля для вашего скрипта. Вам может понадобиться изменить эту документацию, чтобы привести в соответствие с тем, как ваш скрипт или функция работают в данном приложении.
  2. Диспетчер скриптов проверяет .JSD файл на наличие строк документации, которым больше не соответствует никаких скриптов в .JSSS файле и спрашивает, хотите ли вы удалить строки документации.

Команда синхронизации также очень полезна, когда вы вставляете скрипт в файл скриптов из другого файла скриптов. Процесс будет использовать те же методы, которые были описаны выше, чтобы вставить пустые строки в файл документации для вставленных скриптов. В эти строки необходимо будет вписать соответствующую информацию.

Использование процесса синхронизации гарантирует, что ваши скрипты и документация к ним всегда будут текущими. Помните, что Jaws использует синопсис и описание для помощи по клавиатуре, когда пользователь нажимает соответствующие клавиши для вашего скрипта. Поэтому надлежащее внимание к документации поможет всем пользователям ваших скриптов.

Отладка

Об отладке программ написаны целые тома. Самое важное, что нужно запомнить, это то, что здесь требуется совершенно другой склад ума, чем для обычной диагностики. Диагностика проблемы обычно начинается с утверждения, что нечто, с чем вы работаете, однажды работало, а теперь испортилось. Следовательно, если вы просто проследите логику от начала до конца, вы найдете испорченную часть. Отладка чего-то, что еще не работало, означает, что вы даже не можете предположить, что сам ход правилен. А как это относится к отладке наших файлов скриптов? Ну, это просто. Не предполагайте, что только потому, что вы задумали, что все пойдет именно так, так оно и пойдет. Jaws может не всегда думать в точности так, как вы, или, да простят меня небеса, вы можете пропустить какие-нибудь жизненно важные утверждения. Один из самых полезных методов обнаружения логических ошибок заключается в том, чтобы просматривать скрипт строка за строкой, представив, что вы - компьютер. Делайте в точности то, что велит делать скрипт, а не то, что, как вам кажется, вы получили сделать компьютеру. К своему удивлению, вы можете заметить, что на самом деле вы дали инструкции, которая совершенно отлична от той, которую вы намеревались дать. Исправьте все ошибки, которые вы заметили, а затем продолжайте просматривать скрипт, проверяя каждое утверждение на тот предмет, в действительности ли оно выполняет то, что вы задумали. Вот некоторые другие инструменты, которые могут вам помочь в ваших усилиях по отладке скриптов.

Компилятор скриптов Jaws

Первая большая помощь - сам компилятор скриптов. Он проверяет синтаксис ваших утверждений и убеждается в том, что вы правильно завершили каждую последовательность. Когда вы пытаетесь скомпилировать скрипт с ошибкой, он выдает сообщение об ошибке. Те из вас, кто в прошлом писал макросы для Jaws, заметят, ошибки компилятора для скриптов стали более описательными. Уберите диалог об ошибке, и курсор будет помещен в скрипт рядом с ошибкой, или туда, где, по мнению компилятора, находится ошибка. Вы должны понимать, что компилятор может не всегда точно знать, где ошибка. Если вы используете несколько утверждений If-Then, которые, например, вложены, и вы забыли написать нужное количество утверждений EndIf, компилятор покажет ошибку, но курсор не обязательно будет поставлен именно туда, куда нужно вставить недостающее утверждение EndIf. Курсор может находиться на расстоянии нескольких строк от этого места. Компилятор только может вам сказать, что ваши циклы If-Then не сформулированы должным образом, и что после оператора If должен следовать оператор EndIf. Вам придется самим узнавать, куда нужно вставить недостающее утверждение.

Include файлы проверяются, когда они включаются. Всегда ставьте оператор Include в своем файле скриптов прежде, чем вы воспользуетесь чем-нибудь из включенного файла. Например, вы должны включить HJCONST.JSH прежде чем воспользуетесь какой-нибудь константой оттуда. Конечно, если вы располагаете свой файл скриптов как положено, все включения будут примерно в начале файла скриптов.

Ошибочная деятельность

Под ошибочной активностью мы будем подразумевать, что скрипт работает (то есть, он был скомпилирован должным образом), но работает не так, как предполагалось. Если ваш скрипт файл компилируется без ошибок, пора проверить его в предполагаемой среде. Перед тестированием нет необходимости перезапускать Jaws, если только вы не модифицировали файл скриптов по умолчанию. Просто переключитесь на приложение и тестируйте. Вот несколько советов, которые могут облегчить процесс тестирования:

Фрагменты: когда это возможно, компилируйте фрагменты отдельно и тестируйте, чтобы посмотреть, работают ли они сами по себе.

Сообщения: в ключевых точках вашего кода можно вставлять сообщения, чтобы Jaws сообщал, что он делает. ВЫ можете вставить сообщения SayString в ключевых точках скрипта чтобы посмотреть, действительно ли они выполняются, когда вы предполагаете это. Ряд таких сообщений, которые выдают несколько различные сообщения, могут быть весьма информативными в том, чтобы помочь вам расшифровать, если код выполняется в том порядке, в каком вы задумали, и ветвление происходит корректно. Например, сообщения SayString в каждой ноге утверждения If-Then проинформируют вас, какая нога выполняется. Вы также можете использовать функцию SayInteger, чтобы она информировала вас о значениях целочисленных переменных и о том, как эти значения изменяются в ходе выполнения скрипта. Вы можете обнаружить, что эти переменные имеют не те значения, которые вы ожидали, в некоторых точках выполнения скрипта. Функция SayInteger также может оказаться полезной в том, чтобы помочь вам отслеживать значения целочисленных переменных во время выполнения цикла While.

Многие ошибки выполнения можно проследить до сбоя, чтобы сохранить и восстановить состояния, должным образом. Это относится к состояниям курсора, состояниям эха экрана, состояниям подробности и т.д. Всегда, когда вам нужно изменить состояние для ваших задач, убедитесь, что вы возвращаетесь в первоначальное состояние. Например, изменение эха экрана на "Все", так чтобы вы могли всегда слышать подсказку, это конечно здорово, но не оставляйте систему в таком состоянии поскольку это может запутать пользователя.

Отладочные скрипты: вы можете создавать отладочные скрипты, которые будут сообщать всю необходимую информацию, такую, как активный курсор, что содержится в переменных и различные свойства окон. Вот пара скриптов, которые вы можете скопировать и вставить в свой файл скриптов и изменить их,чтобы они сообщали необходимую информацию.

Script SayVars ()
SayString( MyVariable) ; Наберите имя своей переменной
; Скопируйте предыдущую строку для каждой своей переменной
EndScript

Script WindowInfo ()
SayString( GetWindowClass (GetFocus ())) ; Класс окна с фокусом
SayString ( GetWindowClass (GetParent (GetFocus ()))) ; Класс окна для родительского окна
UtilitySayInfoAccess() ; Название элемента управления
EndScript

Взаимодействие ваших скриптов с функциями событий: вы должны иметь в виду, что у Jaws имеются функции событий, которые представлены в файле скриптов по умолчанию, которые могут срабатывать автоматически во время работы приложения. Эти функции событий могут взаимодействовать неожиданным образом со скриптами, которые вы пишете. Например, вы можете поместить функции чтения в свой скрипт, чтобы прочитать определенные части экрана в определенных ситуациях, только для того, чтобы узнать, что информация озвучивается дважды. Вероятно, это означает, что одна из функций событий, как, например, функция NewTextEvent или функция событий FocusedChanged была вызвана, чтобы озвучить текст автоматически, а ваш скрипт озвучивает этот текст во второй раз. Вы не найдете решение этой проблемы, просто анализируя свой скрипт, поскольку это не ваш скрипт озвучивает информацию дважды. Вот почему вам так важно четко понимать, что делают функции событий и когда они будут вызваны приложением.

Домашнее задание # 10

Приведенный скрипт содержит ошибки на каждой строке. Найдите ошибки и перепишите скрипт правильно.

Script SayDefaultButton (Int Button )
vars 	
string DefaultButtonName,
if (DialogActive ()) 	
let DefaultButtonName == GetDefaultButtonName 	
if (DefaultButtonName != " ") then 		
if (GetVerbosity () = 0) then 			
SayString ("msg70") ;"default button is" 		
EndIf () 		
SayString (DefaultButtonName)) 	
Else
SayString (msg444) : "Can not determine default button in this dialog box " 	
EndIf
Else () 	
SayString (msg71 ;"not in a dialog box"
EndIf ()
End Script (cont)
Стратегия атаки на новые приложения

Когда вы впервые открываете новое приложение, особенно то, которое не является дружественным к речевому доступу, может оказаться весьма затруднительным решить, как изучить расположение приложения и как приспособить его для лучшего доступа. Это руководство познакомило вас с инструментами создания скриптов, которые помогут вам проделать это. Одна стратегия подхода к таким приложениям показана в приложении E. Там вы найдете некоторые идеи о том, как подходить к проблеме анализа и создания скриптов для нового приложения, в комбинации с использованием других возможностей Jaws, таких, например, как использование фреймов.

Рекомендации для создания дистрибутивных файлов скриптов

Мы уже порекомендовали кучу правил для соблюдения, когда создавали файлы скриптов, такие, как использование подробных комментариев и тщательное заполнение форм документации к скриптам. Конечно, это только рекомендации, и никто не может принудить вас соблюдать эти правила. Однако, если вы намерены передавать свои файлы скриптов в Henter-Joyce для возможного включения в будущие версии Jaws, необходимо соблюдать несколько обязательных правил. Эти правила приведены ниже.

Имена переменных: используйте осмысленные имена переменных, после которых вставляйте комментарий, когда имя является недостаточно описательным.

Комментарии: вставляйте комментарии сразу же после начала каждого скрипта или функции, описывающие его назначение. Комментарии также необходимо вставлять в сложные утверждения, где задача не всегда очевидна, такие, как сложные утверждения типа If-Then-Else.

Сообщения: все озвучиваемые или брайлевские сообщения должны помещаться в файл сообщений для текущего приложения, где скрипт может к ним обращаться. Эти сообщения никогда не должны помещаться в кавычках после SayString в самом .JSS файле. Соблюдение этого правила делает перевод сообщений на другие языки куда проще.

Документация к скриптам: заполняйте поля Синопсис и Описание (Description) в диалоге "Новый скрипт". Они должны заполняться точно и полностью, поскольку они используются в помощи по клавиатуре, вызываемой по Insert+F1. Например, в скрипте SayTextAndAttributes, вы найдете следующий синопсис и описание:

Синопсис: озвучивает изменения в атрибутах, когда читает текст в активном окне.

Описание: читает видимый текст в активном окне не перемещая курсор. Когда попадаются изменения атрибутов, ОНИ СООБЩАЮТСЯ.

Убедитесь, что ваш файл скриптов включает настроенные версии скриптов HotKeyHelp, ScriptFileName, и, если необходимо, ScreenSensitiveHelp.

Преобразование файлов макросов

Диспетчер скриптов можно использовать, чтобы преобразовать файлы макросов, которые вы создавали для версий Jaws старше 3.0. Далее приводятся шаги, которые предпринимает диспетчер скриптов, чтобы переконвертировать файлы макросов в файлы скриптов.

  1. Сначала диспетчер скриптов потребует от вас некоторого ввода. Когда в меню Файл вы выбираете пункт Импортировать макрофайл, вы должны будете ввести имя файла макросов. Диспетчер скриптов использует эту информацию для определения пути и имени файла, который получится в результате. Вы также должны будете выбрать среду, для которой создавался макрофайл: Desktop, Laptop или оба сразу.
  2. Диспетчер скриптов создаст пустой файл скриптов, основываясь целевом пути и имени файла.
  3. Файлы включения обрабатываются следующим образом: файл сообщений копируется в целевую директорию, переименовывается, получая расширение .JSM, и в .JSS файл добавляется оператор Include.

Макросы в Include файлах перемещаются в .JSS файл и конвертируются. Процедура конвертирования следующая: Если есть раздел определения глобальных переменных или констант в Include файле, создается .JSH файл и все это переносится туда. В .JSS файл добавляется оператор Include для этого файла.
Макросы конвертируются следующим образом: если соответствующая клавиша обнаруживается в файле раскладки клавиатуры по умолчанию, основываясь на выбранной среде, скрипту присваивается соответствующее имя.
Если соответствующая клавиша будет найдена в разделе "Старые клавиши" файла раскладки клавиатуры по умолчанию, макрос конвертируется в функцию Jaws с соответствующим именем.
Если соответствия не найдено, скрипту присваивается имя имени файла, после которого идет номер.
Создается файл раскладки клавиатуры, с присвоениями, основанными на первоначальных нажатиях клавиш. Макросам, которые конвертированы в определяемые пользователем функции, клавишных команд не присваивается, но после имени функции помещается комментарий, с первоначальным макронажатием клавиши.
Каждое PerformMacro конвертируется в PerformScript, если только вызванный макрос не был переконвертирован в функцию Jaws. В этом случае PerformMacro конвертируется в вызов функции.
Файл скриптов, который получается в результате, открывается в диспетчере скриптов.

Предыдущая версия Jaws требовала пробелов между кавычками для обозначения нулевого значения. В текущей версии нулевые значения обозначаются просто двумя кавычками без пробелов. Если ваш файл макросов содержал такие тесты на нулевое значение, вам придется убирать пробелы между кавычками вручную.

Последнее, что вы должны сделать, это просмотреть скрипты, изменить имена, если это необходимо, и написать документацию для каждого скрипта. Если у вас были макросы, служившие в качестве функций, сконвертируйте их в определяемые пользователем функции. Затем скомпилируйте новый файл скриптов.

Примечание: если вы вносите обширные изменения в скрипты и функции, вы можете пожелать компилировать после каждого изменения.

Благодарности

Я хотел бы выразить мою искреннюю благодарность Глену Гордону, Майку Педерсену, Джозефу Данну, Син Мерфи, Глену Сепку, Джеймсу Пазуоли, Лесу Криглеру и дасти Ворхису за их страшно полезную техническую информацию, идеи и рекомендации. Я также хотел бы поблагодарить Фрэнка Дипалермо который написал первые руководства по макросам и скриптам, которые послужили отправной точкой для этого проекта.



Распространение материалов сайта означает, что распространитель принял условия лицензионного соглашения.
Идея и реализация: © Владимир Довыденков и Анатолий Камынин,  2004-2019