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

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

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

Типы утверждений продолжение)
Встроенные функции и операторы

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

Встроенные функции

Язык Jaws предоставляет для использования в скриптах более 200 предопределённых функций. Каждая функция выполняет определенное разработчиками программы Jaws действие. Эти функции являются строительными блоками, из которых мы создаем наши скрипты. Например, RouteJAWSToPC проверяет положение Jaws и PC курсоров, делает необходимые расчеты и перемещает Jaws курсор в ту же точку, в которой находится PC курсор. И хотя вы вряд ли когда-нибудь сможете выяснить, как эта функция устроена изнутри, для написания скриптов вам достаточно знать, что она перемещает Jaws курсор к PC курсору.

Нет никакого практического смысла обсуждать здесь все встроенные функции, поэтому мы подробно рассмотрим наиболее важные из них. В приложении C перечислены многие из важных функций и даны краткие описания каждой. Эти описания основаны на информации, которую можно найти в файле BUILTIN.JSD, расположенном в папке JawsXX\settings\enu, предполагая, что вы используете U. S. English версию Jaws. Эти описания в BUILTIN.JSD являются теми же описаниями, которые вы слышите, когда просматриваете список функций диспетчера скриптов. Хотя все функции Jaws являются важными, те, которые приведены в приложении C показались нам самыми важными и достойными того, чтобы быть включенными в это руководство.

Понимание этого материала сослужит вам хорошую службу на пути к тому, чтобы стать мастером по написанию скриптов. Эти описания и описания оставшихся функций можно просмотреть в любое время, вызвав диалог Insert Function (вставка функции) в диспетчере скриптов или просмотрев файл BUILTIN.JSD.

Мы также сгруппировали многие встроенные функции по их назначению. Списки сгруппированных функций можно просмотреть в приложении D . Если вы хотите выполнить конкретный тип задачи, но не знаете имя функции, можете попытаться посмотреть группы функций в приложении D, вместо того, чтобы просматривать весь алфавитный список приложения C или BUILTIN.JSD.

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

Синтаксис функции следующий:

ИмяФункции ([параметры])

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

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

Функции GetCurrentWindow и GetFocus

Есть две встроенные функции, которые настолько важны для написания скриптов, что они заслуживают отдельного упоминания. Эти две функции называются GetCurrentWindow и GetFocus. Мы уже немного говорили о дескрипторах окон, но мы никогда не говорили вам в явном виде, как их получить и что с ними делать. Именно здесь вы должны начать изучение того, как делать две эти штуки. Это позволит вам получить подробную информацию об окне (которое, как мы уже сказали, также означает любой элемент управления), которое присутствует в вашем приложении.

Ниже приведены определения двух этих функций, взятые из BUILTIN.JDF.

GetCurrentWindow - определяет дескриптор окна (Window Handle) для окна, которое содержит активный курсор. В противоположность этому, функция GetFocus использует аналитический процесс, чтобы найти окно, которое в данный момент содержит фокус, независимо от того, какой курсор является активным.

GetFocus - возвращает дескриптор окна, которое содержит фокус. Она всегда ищет PC курсор или выделенный объект, который имеет фокус. Она не принимает во внимание, какой курсор является активным. В противоположность этому, функция GetCurrentWindow является менее сообразительной. Она просто возвращает дескриптор окна, в котором находится активный курсор.

Так что же означают эти определения? Прежде всего, обе функции сообщают дескрипторы окон, поэтому их использование позволит нам получить эту информацию об окне в нашем приложении. Например, утверждения Let MyHandle = GetCurrentWindow () и Let MyHandle = GetFocus () установят Handle переменную равной значению дескриптора запрашиваемого окна.Если вслед за этим вы использовали утверждение, такое как SayInteger (MyHandle), Jaws озвучит число или дескриптор окна, о котором идет речь. Разница между двумя этими функциями состоит в том, что GetFocus будет сообщать дескриптор любого окна, в котором, по мнению Jaws, находится фокус. Это может быть, например, выделенная в данный момент кнопка или поле редактирования в окне диалога. GetCurrentWindow будет проверять, какой курсор является активным а затем сообщит дескриптор окна, содержащего этот курсор. Таким образом, если вы активизируете Jaws курсор и удаляетесь от фокуса к другому элементу управления, GetCurrentWindow сообщит дескриптор окна этого нового элемента управления, тогда как GetFocus будет по-прежнему сообщать дескриптор окна, содержащего фокус.

Итак, теперь вы знаете, как получить дескриптор окна. И что вы намерены с этим делать? Само по себе это мало что дает, поскольку это просто число. Однако, функции GetFocus и GetCurrentWindow могут использоваться в качестве параметров другими функциями, которые предоставляют куда более полезную информацию об интересующем нас окне. Ниже приведены некоторые примеры.

GetControlID (GetCurrentWindow ()) - сообщит идентификатор элемента управления окна, содержащего активный курсор.

GetFirstChild (GetFocus ()) - сообщает дескриптор первого дочернего окна для окна, в котором находится фокус. этот дескриптор можно затем использовать для получения информации о дочернем окне.

GetParent (GetCurrentWindow ()) - сообщает дескриптор родительского окна, которое породило текущее дочернее окно.

SayControl (GetFocus ()) - озвучит содержание и приглашение элемента управления, который в данный момент содержит фокус.

SayWindowTypeAndText (GetCurrentWindow ()) - сообщит разнообразную информацию об окне, содержащем активный курсор, такую, как заголовок окна, если он есть, содержание окна, тип окна и другую информацию.

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

Функции Pause и Delay

Есть две функции, которые временно приостанавливают обработку скрипта, Pause () и Delay (). Такая приостановка работы скрипта часто бывает необходима, чтобы не дать скрипту уйти слишком далеко вперед по сравнению с приложением, с которым он работает. Например, если вы используете функцию, которая перемещает Jaws курсор в другую часть экрана, или которая убирает меню, вам может понадобиться приостановить работу скрипта, чтобы разрешить завершение действий, прежде чем скрипт продолжит работу. Функция Pause просто останавливает обработку скрипта, и дает другому приложению возможность завершить свою обработку. Затем скрипт продолжает работу. Функция Delay останавливает обработку скрипта на указанный период времени, который указывается целым числом в скобках. Чем больше целое число, тем дольше остановка. Однако, если выбранного времени недостаточно, чтобы наше приложение завершило свою работу, скрипт продолжит работу в любом случае. Иногда необходим процесс проб и ошибок, чтобы определить необходимое время задержки. В общем, функция Delay является более полезной, когда вы хотите заставить скрипт остановиться, независимо от того, закончило приложение свою работу, или нет. Иногда функция Pause просто не останавливает скрипт на достаточно долгий промежуток времени, и для того, чтобы достичь желаемого эффекта, вызывается Delay. В общем, стоит сначала попробовать Pause. Если требуется более длительная приостановка, то можно использовать Delay.

Слово об SDM окнах

Как только вы узнали кое-что об окнах, вам придется кое-что узнать об исключении. Раньше мы уже говорили о взаимодействии родительских и дочерних окон, и описали, как каждый элемент управления (то есть, кнопка, поле редактирования, блок проверки и т.д.) является окном со своими собственными правами и является дочерним окном родительского окна, которое породило его, Обычно окна диалога. В общем, как оказалось, есть такая ситуация, когда это не так. В Windows есть тип окна, который он использует в некоторых своих приложениях, который называется SDM окно, что расшифровывается как standard dialog manager (стандартный диспетчер диалога). В SDM окне элементы управления не являются дочерними окнами родительского диалога, и на самом деле, вообще не являются отдельными окнами. Поэтому у них нет своих дескрипторов. Это делает невозможным написание скриптов, чтобы получать о них информацию, используя стандартные методы, подходящие для других элементов управления. Например, в обычном диалоге, если вы хотите получить информацию об элементе управления, на котором в данный момент находится фокус, вы можете воспользоваться вложенным оператором функции, как, например, GetWindowSubtypeCode (GetFocus ()). GetFocus () передаст дескриптор окна, в данный момент содержащего фокус функции GetWindowSubtypeCode () а эта функция затем возвратит код подтипа элемента управления, в настоящий момент содержащего фокус. Таким способом вы можете узнать, является ли текущий элемент управления кнопкой, радиокнопкой, слайдером, блоком проверки или другим типом элемента управления. Но это просто не будет работать в SDM окнах, поскольку его элементы управления просто не имеют уникальных дескрипторов. Поэтому в Jaws входят некоторые специальные функции, которые вы увидите в приложении C и которые используются для получения информации об элементах управления в SDM окне.

Ну а как мы узнаем, что имеем дело с SDM окном? Ну, по крайней мере, это-то легко. Вы всегда можете воспользоваться комбинацией клавиш Jaws Ctrl+Insert+F1, чтобы получить некоторую информацию об окне, на котором вы в данный момент сфокусировались, и один из пунктов, который вы получите, это класс окна. SDM окна всегда имеют в своих именах буквы SDM. Например, если вы вызовете диалог открытия файлв в Microsoft Word и нажмете CTRL+Insert+F1 на элементах управления в этом диалоге, вы обнаружите, что большинство из них имеют имя класса окна bosa_sdm_Microsoft Word 8.0. Вы также заметите, что все элементы управления с этим именем также имеют один и тот же дескриптор (window handle). Это дескриптор самого диалога открытия, и таким образом, от него мало пользы в получении информации о конкретных элементах управления. Тогда как же получать такую информацию? Специальные функции в Jaws, которые предназначены для того, чтобы делать это, основываются на том факте, что элементы управления в SDM диалоге имеют уникальный контрольный идентификатор, даже если у них нет уникального дескриптора окна. Используя этот уникальный контрольный идентификатор в комбинации с дескриптором окна диалога, можно получить информацию об элементах управления SDM диалога. Например, две из специальных SDM функций, приведенных в приложении C, это SDMGetCurrentControl и SDMGetNextControl. Первая из них возвращает контрольный идентификатор элемента управления, на котором находится активный курсор, а вторая сообщит контрольный идентификатор следующего элемента управления в SDM диалоге. Таким образом, если вы хотите получить более подробную информацию о текущем или следующем элементе управления в SDM диалоге, он может воспользоваться информацией о контрольном идентификаторе или из двух этих функций с одним из других специальных SDM утверждений, чтобы сообщить дополнительную информацию об элементе управления. Например, такое утверждение показано ниже.

SDMSayControl (GetFocus (), SDMGetCurrentControl ())

Функция SDMSayControl озвучит элемент управления в SDM диалоге, но мы хотим, чтобы она сообщила, какой. Чтобы сделать это, потребуются два параметра. Первый, GetFocus, заставляет функцию получить дескриптор текущего активного SDM диалога. Второй параметр, SDMGetCurrentControl, сообщает функции, что нам нужен контрольный идентификатор элемента управления SDM, на котором мы сейчас находимся. Таким образом, эта функция озвучит имя и другую информацию об элементе управления SDM, на котором мы находимся в данный момент в SDM диалоге. Другими словами, мы можем вычислить уникальный элемент управления, сообщив Jaws и дескриптор SDM диалога, на который мы ссылаемся, и контрольный идентификатор элемента управления, который нас интересует. Две этих частей информации, взятые вместе, оказывается достаточно, чтобы сообщить Jaws, о каком элементе управления в SDM диалоге мы хотим узнать. Другие SDM функции, приведенные в приложении C, предоставляют другие опции для идентификации элементов управления в SDM диалогах.

Арифметические операторы

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

Let IntVar = IntVar + 1 (это увеличит целочисленную переменную, которая называется IntVar на 1)
Let IntVar = FirstVar * SecondVar (это устанавливает, что IntVar равняется FirstVar, умноженной на SecondVar)
SayString (MyConstant + YourConstant) (это озвучит содержание двух констант, Myconstant и YourConstant, как если бы это было одно сообщение).
Логические операторы

Логические операторы используются для сравнения переменных с другими переменными или константами. Нам часто бывает необходимо знать, имеет ли объект то же значение, меньшее значение или большее значение, чем другой объект. Иногда необходимо сравнить несколько объектов или группу объектов, с другими объектами. Логические операторы обычно используются внутри циклов if-then и While, чтобы решить, являются ли условия, необходимые для логических решений, истинными или ложными. Ниже приводится список логических операторов Jaws.

== - два знака равенства подряд спрашивают, является ли первое условие равным второму условию. То есть, является ли выражение слева от двух знаков равенства эквивалентным выражению справа. Например, выражение (A == B) спрашивает, является ли A равным B.

!=- восклицательный знак и знак равенства - спрашивает, является ли первое условие неравным второму условию. То есть, является ли выражение слева от восклицательного знака и знака равенства отличным от выражения справа. Например, выражение (A != B) является истинным, если A не равно B.

< - знак "меньше" спрашивает, является ли первое условие меньше второго условия. То есть, является ли выражение слева от знака < меньше, чем выражение справа. Таким образом, выражение (A < B) является истинным, если если A меньше B.

<= - знак "меньше", после которого следует знак равенства, спрашивает, является ли первое условие меньшим или равным второму условию. То есть, является ли выражение слева от <= меньшим или равным выражению справа. Таким образом, выражение (A <= B) будет истинным, если A меньше или равно B.

> - знак "Больше" - спрашивает, является ли первое условие больше второго условия. То есть, является ли выражение слева от знака > больше, чем выражение справа. Таким образом, выражение (A > B_ является истинным, если A больше B.

>= - знак "Больше", после которого следует знак равенства, спрашивает, является ли первое условие большим или равным, чем второму условию. То есть, является ли выражение слева от >= большим либо равным выражению справа. Таким образом, выражение (A >= B) будет истинным, если A будет больше или равно B.

&& - этот оператор помещается между двумя логическими сравнениями, которые производятся с использованием таких логических операторов, как те, которые были описаны выше. Он спрашивает, является ли первое условие верным "и кроме того" является ли верным второе условие. Выражение в целом оценивается как истинное только в том случае, если сравниваемые элементы по обеим сторонам оператора && являются истинными. Таким образом, в выражении (A == B) && (C != D), значение истины возвращается только в том случае, если A равно B, а C не равно D.

|| - этот оператор помещается между двумя логическими сравнениями, которые производятся с использованием логических операторов, таких, как те, которые были перечислены выше. Он спрашивает, является ли истинным либо первое, либо второе условие. Выражение в целом оценивается как истинное, если любое выражение на любой стороне от оператора || является истинным. Таким образом, в примере (A == B) || (C == D), значение истины возвращается, либо если A равно B, либо если C равно D. Конечно, истина будет возвращена и в том случае, если верными будут оба выражения.

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

!Выражение ==True

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

Поразрядные операторы

Поразрядные операторы - это инструмент, который позволяет нам сравнить два фрагмента данных скорее необычным способом. Они позволяют нам сравнить два фрагмента информации байт за байтом, а не значения в целом. Все мы знаем, что компьютерная информация хранится в цифровой форме, как ряд нулей и единиц. Это, конечно, верно для констант и переменных. Например, константа Jaws для выбранного или выделенного текста называется Attrib_highlight. Если вы заглянете в файл HJCONST.JSH, то вы обнаружите, что эта константа имеет значение 64. Что же значит это 64? Очевидно, что 64 - это десятичное число, а не бинарное число. Мы можем это утверждать, потому что бинарные числа состоят только из нулей и единиц, поэтому 64 не может быть двоичным числом. Когда мы переведем 64 в двоичную систему счисления, мы получим число 01000000. (Обсуждение двоичной арифметики не входит в компетенцию данного руководства, поэтому если вы не знаете, как было проведено преобразование, просто примите это на веру). HJCONST.JSH также сообщает нам, что атрибут жирного шрифта, Attrib_Bold, имеет значение 2 или 00000010 в двоичном формате, атрибут курсива, Attrib_Italic, имеет значение 4 или 00000100 в двоичном формате, а атрибут подчеркивания, Attrib_Underline, имеет значение 8 или 00001000 в двоичном формате. Помните, как раньше мы говорили в этом руководстве, что константы используются потому, что их легче запомнить, чем числа? Ну вот вам и превосходный пример такой ситуации. Имена типа ATTRIB_HIGHLIGHT гораздо легче запомнить, чем длинные двоичные числа.

Так что же мы будем делать с этими числами, и что они будут делать с поразрядными операторами? Допустим, мы хотим знать, является ли некоторая часть текста выделенной. Мы будем пользоваться одним из поразрядных операторов, который обозначается одиночным символом & чтобы узнать это. Этот поразрядный оператор позволяет нам взять переменную и сравнить ее, бит за битом, с другой переменной или константой, такой, например, как ATTRIB_HIGHLIGHT. Есть существенная разница между стандартным сравнением и поразрядным сравнением двух фрагментов информации с использованием оператора &. В стандартном сравнении значение True или 1, будет возвращена, только если оба фрагмента информации являются идентичными во всех отношениях. В поразрядном сравнении, использующем оператор &, значение True или 1 будет возвращено для каждой пары битовых позиций в двух фрагментах информации, которые являются идентичными. Допустим, нам нужно сравнить два двоичных числа, 0101 и 0001. В стандартном сравнении два эти числа не одно и то же. В поразрядном сравнении правая цифра одна и та же для обоих чисел, поэтому для поразрядного сравнения будет возвращено значение 0001. Этот возврат означает, что сравнение было истинным, но только в первой, или в самой правой позиции. Если бы нам надо было сравнить числа 0111 и 010, то мы бы увидели, что вторая и третья позиции справа - единицы в обеих числах. Следовательно, поразрядное значение возвратит значение 0110. Аналогичным образом, 0011 и 0110 возвратят значение 0010. Только вторая цифра в обоих числах является единицей. Мы можем проводить аналогичные сравнения, когда одно из чисел является переменной,как, например, переменная, которая сообщает атрибуты, которые ассоциированы с атрибутами текста в функции скрипта NewTextEvent. (Вспомните, что функция NewTextEvent начинает работать автоматически всякий раз, когда на экране появляется новый текст. Следующая строка взята из этой функции:

If (nAttributes & ATTRIB_HIGHLIGHT) Then

На первый взгляд, это очень странное утверждение. Переменная nAttributes является параметром, который вносит информацию об атрибуте в функцию NewTextEvent, когда на экране появляется новый текст. Таким образом, если этот текст выделен цветом, nAttributes будет иметь значение 01000000. Если текст выделен жирным шрифтом, переменная будет иметь значение 00000010. Если текст выделен курсивом и жирным шрифтом, nAttributes будет иметь значение 00000110. Если он выделен цветом, курсивом и жирным шрифтом, она будет иметь значение 01000110. Каждую позицию в nAttributes можно представить в виде переключателя, который включает и выключает один из возможных атрибутов. Ну, мы уже знаем, что ATTRIB_HIGHLIGHT имеет значение 01000000, так что вышеприведенная строка кода говорит, что возьмите nAttributes и сравните его, используя поразрядный оператор, с константой Attrib_highlight. Если совпадение есть, верните назад сообщение 1 для каждого положения бита, которое совпадает. Если мы сравним, например, текст, который является выделенным цветом, подчеркнутым и жирным шрифтом (nAttributes = 01000110) поразрядным способом с ATTRIB_HIGHLIGHT (01000000), то мы вернем значение 01000000. Это означает, что утверждение If-Then возвращает значение True, или 1 для седьмой позиции справа, той, которая указывает, является ли текст выделенным, и NewTextEvent узнала, что текст, который появился на экране, действительно является выделенным. Поэтому текст будет обрабатываться как выделенный текст. Тот факт, что этот текст также выделен курсивом и жирным шрифтом также истинен, но для данного теста это не имеет значения. Вышеприведенное утверждение If-Then проверяет только то, является ли бит выделения истинным или 1, и эта информация посылается в скрипт NewTextEvent.

Кроме того, есть еще один поразрядный оператор, который выполняет операцию Или, вместо операции И. Этот оператор обозначается единичным символом | чтобы отличить его оператора Или, который обозначается двойным символом, ||. Когда вы используете поразрядный оператор Или, значение True возвращается в том случае, если любой из бит, или они оба, которые участвуют в сравнении, равны единице. Таким образом, сравнение двух бинарных чисел 0101 и 0010 вернет значение 0111. Аналогичным образом, сравнение чисел 0100 и 0001 вернет значение 0101. Таким образом, поразрядный оператор Или удовлетворяется, если любое из чисел имеет 1 в конкретной позиции.

Hook функции

Иногда бывает необходимо перевести Jaws в измененное состояние, когда некоторые, или все клавиши на клавиатуре выполняют функции, которые отличаются от обычных. До некоторой степени мы уже знакомы с этим понятием. Вы можете переключать такие настройки, как Эхо экрана, эхо клавиатуры и состояние Home Row, последний режим будет описан позже. Эти типы переключений возможны потому, что Jaws имеет встроенные функции, которые могут вызываться скриптами, чтобы переключать эти состояния определенным образом. Однако, Jaws также содержит две функции, которые позволяют вам изменять состояние системы сообразно вашим нуждам. Это функции AddHook () и RemoveHook (). В общих чертах происходит примерно следующее: если вы устанавливаете hook, вызвав функцию AddHook () из скрипта, мы говорим, что hook помещен. Когда вы используете функцию AddHook, вы даете ей имя хука. Этот хук является специальной функцией, определяемой пользователем, которую вы должны создать, и которая должна выполняться вместо кода, обычно выполняемого скриптами Jaws. Когда хук на месте, он вызывается прямо перед выполнением каждого скрипта, и передает имя текущего скрипта и фрейма в качестве двух своих параметров. Поскольку хук функция фактически вызывается Jaws, когда он на месте, а не скриптом, эти параметры предоставляются внутренним кодом Jaws, а не вызовом функции. Если хук возвращает истину, скрипту разрешается выполняться. Если хук возвращает ложь, скрипту не позволяется выполняться. Таким образом, если хук на месте, и мы разработали хук таким образом, что он будет возвращать ложь, пока он на месте, скрипт, закрепленный за клавишей, которую мы нажали, работать не будет, и мы можем заставить хук функцию сделать что-то другое. Вы можете, если хотите, разработать хук, который будет заставлять каждую клавишу, закрепленную за скриптом Jaws, воспроизводить "У маленькой Мэри жила-была овечка" вместо того, чтобы выполнять нормальные функции Jaws. Ну, сейчас в этом особой пользы нет, но было бы здорово, если бы у вас был такой хук и вы бы его включали всякий раз, когда вы позволяете своему другу воспользоваться вашим компьютером! Но давайте рассмотрим более полезную хук функцию, KeyboardHelpHook.

Как вы теперь, вероятно, знаете, вы можете включить помощь по клавиатуре, нажав Insert+1. Когда вы это делаете, каждая клавиша начинает воспроизводить свои функции, если она закреплена за каким-либо скриптом Jaws, вместо того, чтобы реально выполнять эти функции. Когда вы снова нажимаете Insert+1, клавиатура возвращается к выполнению функций, вместо того, чтобы выдавать описания. А вы когда-нибудь задумывались, как это сделано? А сделано это с помощью хук функций. Давайте рассмотрим скрипт KeyboardHelp и функцию KeyboardHelpHook чтобы посмотреть, как выполняются эти задачи.

Script KeyboardHelp()
SayString (msg401) ; "Keyboard Help on". Сообщается, когда вы в первый раз нажимаете Insert+1. let nKeyboardHelpSavedTypingEcho = GetJcfOption(OPT_TYPING_ECHO); сохраняет текущую настройку эха клавиатуры.
SetJcfOption(OPT_TYPING_ECHO,1) ;Эхо клавиатуры символы. Помощи по клавиатуре необходимо, чтобы эхо клавиатуры находилось в режиме "символы".
AddHook (HK_SCRIPT, "KeyboardHelpHook") ;добавляет хук по имени KeyboardHelpHook.
TrapKeys(TRUE) ;будучи истинной, эта функция заставляет Jaws игнорировать любые клавиши, не закрепленные за скриптами
EndScript

Происходит следующее: озвучивается сообщение, оповещающее вас, что помощь по клавиатуре включена, сохраняется текущее состояние эха клавиатуры, эхо клавиатуры переводится в режим "Символы", чтобы помощь по клавиатуре функционировала должным образом, и устанавливается KeyboardHelpHook. Кроме того, TrapKeys устанавливается в значении True, поэтому клавиши, не связанные со скриптами Jaws, или фреймами, будут игнорироваться. (Вы не можете назначить подсказку на клавишу, с которой не ассоциировано скриптов Jaws или фреймов). Также, пожалуйста, обратите внимание,что функция AddHook требует два параметра. Первый, HK_SCRIPT, это константа, заданная в HJCONST.JSSH, вы должны использовать для каждой AddHook. Второй - это имя хука, который вы устанавливаете. Так что теперь любая клавиша, связанная с функцией Jaws, не будет выполнять свою функцию, а будет вызывать функцию KeyboardHelpHook, показанную ниже.

Void Function KeyboardHelpHook (string ScriptName, string FrameName)
if (ScriptName == "KeyboardHelp") then ;если мы нажимаем Insert+1 когда хук установлен, это означает, что мы хотим выключить помощь по клавиатуре. 	
SayString(msg402) ; "Keyboard Help off" RemoveHook (HK_SCRIPT, "KeyboardHelpHook") ;хук удаляется
TrapKeys(FALSE) ;теперь клавиши снова будут распознаваться.
SetJcfOption(OPT_TYPING_ECHO,nKeyboardHelpSavedTypingEcho) ; восстанавливается первоначальное состояние эха клавиатуры
return FALSE ;несмотря на то, что мы отключили хук, нам лучше еще раз
 ;вернуть ложь, или скрипт Insert+1 запустится снова и снова установит хук.
EndIf

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

 if IsSameScript () then 	
if ((FrameName != "") && (GetFrameDescription (FrameName) != "")) then 		
SayString (msg420) ; "This frame " 		
SayString (GetFrameDescription (FrameName)) 	
EndIf 	
if (FrameName == "") then 		
SayString(GetScriptDescription(ScriptName)) 	
EndIf
else 	
SayString (GetCurrentScriptKeyName ()) ; says key name, "INSERT+UP ARROW" 	
if (FrameName != "") then 		
SayString (msg421 + FrameName) ; "says the content of the frame " 		
SayString (GetFrameSynopsis (FrameName)) 	
else 		
SayString (ScriptName) ; will say the name of the script, "SayLine" 		
SayString(GetScriptSynopsis(ScriptName)) 	
EndIf
EndIf
return FALSE ;Prevent the script from running since we only want the help message.
EndFunction
Знакомство с написанием скриптов с объектами Microsoft

Если вам довелось прочитать какой-нибудь скрипт для Microsoft Word или Excel, вы, вероятно, наталкивались на очень странный код, который не похож ни на какие блоки построения скриптов, о которых мы говорили до сих пор. Этот код содержит такие слова, как Selection, Range, Text, Collapse, отделенные друг от друга точками. Если вы не знакомы с объектно-ориентированным программированием с использованием таких языков, как Visual Basic и C++, этот тип кода будет совершенно непонятным. Так что же это за штука и что она делает среди скриптов Jaws? Чтобы пояснить, нам придется ввести три новых понятия - объекты, методы и свойства.

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

Так почему же мы так заботимся об этих объектах? Есть некоторые вещи, которые пользователи любят уметь делать, как, например, читать и перемещаться по предложениям или абзацам, а не просто по строкам. К сожалению, в большинстве текстовых процессоров добиться этого довольно трудно, поскольку они не предусмотрены для навигации в такой манере. Кроме того, мы должны помнить, что программа доступа к экрану по определению читает то, что видимо на экране, и если часть предложения или абзаца, который мы пытаемся прочитать, находится за экраном, обычно он не сможет получить доступ к этой части материала без прокрутки экрана. Но пользователь может не захотеть этого делать, поскольку, например, он находится в процессе редактирования, и ему не хочется перемещать курсор. Объекты предоставляют нам средства, чтобы выполнить эту задачу, поскольку объект,представляющий данный документ, содержит все процедуры и свойства, необходимые для того, чтобы сообщить информацию, необходимую Jaws. Microsoft решил выставить эти "объекты автоматизации" на всеобщее обозрение, в некоторых своих приложениях, таких, как Office 97 Suite, и Jaws, исследуя и манипулируя этими объектами, может выполнить некоторый спектр желательных задач, описанных выше. По сути дела, Jaws временно становится программой доступа к объектам, а не только программой доступа к экрану. Термин "Объект автоматизации" ("automation object") здесь используется, чтобы показать объект, выставленный на всеобщее обозрение, так что другие агенты, как например Jaws, могут иметь доступ к таким объектам. Приложения, которые не используют некоторый вид модели объекта, описанную здесь, для своего кодирования, или не показывают эти объекты для внешнего мира, не могут быть доступными с помощью этой технологии. Таким образом, использование объектов для улучшения чтения экрана ограничено некоторыми приложениями Microsoft, или любым приложением, которое решает показать эти объекты автоматизации(или автоматические объекты, не знаю, как лучше. Прим. пер.).

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

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

Понимание объектов, свойств и процедур

Объекты являются фундаментальными строительными блоками в Visual Basic. Почти все, что вы делаете в Visual Basic, включает модификацию объектов. Каждый элемент документов Word, таблицы, абзацы, закладки, поля и так далее, могут быть представлены объектом в Visual Basic.

Что такое объекты и коллекции?

Объект представляет элемент Wordа, такой, как документ, абзац, закладка или просто символ. Коллекция - это объект, который содержит несколько других объектов, обычно одного и того же типа; например, все объекты закладок в документе содержатся в одном объекте коллекции. Используя процедуры и свойства, можно модифицировать одиночный объект или всю коллекцию объектов.

Что такое свойство?

Свойство - это атрибут объекта, или аспект его поведения. Например, свойства документа включают его имя, содержание и статус сохранения, а также то, является ли включенным отслеживание изменений. Чтобы изменить характеристики объекта, вы изменяете значение свойств. Чтобы установить значение свойства, поставьте точку после ссылки на объект, затем имя свойства, знак равенства затем новое значение свойства. Следующий пример включает статус отслеживания изменений в документе под именем mydoc.doc.

Documents("MyDoc.doc").TrackRevisions = True

В этом примере Documents ссылается на коллекцию открытых документов, а имя "MyDoc.doc" идентифицирует один документ в коллекции. Свойство TrackRevisions задается только для этого документа.

Некоторые свойства задавать нельзя. Раздел помощи для свойства (property) указывает, можно ли задавать это свойство (read-write) или его можно только просматривать (read-only).

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

docName = ActiveDocument.Name

В этом примере ActiveDocument обращается к документу в активном окне в Wordе. Имя этого документа присвоено переменной docName.

Обратите внимание, что раздел помощи для каждого свойства указывает, можете ли вы задавать это свойство (read-write), только просматривать свойство (read-only), или только задавать (write-only). Браузер объектов в редакторе Visual Basic также выводит статус чтения-записи в нижней строке окна браузера, когда выбирается свойство.

Что такое процедура?

Процедура - это действие, которое может выполнить объект. Например, точно также, как можно распечатать документ, объект документа имеет процедуру PrintOut. Процедуры часто имеют аргументы, которые квалифицируют, как выполняется действие. Следующий пример распечатает первые три страницы активного документа:

ActiveDocument.PrintOut From:=1, To:=3

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

Возвращение объекта

Большинство объектов возвращаются путем возврата одного объекта из коллекции. Например, коллекция Documents содержит открытые документы Word. Вы используете свойство Documents объекта Application (объекта, находящегося на самом верху иерархии объектов Word), чтобы возвратить коллекцию Documents.

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

Следующий пример использует свойство Documents для получения доступа к коллекции Document. Число индекса используется для того, чтобы возвратить первый документ в коллекции Documents. Затем к объекту Document применяется процедура Close, чтобы закрыть первый документ в коллекции Documents.

Documents(1).Close

Следующий пример использует имя (указанное как строка (string)) чтобы идентифицировать объект Document внутри коллекции Documents.

Documents("Sales.doc").Close

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

Documents.Save

Объекту Document также доступна процедура Save, для сохранения только одного документа. Следующий пример сохраняет документ под именем report.doc.

Documents.Save

Надеемся, что вам становится ясно, что манипулирование этими типами объектов является фундаментальным в действиях, которые происходят в приложениях Microsoft Office, и что манипулируя этими объектами Jaws может получить желанную информацию из модели объекта. На самом деле, если вы затратите время, чтобы научиться писать макросы в Word (что делается просто в подменю Макро в меню Сервис), вы увидите нечто крайне интересное. (вы можете получить информацию о том, как писать макро из системы помощи Windows, если нажмете F1 находясь в Word). Войдите в меню Указатель и наберите слово Макро. Вам будет представлено несколько тем, включая создание макросов). Попробуйте написать макрос, когда будете делать какую-нибудь типичную операцию, как открытие документа, сохранение документа, или выбор, а затем удаление какого-либо текста. Затем, после того, как запись макро будет выключена, вернитесь в подменю Макросы и нажмите Enter на первой опции, Макросы, или Alt+F8. Вы откроете список существующих макросов и вам будет предложено их отредактировать. Выберите опцию "Правка", и вы окажетесь в редакторе Visual Basic вам будет показана копия вашего макроса. Вы обратите внимание, что код выглядит так, как объектно-ориентированное программирование, которое мы только что обсуждали. Это означает, что все, что вы делаете, работая в этом приложении, делается посредством доступа к объектам и работы с их процедурами и свойствами. Таким образом, изучение макросов, которые вы записали, является одним из способов изучить, как манипулировать объектами в приложениях Office. Есть еще один полезный способ, который вы можете использовать, находясь в редакторе Visual Basic. Если вы нажмете F1 когда курсор вставки будет находиться на процедуре или свойстве программного кода, появится экран помощи, который объясняет термин и как он используется. Если у вас этой помощи нет, это может означать, что помощь по Visual Basic на вашей системе не установлена. Вы можете установить ее с установочного диска Microsoft Office, вставив диск в дисковод, а затем вызвав диалог "Выполнить" главного меню и набрать X/setup, где X - буква вашего дисковода для компакт-дисков. Когда появится диалог установки, щелкните кнопку "Добавить/Удалить". Затем, когда появится список вариантов, выберите одно из приложений Office, например Word, и перейдите к кнопке "изменить параметры". Щелкните ее. Вы окажетесь еще в одном списке вариантов. Выберите пункт "Помощь" и перейдите к кнопке "изменить настройки" снова. Щелкните ее. Вы попадете в третий список: выберите опцию "Справка по Visual Basic", а затем перейдите к кнопке OK и щелкните ее. Щелкайте кнопку OK, пока не вернетесь на самый верхний уровень списка. Повторяйте процедуру, пока не установите систему помощи для Visual Basic в каждом приложении, которое вас интересует. Затем нажмите OK на верхнем уровне, чтобы закончить установку. Вы можете в любое время вернуться в редактор Visual Basic, выбрав его в подменю Макро в меню Сервис, или нажав Alt+F11.

Теперь давайте бросим взгляд на один из скриптов Jaws, который использует объекты для выполнения своей задачи. В версии 3.2 нажатие клавиши Ctrl и плюса на цифровой клавиатуре, если вы находитесь в Microsoft Word 8, читает текущий абзац.

Script SayParagraph ()
SaveCursor ()
PCCursor ()
if (GetLine () == "") then 	
SayString (msge18); "Blank"
else 	
SayString (GetParagraphContent ())
EndIf
EndScript

Выглядит как совершенно обычный скрипт, который вызывает определенную пользователем функцию GetParagraphContent (). Давайте посмотрим на эту функцию.

String Function GetParagraphContent ()
var 	
object o
let o = oWord.Selection.Paragraphs(1).Range;
return (o.Text);
EndFunction

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

let o = oWord.Selection.Paragraphs(1).Range;

Прежде чем мы проанализируем эту строку, мы хотели бы упомянуть о точках с запятой, которые появляются на концах некоторых строк. Они означают то, что означали всегда, что все, что написано после них, является комментарием. Некоторые программисты добавляют эти точки с запятой, чтобы показать окончание действительного кода в строке, даже если они не помещают после точки с запятой никаких комментариев. Теперь давайте проанализируем эту строку слева направо. Слева от знака равенства мы говорим, что собираемся присвоить некоторое значение переменной o. Первое, что написано справа от знака равенства, это нечто, называющее себя oWord. oWord - это глобальная переменная, которая была объявлена в заголовочном файле WINWORD.JSH, и это переменная типа Object, которая хранит объект application (приложение), а приложением является Microsoft Word. oWord определена в функции AutoStartEvent в начале файла скрипта. Вспомните, что эта функция события отрабатывает автоматически всякий раз, когда загружается Word или когда он получает фокус системы. Код в функции AutoStartEvent, написанный программистами из Henter-Joyce, устанавливает указатель на Word, поэтому Jaws будет знать, где искать объекты приложения. Если бы на этой строке не было ничего, кроме Let o = oWord, мы бы задали переменную o равной глобальной переменной типа Object oWord, объекту приложения в целом. Это не дало бы нам ничего хорошего, если все, что мы хотели сделать, это прочитать текущий абзац. Поэтому мы намерены найти какой-то способ извлечь текстуальную информацию этого абзаца из объекта приложения в целом.

Следующий пункт - это знак точки. Он используется, чтобы разделить переменные, процедуры и свойства. Затем идет Selection. Это свойство Selection, и, по сути дела, оно возвращает объект Selection, который содержит информацию о том, что в данный момент выделено в документе. Если вы выделили в документе какой-то текст, этот текст будет возвращаться в объекте Selection. Если ничего не выделено, объект Selection сколлапсируется в простую точку в курсоре вставки. Вот некоторая информация об объекте Selection, которая выдается в справочной системе по Visual Basic.

Объект Selection

Представляет выделение в панели окна. Selection может либо охватывать некоторую область в документе, или сколлапсироваться в курсор вставки.

Обратите внимание, что в панели окна может быть только один объект Selection, и только один объект Selection может быть активным.

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

Используйте свойство Selection, чтобы возвратить объект Selection.

Все это имеет смысл, если мы подумаем о том, что мы знаем о выделении текста. Мы знаем, что можно выделить только один блок текста в данном документе. Таким образом понятно, что может быть только один объект Selection. Если ничего не выделено, тогда выделение и объект Selection должны будут сколлапсироваться в одну точку, курсор вставки.

Также стоит уделить особое внимание последней строке на последнюю строку вышеприведенной цитаты, "используйте свойство Selection чтобы возвратить объект Selection". Если свойство возвращает объект, то этот объект будет иметь то же самое имя, что и свойство, которое его возвращает. Пожалуйста, имейте это в виду, потому что альтернативой является полная путаница. Свойство возвращает объект с тем же именем, но стартовое свойство не является свойством нововозвращенного объекта. Это истинно даже несмотря на то, что они имеют одно и то же имя. Свойство принадлежит предыдущему объекту, тому, с которым производились операции, а не наново созданному объекту. Новый объект имеет свой собственный набор процедур и свойств, и они не включают тот, который создал его.

Итак, давайте еще раз рассмотрим все, что мы имеем. Мы имеем объект Приложение Word в целом, представленный переменной oWord, а свойство Selection возвратило объект Selection, который содержит информацию о том, что в данный момент выделено в текущем документе.

Далее следует свойство Paragraph. Использование этого свойства возвращает объект Paragraph. Этот объект содержит информацию об абзаце, указанном в индексном номере в скобках, который содержится в объекте Selection, который был возвращен свойством Selection слева. Вот еще одно извлечение из системы помощи по 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. После того, как вы воспользуетесь процедурой или свойством, которое вы выбрали, вы затем получите объект, который будет иметь то же имя, что и данная процедура или свойство. Возвращайтесь в алфавитный список книг с объектами и открывайте ту, которая начинается на ту же букву, что и процедура или свойство, которыми вы пользовались, поскольку объект, возвращаемый этим свойством или процедурой, имеет то же имя. Открывайте эту книгу и ищите строку с этим именем. Затем открывайте этот пункт и используйте его список процедур и свойств, чтобы выбрать следующие. Повторяйте эту процедуру, пока не зайдете достаточно далеко, чтобы извлечь ту информацию, которая вам нужна.



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