Skip to Main ContentWindow-Eyes  Braille Sense  CCTV  Voice Sense  SyncBraille  Support  Training
GW Micro - Unleashing the power of your mind's eye.
 

So you want to write a script? - GWWiki

(Difference between revisions)
Jump to: navigation, search
(added reference to wiki article for user interface techniques)
(clarified types of scripts and added proper wiki type link to wiki article article on internal/external scripts)
Line 36: Line 36:
 
usable in your programming language of choice, and they are made possible by Window Eyes making available an enormous library of objects, properties, and methods, via the Windows COM facility.  How to use objects, properties, and methods are a topic for the learning of object oriented programming.   
 
usable in your programming language of choice, and they are made possible by Window Eyes making available an enormous library of objects, properties, and methods, via the Windows COM facility.  How to use objects, properties, and methods are a topic for the learning of object oriented programming.   
  
It is useful to know however that WE has configured 2 particular programming languages (VBScript and JavaScript) so that they are more tightly integrated with the WE object model than is normally the case.  A script written in one of these 2 languages need not open the Window Eyes COM object model explicitly (it is done automatically), and  are referred to as an "internal" script.  All other scripts, which may be written in  other programming languages, are referred to as "external" scripts, and must open the Window Eyes COM object in order to make use of it's object model.  External scripts also have a few additional requirements, documented in a [http://www.gwmicro.com/mediawiki/index.php?title=Internal_and_External_Scripts&t=20091224192759 separate wiki article]. Whether a script is internal or external is not immediately obvious in the list of scripts shown in the script manager, and it is of no importance to someone using the scripts in Window Eyes, only the developer need be concerned with the differences.
+
A script might be defined as any program which the Window Eyes script manager causes to be run, and by implication is running in order to make use of the WE object model.  These programs are under the control of WE, and integrated with it because of WE having started them running.  Another type of program, can make use of the WE object model, without having been started by the WE script manager.  It can open the WE COM object in the normal way; either to obtain information or to control WE's behavior, but it will not be as tightly integrated with WE as a WE script, and there will need to be some other way to start it executing.
 +
 
 +
It is useful to know however that WE has configured 2 particular programming languages (VBScript and JavaScript) so that they are more tightly integrated with the WE object model than is normally the case.  A script written in one of these 2 languages need not open the Window Eyes COM object model at all (it is done automatically), and  are referred to as an "internal" scripts.  All other scripts, which may be written in  other programming languages, are referred to as "external" scripts, and must open the Window Eyes COM object in order to make use of it's object model.  External scripts also have a few additional requirements, documented in the wiki article [[Internal and External Scripts]].
 +
 
 +
Whether a script is internal or external is not immediately obvious in the list of scripts shown in the script manager, and it is of no importance to someone using the scripts in Window Eyes, only the developer need be concerned with the differences.
  
 
WE also has two types of scripts, based on when the script first starts running, and when it stops.  These two types of scripts are explicitly differentiated in the script manager. You can either have a script start to run when window eyes starts, and optionally stay running as long as WE is running (referred to as a "global script"), or, have WE start a script when a particular program starts, and stop the script when the program closes down (referred to as an "application script").  All of these scripts are running concurrently, and independant of each other.  One of your first decisions, when designing a script, will be whether it should run all the time (a global script), or only when a given application is running (an application script).
 
WE also has two types of scripts, based on when the script first starts running, and when it stops.  These two types of scripts are explicitly differentiated in the script manager. You can either have a script start to run when window eyes starts, and optionally stay running as long as WE is running (referred to as a "global script"), or, have WE start a script when a particular program starts, and stop the script when the program closes down (referred to as an "application script").  All of these scripts are running concurrently, and independant of each other.  One of your first decisions, when designing a script, will be whether it should run all the time (a global script), or only when a given application is running (an application script).
  
All of the script types listed above can draw on the WE object model in order to achieve their tasks, the differences in the types only concern what programming language is used, and when the script is run.
+
All of the script types listed above can draw on the WE object model in order to achieve their tasks, the differences in the types only concern what programming language is used, and when the script is run.   Therefore, it is necessary that a scripter become familiar with the capabilities of the WE object model. Below are just some of the capabilities of the object model that scripts may make use of, listed in broad categories:
Therefore, it is necessary that a scripter become familiar with the capabilities of the WE object model. Below are just some of the capabilities of the object model that scripts may make use of, listed in broad categories:
+
  
 
* change any of the configuration settings within the WE control panel
 
* change any of the configuration settings within the WE control panel

Revision as of 18:33, 9 January 2010


Contents

Introduction

The window eyes scripting manual has several good explanations of particular scripting issues; and a good list of resources to help you learn about various aspects of programming which may help you write a script. There are also at least three scripts I know of written specifically for the purpose of helping beginners advance their scripting knowledge.

What I don't know of is a comprehensive document, which attempts to make a start at explaining the various topics you'll need to understand in order to write a script; and perhaps help take you from a scripting igneramous to a scripting expert over time.

Starting out

You have to start somewhere, so I'll start by saying that in order to write a script, you've got to know how to program in some computer programming language. A lot of the documentation in the scripting manual, and the wiki articles here, try to be helpful regardless of which language you're using, but they all assume a working knowledge of VBScript. So, you're first step should be to learn how to program if you don't already know how to; and since that usually involves learning a programming language, go out and try to find a programming tutorial book which uses VBScript. Here is a simple VBScript tutorial. If you can't find that, try for a programming tutorial book which uses the older version of visual basic (version 6 or earlier), before VB became .net, because it resembles VBScript more, and is much less complex to learn than VB.net. Failing those, you need to learn "object oriented" programming, in whatever language is available; then, when you feel comfortible as a "programmer", go and learn the VBScript language itself. Try here for a VBScript tutorial if you already know how to program. and try here for a very simple explanation of properties, methods, and objects, which are the heart of object oriented programming. These links, along with many others, can be found on the GW Micro Scripting Developer Resources page.


This raises the point, that's important to grasp, that learning how to program is a separate skill from learning any particular programming language.

This article, or series of articles, isn't going to teach you how to program if you've never programmed. you may want to know that in my opinion, learning how to program is a much bigger task than taking that knowledge, and proceeding to learn how to write window eyes scripts; so, if you don't know how to program, go learn in any way that you can, and then try and pick up an understanding of VBScript, because the rest of these articles will likely assume you'll be able to follow VBScript examples.

The differences between programming and writing a Window Eyes script

So, in general you know how to program, and you don't see how writing a script is anything more than the programming you've already learned? That's a fair question, and we'll try to answer it, but for now take it from a professional programmer: there's a great deal more knowledge you need to learn, after you've learned how to program, before you can consider yourself a good scripter; going through all that knowledge, one piece at a time, is the aim of the rest of these articles. if you'd like an analogy: it's something like learning a new programming language which is quite different from the ones you learned to program with.

The first point you'll need to examine is "what do scripts do"? "Why do we need them, what are they good for"? One thing they have been used for, but they weren't designed for and so perhaps should not be used for, is general purpose programming. If youwant a program to calculate the interest payments on your home mortgage loan, you don't need the WE scripting environment to do this. MS Windows provides you a way to write scripts, or general purpose programs, quickly and easily, and it's called the Windows Script Host; it will run VBScript programs for instance, and you don't need to learn anything about the WE scripting environment. So, we're back to why do you need to learn all the extra knowledge I've been refering to as the "WE scripting environment"? Here's a list, in no particular order, of answers to that question:

  • they can improve the accessibility (to WE only of course) of a particular software application. If there's a particular application which can't be made to work well with WE, it's quite possible you can change that significantly with a script (referred to as an "application script"). Even if it works well enough with WE, you can add "convenience features" to it with a script, so that it's faster or easier to use it.
  • You can also create similar "convenience features" with a script, which are available in all applications (referred to as a "global script"). An example might be a script which makes it particularly easy to spell the word under the cursor, or spell it phonetically.
  • Sometimes these convenience features may have nothing to do with accessibility or WE, in which case they may look like "general purpose programming" (e.g. looking up a word under the cursor on the internet); however, the WE scripting environment makes writing this kind of program much easier than would a general purpose programming language, and so a WE script may be used simply for the convenience of the developer. Another important aspect of the "convenience of the developer" is the ability to design visual interfaces, such as a dialog which contains windows controls (listboxes, editboxes, radio buttons, etc.), without sighted assistance, and have this interface appear aestheticly pleasing and have it function well. This type of programming is particularly difficult for blind programmers (often requiring the use of a purely visual dialog layout aplication, which is not accessible), in almost every programming environment. However, WE scripting has added "xml-based dialogs" which allow blind programmers to do such programming, and so developing a program with a user interface similar to the Windows standard model is made much easier.

Capabilities of WE scripts

One reason to write a WE script instead of a more usual type of program is to make it easier to develope the program, by making use of some unique window eyes capability. One such capability has already been mentioned: the XML dialog facility. WE scripts have many other unique abilities to work with; all of these together are known as the "window eyes object model".

This object model is documented in the WE scripting manual, but only by listing every possible object, property, or method in alphabetical order. A beginning scripter would therefore benefit from a higher-level overview, introducing capabilities in some logical order (such as simple to advanced), and grouped by similar functionality. All of these capabilities are usable in your programming language of choice, and they are made possible by Window Eyes making available an enormous library of objects, properties, and methods, via the Windows COM facility. How to use objects, properties, and methods are a topic for the learning of object oriented programming.

A script might be defined as any program which the Window Eyes script manager causes to be run, and by implication is running in order to make use of the WE object model. These programs are under the control of WE, and integrated with it because of WE having started them running. Another type of program, can make use of the WE object model, without having been started by the WE script manager. It can open the WE COM object in the normal way; either to obtain information or to control WE's behavior, but it will not be as tightly integrated with WE as a WE script, and there will need to be some other way to start it executing.

It is useful to know however that WE has configured 2 particular programming languages (VBScript and JavaScript) so that they are more tightly integrated with the WE object model than is normally the case. A script written in one of these 2 languages need not open the Window Eyes COM object model at all (it is done automatically), and are referred to as an "internal" scripts. All other scripts, which may be written in other programming languages, are referred to as "external" scripts, and must open the Window Eyes COM object in order to make use of it's object model. External scripts also have a few additional requirements, documented in the wiki article Internal and External Scripts.

Whether a script is internal or external is not immediately obvious in the list of scripts shown in the script manager, and it is of no importance to someone using the scripts in Window Eyes, only the developer need be concerned with the differences.

WE also has two types of scripts, based on when the script first starts running, and when it stops. These two types of scripts are explicitly differentiated in the script manager. You can either have a script start to run when window eyes starts, and optionally stay running as long as WE is running (referred to as a "global script"), or, have WE start a script when a particular program starts, and stop the script when the program closes down (referred to as an "application script"). All of these scripts are running concurrently, and independant of each other. One of your first decisions, when designing a script, will be whether it should run all the time (a global script), or only when a given application is running (an application script).

All of the script types listed above can draw on the WE object model in order to achieve their tasks, the differences in the types only concern what programming language is used, and when the script is run. Therefore, it is necessary that a scripter become familiar with the capabilities of the WE object model. Below are just some of the capabilities of the object model that scripts may make use of, listed in broad categories:

  • change any of the configuration settings within the WE control panel
  • control the speech (it's voice, rate, other parameters), and the braille display
  • define a hotkey, which can cause something to happen in your script (something spoken, something displayed, the window eyes environment is changed, etc.)
  • examine what text is in any window; watch for specific text to appear, or to change, and take some action (such as speaking it) through the WE speech
  • take some action when the user tabs to a new field, or perhaps when he presses a particular key (such as the arrow keys)
  • cause window eyes not to speak certain text it would otherwise speak, or to speak it differently
  • activate a particular window, or cause a particular control to have the focus
  • send keystrokes into a specific program, as if they were typed on the keyboard
  • open a dialog to get data from the user, and then process this data in some way


Finally, Starting to Write Some Code!

You should, by the time you reach this point, have an idea of what in particular you want a script to do, given what can be done, and you should also have an understanding of VBScript, as well as object oriented programming. If you don't know VBScript, you can still read on, but at some time, something that you don't understand, and didn't even know to ask about or look-up, will end up causing you a lot of grief if you try and learn VBScript by reading this and other articles.


Root Level Objects

If you're an experienced object-oriented programmer, you're used to opening THE COM object for some application, and storing it in a variable. Then, each time you go to make use of it you have to "dereference it" by using this variable which holds the COM object. When external scripts make use of the WE object model this is still the case; however, internal scripts need not do this. WE, in combination with the Windows Active Scripting facility, allows certain scripting languages, which are written for the Active Scripting facility, to make use of the WE object model without having to open it, and without having to dereference it. This means that all of the top-level properties and methods in the Application object of the WE object model can be used in your VBScript or JavaScript statements without specifying the WE application object and without use of the dereferencing operator which normally follows the object variable (in VBScript, this is the dot). These special objects are known as "root level" objects.

In addition to the Application object's methods and properties being "root level" objects, there are two other objects who themselves, like the Application object, have been given special status so that their properties and methods are also root level objects. These are the Speech and the Script objects.

using the methods of these 3 objects, which are at the root level, gives a script the appearance that many extra commands have been added to the VBScript language just for WE.

For example, if you wanted to use the SPEAK method of the SPEECH object, you would write something like the following:

set WE = createObject ("windoweyes.application")
WE.speech.speak "hello"

However, in the VBScript integrated with WE, you only have to write:

speak "hello"

That's it! The WE application COM object is already opened for you, along with the Speech and the Script objects, and their methods and properties are available to you as root level objects, which you do not need to dereference in order to use. The WE scripting documentation does indicate in the help topic for a given object if that object is a root level object, so that you can easily know when there is no need to dereference another object in order to use it.

Below is a list of root level objects; they are listed here so that you can more easily go into the scripting help documentation, and read more about them, and in particular their methods. I've found that anything which has been made into a root level object is something which you are likely to need much more frequently than the other hundred or so other objects:

  • application
  • braille
  • brailleDisplays
  • browseMode
  • clientInformation
  • clipBoard
  • clips
  • cursor
  • Dialog
  • INIFile
  • keyboard
  • menu
  • mouse
  • MSAAEventSource
  • OSVersion
  • profiles
  • screen
  • script
  • sharedObjects
  • speech
  • startupOptions
  • synthesizers
  • text
  • utilities
  • WEDialogs
  • WEPM

Creating Your First Script

This is a good time to read the entire first major section in the WE scripting help file. We are not going to cover all of the valuable info it contains, again, in this article. However, there is one point which could use attention: how do you create the file which is going to be your first script?

The manual gives you the explanation as to why it's helpful to store your scripting files in the default location for scripts. That way, when you see the list of scripts in the script manager, you don't have to hear the complete path to each one every time you arrow past it. If it's stored in the default directory for scripts, then you only have to hear it's name. Unfortunately, this default directory is very hard to find; one reason is that it's actual path is different for each user. This is because the default directory is in the current WE profile (and you can have more than one of those), and this in turn is stored as part of the directory tree which is your Windows user profile (and this is named based on your login name). In the end, it's a very long path string, and it's some trouble to get it right, and impossible for someone to tell you ahead of time exactly what it is.

So, what I do is to go to the file menu of the WE control panel, before I go into the script manager, and choose it's User Profiles choice. We're not in this dialog to create or change user profiles; however, there is also a command button in here, who's shortcut is alt-o, which opens the directory for your current WE profile. (The name of the menu choice is a little misleading; this dialog allows you to do things with WE profiles, and not Windows user profiles, which are a different set of directories).

So, when you pressed alt-o, or clicked on the open button, a Windows Explorer window opened for the directory which contains all your scripts by default, and this is now your active window. Since this is your firstscript, you need to create the file which will hold it, and then you need to tell the script manager to load it. once it's in the script manager's list of scripts, you can edit it in the future from the script manager (with the alt-I shortcut), and you need not open this directory again unless you need to create another new file, or delete one.

To create a new script file, which is just a text file, you choose the file menu, the new sub-menu, and the text file choice. Windows Explorer will then prompt you for the new file's name, with something like "new text document.txt" already filled in, if you were to just press enter without entering a name. If you start typing this will be wiped out, but later versions of windows will still preserve the .txt extension; you however want it to have a .vbs file extension (for VBScript), and so you will need to press shift-end, wich selects the text from your current location to the end of the line, and press delete to remove this file extension. now you can enter the file name with a .vbs extension and press enter. Windows will prompt you with a yes/no question, about being sure that you really want to change the file extension from .txt. Respond with alt-Y for yes, and you're done with the file creation.

you can now go into the script manager from the WE control panel by returning to the WE control panel, where you will find the WE profiles dialog has closed, and following the steps in the scripting manual alt-F, M, and M). There is some setup work for you to do in the script manager if this is your first time in it (configuring it to see additional options, and setting your default editor).

Your script is not yet shown in the list of scripts in the script manager, you will need to set your script display to "global", and then "load" your script (detailed in the scripting help manual). At this point, you should be able to find the newly created empty file in your list of scripts; you can now highlight it, and pressing alt-I will take you into your editor of choice so that you can actually create it.

When you finish creating your script, and close the editor, your script is configured to run by default, but it will not automatically run when you close your editor. So, to get it to run you will need to "reload" it with the alt-R command.

One more thing to take note of: you may not want this new script to run each time you startup WE, and so in order to keep it from doing so, you need to disable it. To disable it, just highlight it and press the alt-E shortcut (for the enable/disable button), and it's status will changed to disabled. You may want to do this before closing down WE.


Scripting Varius Types of Issues

The remaining portion of this article is going to focus on various problems or goals that scripting might solve, and show examples of how they may be done. In each case all the WE features used will be explained. I hope in this way to be able to demonstrate all the WE scripting features and capabilities. I plan to order the issues from simpler to more complex, but I believe it's important that you read them all, and not just the one which may pertain to your immediate plans.

Having Hotkeys Trigger a Script

Virtually all scripts have this in common: they start running atsome point,they perform their initialization, and then they go into a state where they are waiting for something to happen; usually that something ultimately is the user prforming some action. When a script is in this "wait state" the WE script manager will show it's status as "running", which is a little confusing as it's not actively doing anything, it's just waiting for something to happen.

If a script isn't in this wait state, then, if it's not actively executing, then window eyes will stop the script; it assumes it has completed (and the script manager will show it's status as "stopped"). If a script however is always executing, and never goes into a wait state, then it's very likely something is wrong with it's design, as there is no reason for a script to constantly execute, endlessly, unless perhaps you're calculating Pi out to forever! Unfortunately, when a script is constantly executing, WE is unable to stop it or shut it down. This is why the wait state is so important for a script, it then allows it to receive messages, information, and instructions from WE or the oprating system. This important point, that a script is not constantly executing, but is usually waiting for something to happen, is not one which is obvious to the new scripter.


Having a script wait for the user to press a particular global hotkey is a very common way for a script to enter this wait state. It relies on capabilities of the WE object model, which allow the script to tell WE what keystroke is the hotkey, and which of the scripts subroutines or functions should automatically be executed, when the hotkey is pressed. WE also supresses the keystroke so that Windows or any application doesn't see it, and try to react to it. When you have your script call a method, and pass it the name of one of your subroutines or functions which it is to cause to be executed, then this subroutine or function is known as a "callback". A callback is required to be defined in just the specific way that the method which you are calling specifies. that is, the method you call may specify in it's documentation that the callback should b a function, with 3 parameters, defined in this order ... and when that is the case, you cannot deviate from those instructions; you must create a function, with the specified parameters (except where they are described as being optional), which returns the specified data, if you want to use the method.

In this case, the method you need to use in order to have your script respond to a hotkey is the registerHotKey method of the keyboard object. once you know this, you go to the scripting help file and lookup objects, the keyboard object, and under it methods, and finally the registerHotKey method. in it's documentation will be a specification as to how you will need to setup your callback routine for this method to use. Here is an example from the scripting help file:

' this example is a fully functional script.
dim registeredKey 
Set registeredKey = keyboard.registerHotKey("Control-Shift-Windows-", "SpeakHelloWorld")

Sub SpeakHelloWorld()
      Speak "Hello world!"
End Sub

Items to note about this example are:

  • this is a complete and fully functional script.
  • the speak method was able to be used without specifying the application object, or it's parent object, because those objects are root level objects (the parent object of the speak method is the speech object).
  • the result of the call to the registerHotkey method must be stored in a variable, and this variable must be a global variable, in order for the hotkey to continue functioning. if the variable holding the result is destroyed, such as when it's a local variable and the subroutine or function ends, then the hotkey will stop functioning. this is not the only method which relies on it's result being stored in a global variable, and so you will need to pay attention to the documentation of each method for this requirement. Actually, it's not only that it keeps the hotkey functioning which is important; WE examines each script to see if it's waiting on anything, in order to decide if it's done executing and should be stopped. with the result of the registerHotkey method being stored in a global variable, this satisfies the WE requirement of "waiting on something", and so the script will be kept executing in memory, instead of being stopped. in your callback routine for example, if you were to set the global variable to nothing, destroying the result of registerHotkey, then when you returned from the callback the script would terminate.
  • the result of the registerHotkey method is an object, and because it's being stored in a variable, you must use the "set" command to do so, instead of just assigning it directly to the variable.
  • the hotkey being registered only remains registered as a hotkey for this session of WE running; it is not saved permanently anywhere.
  • as a general rule, you should not hard-code the name of the hotkey you wish to use directly into the registerHotkey command; this does not give the user the opportunity to change it to anything else. see the section on the GWToolkit for a collection of functions and subroutines which will make it much easier for you to store the hotkey name in a file, and to allow the user to change it.
  • even though this script uses the Speak method, it works with braille displays as well; the Speak method also displays any text on the braille display (for 2 seconds), and has no trouble if you're not running a speech synthesizer at all.

Writing a Script to Manipulate the Data in the Window of Another Program

Using Shared Objects and the GWToolkit to Make Scripting Easier

Having an event (such as an Action of Windows) Trigger a Script

Being Able to Localize a Script Using XML

Using the WEScripting Framework to Help Develop Your Script

Using MSAA to Obtain Information as to What Another Program is Doing

Adding Dialogs With Menus and Controls to Your Script

See the wiki article User Interface Techniques.


Text Size:
Decrease Text Size Increase Text Size

Personal tools

Powered by MediaWiki
Public Domain
© 2013 GW Micro, Inc. All Rights Reserved.
GW Micro, Inc.    725 Airport North Office Park    Fort Wayne, IN 46825
Ph: 260-489-3671 Fax: 260-489-2608    www.gwmicro.com    sales@gwmicro.com    support@gwmicro.com
Hours: M-F, 8a-5p, EDST