Beta 0.74
September 22, 2009

Copyright 2009 by Jamal Mazrui
GNU Lesser General Public License (LGPL)

Contents

Overview

The word "Homer" is a brand name I sometimes use for developer tools I create. Homer.NET is a set of developer tools for the .NET platform. It supports rapid application development with many convenience functions for accessing Internet data, creating GUI forms, and using screen reader APIs. Development may be done with command-line utilities and a text editor -- no integrated development environment (IDE) is required.

I suggest unarchiving hnsetup.zip into a new directory, e.g.,
C:\Homer.NET

There are three assemblies that define types in the Homer namespace. HomerJax.dll defines the Jax class containing static methods for accessing Internet resources. HomerAcc.dll defines the Acc class containing static methods for producing speech through an active screen reader, and other accessibility-related tasks. HomerLbc.dll implements classes for creating Windows forms conveniently via "Layout by Code" rather than a visually-oriented designer.

The Lbc class has static methods for a variety of canned dialogs. The LbcForm class inherits from System.Windows.Forms.Form, and has instance methods and properties for adding controls to a form, which may be either a modal dialog or a modeless window. The LbcForm class and its members are used to build the canned dialogs of the Lbc class, thereby showing the power of this API and illustrating working code.

JaxForm.exe is an interpreter for source code files written in JScript .NET. Such code can access any of the Homer.NET functionality. JaxFormW.exe is a Windows-only version that does not use a console mode environment. That environment is useful when developing and debugging a .js script (e.g., the print function), but often not appropriate at the production stage.

Interactive JScript (InJs) is a REPL (read execute print loop) environment for testing JScript expressions, including functionality of Homer.NET. Load the program by running InJs.exe.

Batch files starting with the word "Compile" build the Homer.NET assemblies from source code using compilers provided with the .NET 2.0 SDK. Batch files beginning with the word "Run" execute a JScript .NET file dynamically. The .js files illustrate functionality of Homer.NET.

Samples of Homer.NET include compiled C# and VBNET fruit basket programs implemented with Layout by Code. A more sophisticated sample is executed with JaxForm via RunLbcDemo.bat. It includes a tip on the status line for each control and a menu system. All of this is done without any need to reference pixel coordinates for location or size. More specific layout information could be added if desired.

RunJaxDemo.bat illustrates HomerJax functionality, including how you can easily get the content type, source HTML, or plain text of a web page; how you can download a file to disk, how you can translate between languages via the Google API; how you can read recent RSS items from AccessibleWorld.org; how you can list MP3 files from AccessibleWorld.org; how you can get messages from the public timeline of Twitter.com, or poast a tweet if you have a Twitter account. The demo shows how data is converted from JavaScript Object Notation (JSON) to what I call COM exchange format, and how XML data may be conveniently accessed as well.

The functionality and documentation of Homer.NET will improve over time in response to comments, questions, and suggestions. Code contributions are also welcome.

COM Exchange Format

The Component Object Model (COM) is a set of Windows standards by which different programming languages and applications can communicate. COM uses a flexible data type called a variant, which can be an individual value, array of values, or complex object with methods, properties, and events. In general, any COM client can use string, numeric, and COM objects as the data types of parameters or return values. Some, however, cannot use arrays. COM exchange format is intended to support collections, as well as primitive data types, for use by any COM client. Rather than an array, a list COM object is used from the .NET Framework (any version). A COM object dictionary is also used from the Windows Script Host.

HomerJax includes a method called JsToVt, which converts data in JSON format to variant types understood by VBScript (and any COM client language). JavaScript arrays are converted to COM objects with the progID "System.Collections.ArrayList." The methods and properties of this object are documented at
http://msdn.microsoft.com/en-us/library/system.collections.arraylist.aspx

JavaScript objects, which are like dictionaries, are converted to COM objects with the progID "Scripting.Dictionary." This object is documented at
http://msdn.microsoft.com/en-us/library/x4k5wbx4(VS.85).aspx

In Visual Basic and other languages, either of these types of object collections may be iterated with the "For Each" statement. These objects have an "Item" method, which is the default COM method of the object, so syntax can succinctly referr to items without even using the "Item" keyword (just using an integer element of a list or string key of a dictionary enclosed in parentheses). The code of the demo program illustrates this in getting public messages from Twitter.

HomerJax includes various methods for converting between JavaScript Object Notation (JSON), variant data types, and COM exchange format. This provides much flexibility for accessing data on the Internet.

HomerJax

HomerJax is a library of convenience functions for accessing Internet resources. It is written in JScript, the Microsoft version of JavaScript, and is dependent on several COM servers distributed with Windows. The word "Jax" derives from Ajax, which originally meant "Asynchronous JavaScript and XML." Ajax technologies focus on building dynamic user interfaces in web browsers. HomerJax functions use some of these core technologies, but focus on reading, interpreting, and writing data from the Internet.

Since the Internet is a great source of accessible information for people with visual disabilities who cannot readily read the printed word, my hope is that this library makes it easier for developers, including blind ones like myself, to build applications that take advantage of new social networking sites such as Twitter, FaceBook, and many others. I intend for HomerJax to be accessible via various programming environments, including the Windows Script Host, screen reader scripting languages, and other programming languages via a COM server interface.

HomerJax methods are divided into categories indicated by a prefix at the beginning of their names: Dialog, File, Folder, Html, Js, Path, RegExp, Registry, String, Vt, Web, and Xml. By convention, HomerJax variable names use lower case prefixes to indicate the data type: s for string, i for integer, n for floating point number, l for list, d for dictionary, and o for other COM object. Method and variable names use upper camel case (like the .NET Framework), e.g., XmlGetValue rather than XMLGetValue. JavaScript is a case-sensitive language, so methods need to be called with appropriate capitalization.

Here is a summary of HomerJax methods:

DialogConfirm(sTitle, sMessage, sDefault) = Get choice from a standard Yes, No, or Cancel message box

DialogInput(sTitle, sField, sValue) = Get input from a single edit box

DialogShow(oTitle, oMessage) = Show string version of two parameters in the title && prompt of a message box

FileCopy(sSource, sTarget) = Copy source to destination file, replacing if it exists

FileDelete(sFile) = Delete a file if it exists, && test whether it is subsequently absent
either because it was successfully deleted || because it was!present in the first place

FileExists(sFile) = Test whether File exists

FileGetDate(sFile) = Get date of a file

FileGetSize(sFile) = Get size of a file

FileGetType(sFile) = Get file type

FileMove(sSource, sTarget) = Move source to destination file, replacing if it exists

FileToString(sFile) = Get content of text file

FolderCopy(sSource, sTarget) = Copy source to destination Folder, replacing if it exists

FolderCreate(sFolder) = Create folder

FolderDelete(sFolder) = Delete a Folder if it exists, && test whether it is subsequently absent
either because it was successfully deleted || because it was!present in the first place

FolderExists(sFolder) = Test whether folder exists

FolderGetDate(sFolder) = Get date of a Folder

FolderGetSize(sFolder) = Get size of folder, summing the sizes of files && subfolders it contains

FolderMove(sSource, sTarget) = Move source to destination Folder, replacing if it exists

HtmlEncodeString(sText) = Encode a string for HTML or XML

HtmlGetLinks(sUrl) = Get a list of two-item lists containing the URL and text of a link

HtmlGetTableText(sUrl, iTable) = Get the text of an HTML table specified by number, or null for all of them

HtmlGetText(sUrl) = Get the text of an HTML page

HtmlGetUrls(sUrl) = Get a list of URLs linked to a web page

JsDictionaryToEncodedString(d) = Convert dictionary to string with http encoding
var sReturn = ''
for (var sKey in d) = var sValue = d[sKey]
var sComponent = encodeURIComponent(sKey) + '=' + encodeURIComponent(sValue) = if (sReturn.length > 0) sReturn += '&'
sReturn += sComponent
} return sReturn
} JsDictionaryToEncodedString method

JsEval(sCode, o1, o2, o3, o4) = Evaluate sCode, optionally referencing up to 4 parameters of any type, and return the result

JsInitArray(oValue, iLength) = var aReturn = []
for (var i = 0; i < iLength; i++) aReturn[i] = oValue
return aReturn
} JsInitArray method

JsIsBlank(sText) = Test if string is empty or white space

JsIsMute(o) = test for empty string

JsIsNull(o) = Test for null

JsIsObject(o) = Test for object

JsIsUndefined(o) = Test whether object is undefined

JSNumber(o) = Convert to JScript number

JsObjectToVt(oValue) = Convert JScript object to variant

JsPrint(o) = Print to screen using console mode of Windows Script Host

JsPrintObject(sName, oValue) = Print type of object and its subobjects

JsSplit(sText, sDelimiter) = Split but ensure an empty array for empty text

JsSplitLines(sText) = JsSplit by line feeds after chomping

JsString(o) = Convert to a JScript string

JsToVt(sJs) = Convert string in JavaScript Object Notation to COM exchange format

PathCombine(sFolder, sName) = Combine folder and name to form a valid path

PathCreateTempFolder() = Create temporary folder && return its full path

PathExists(sPath) = Test whether path exists

PathGetBase(sPath) = Get base/root name of a file or folder

PathGetCurrentDirectory() = Get current directory of active process

PathGetExtension(sPath) = Get extention of file || folder

PathGetFolder(sPath) = Get the parent folder of a file or folder

PathGetInternetCacheFolder() = Get Windows folder for temporary Internet files

PathGetLong(sPath) = Get long name of file or folder

PathGetName(sPath) = Get the file or folder name at the end of a path

PathGetShort(sPath) = Get short path (8.3 style) of a file or folder

PathGetSpec(sDir, sWildcards, sFlags) = Get a list of paths, specifying folder, wild card pattern, && sort order

PathGetTempFile() = Get full path of a temporary file

PathGetTempFolder() = Get Windows folder for temporary files

PathGetTempName() = Get Name for temporary file || folder

PathGetValid(sDir, sBase, sExt, bUnique) = var sIllegal = "&=@%*+\\|':'<>/?" + xQuote
var sViewable = "!#$%&'()*+,-./0123456789:'<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz|}~"
var sPrintable = xSpace + sViewable

PathSetCurrentDirectory(sDir) = Set current directory of active process, and return previously current directory

RegExpContains(sText, sMatch, bIgnoreCase) = /*
Get Array containing the starting index and text of the first match of a regular expression
where sText is the string to search
sMatch is the regular expression to match
bIgnoreCase indicates whether capitalization matters
*/

RegExpContainsLast(sText, sMatch, bIgnoreCase) = /*
Get list containing the starting index and text of the last match of a regular expression
where sText is the string to search
sMatch is the regular expression to match
bIgnoreCase indicates whether capitalization matters
*/

RegExpCount(sText, sMatch, bIgnoreCase) = /*
Count matches of a regular expression
where sText is the string to search
sMatch is the regular expression to match
bIgnoreCase indicates whether capitalization matters
*/

RegExpExtract(sText, sMatch, bIgnoreCase) = /*
Get list containing matches of a regular expression
where sText is the string to search
sMatch is the regular expression to match
bIgnoreCase indicates whether capitalization matters
*/

RegExpReplace(sText, sMatch, sReplace, bIgnoreCase) = /*
Replace text matching a regular expression
where sText is the string to search
sMatch is the regular expression to match
sReplace is the replacement text
bIgnoreCase indicates whether capitalization matters
*/

RegExpTest(sText, sMatch, bIgnoreCase) = /*
Test match of a regular expression
where sText is the string to search
sMatch is the regular expression to match
bIgnoreCase indicates whether capitalization matters
*/

RegistryGetString(iRootKey, sSubKey, sValueName) = Get a string from registry

RegistryRead(sKey) = Get a string from the registry

RegistrySetString(iRootKey, sSubKey, sValueName, sValueData) = Set a registry string

RegistryWrite(sKey, sValue) = Write a string to the registry

ShellCreateShortcut(sFile, sTargetPath, sWorkingDirectory, iWindowStyle, sHotkey) = Create a .lnk or .url file

ShellExec(sCommand) = Run a console mode command && return its standard output

ShellExecute(sFile, sParams, sFolder, sVerb, iWindowStyle) = Execute a command with a verb like RunAs

ShellExpandEnvironmentVariables(sText) = Replace environment variables with their values

ShellGetEnvironmentVariable(sVariable) = Get the value of an environment variable

ShellGetShortcutTargetPath(sFile) = Get the target path of a shortcut file

ShellGetSpecialFolder(vFolder) = Get a special Windows folder

ShellInvokeVerb(sPath, sVerb) = Invoke a verb on a file or folder

ShellOpen(sPath) = Open a file or folder with the default program associated with its type

ShellOpenWith(sExe, sParam) = Open a program with a file

ShellRun(sFile, iStyle, bWait) = /*
Launch a program or file, indicating its window style && whether to wait before returning
window styles:
0 Hides the window && activates another window
1 Activates && displays a window. If the window is minimized || maximized, the
system restores it to its original size && position. This flag should be used
when specifying an application for the first time
2 Activates the window && displays it minimized
3 Activates the window && displays it maximized
4 Displays a window in its most recent size && position. The active window
remains active
5 Activates the window && displays it in its current size && position
6 Minimizes the specified window && activates the next top-level window in the Z
order
7 Displays the window as a minimized window. The active window remains active
8 Displays the window in its current state. The active window remains active
9 Activates && displays the window. If it is minimized || maximized, the system
restores it to its original size && position. An application should specify
this flag when restoring a minimized window
10 Sets the show state based on the state of the program that started the
application
*/

ShellRunCommandPrompt(sDir) = Open a command prompt in the directory specified

ShellRunExplorerWindow(sDir) = Open Windows Explorer in the directory specified

ShellWait(sPath) = Run a program and wait for it to return

StringAppendToFile(sText, sFile, sDivider) = Append string to File, omitting divider if the first one

StringChomp(sText) = Chop \n for both ends of a string

StringChopLeft(sText, iCount) = Remove iCount characters from left of sText

StringChopRight(sText, iCount) = Remove iCount characters from Right of sText

StringContains(sText, sMatch, bIgnoreCase) = Test if a string is contained in another

StringConvertToMacLineBreak(sText) = Convert to Macintosh line break, \r

StringConvertToUnixLineBreak(sText) = Convert to Unix line break, \n

StringConvertToWinLineBreak(sText) = Convert to standard Windows line break, \r\n

StringCount(sText, sMatch) = Count occurrences of a string within another string

StringEndsWith(sText, sSuffix, bIgnoreCase) = Test whether first string ends with second one

StringEqual(s1, s2) = Test if two strings are exactly equal

StringEquiv(s1, s2) = Test whether two strings are the same except for capitalization

StringGetASCII(sText) = Get space delimited ASCII codes for characters in string

StringLeft(sText, iCount) = Return leftmost characters of a string

StringLength(sText) = Return length of a string

StringLower(sText) = Convert string to lower case

StringPlural(sItem, iCount) = Return singular || plural form of a string, depending on whether count equals one

StringQuote(sText) = Quote a string

StringReplace(sText, sMatch, sReplace, bIgnoreCase) = Replace text

StringReplaceAll(sText, sMatch, sReplace, bIgnoreCase) = Replace all occurrences of a string within another

StringRight(sText, iCount) = Return rightmost characters of a string

StringSlice(sText, iStart, iEnd) = return sText.slice(iStart, iEnd) = } StringSlice method

StringToFile(sText, sFile) = Saves string to text file, replacing if it exists

StringToList(sText, sDelimiter) = Convert string with specified delimiter to list

StringTrim(sText) = Trim white space from both ends of a string

StringTrimLeft(sText) = Trim white space from left end of a string

StringTrimRight(sText) = Trim white space from right end of a string

StringUnquote(sText) = Unquote a string

StringUpper(sText) = Convert string to upper case

StringWrap(sText, iMaxLine) = var aLines, aWords
var i, j
var sReturn, sLines, sLine, sWords, sWord

UrlCreate(sProtocol, sHost, sPath, sQuery) = Create a URL from components

UrlGetBaseDomain(sUrl) = Get base domain of a URL

UrlGetExtension(sUrl) = Get extension of a URL

UrlGetFile(sUrl) = Get file of a URL

UrlGetFolder(sUrl) = Get folder of a URL

UrlGetFragment(sUrl) = Get fragment of a URL

UrlGetHost(sUrl) = Get subdomain and domain of a URL

UrlGetPath(sUrl) = Get path of a URL

UrlGetPathPlus(sUrl) = Get path and fragment or query of a URL

UrlGetPrePath(sUrl) = Get part of URL before path

UrlGetProtocol(sUrl) = Get protocol of URL

UrlGetQuery(sUrl) = Get query of URL

UrlGetSubdomain(sUrl) = Get subdomain of a URL

UrlNormalize(sUrl, sBase) = Normalize a URL for comparison

VtArrayToJs(a) = Convert variant array to JScript

VtArrayToList(a) = Convert variant array to list

VtCopyDictionary(dItems) = Copy a dictionary

VtCopyList(lItems) = Copy a list

VtCreateDictionary() = Return a variant dictionary

VtCreateFileSystemObject() = Return a file system object

VtCreateHtmlFile() = Create a variant HTMLFile object

VtCreateInternetExplorerApplication() = Return an Internet Explorer object

VtCreateList() = Create a variant list object

VtCreateRecordSet() = var oRs = Interaction.CreateObject('ADODB.RecordSet') = oRs.CursorLocation = adUseClient
return oRs
} VtCreateRecordSet method

VtCreateShellApplication() = Return a Shell.Application object

VtCreateStream() = Return an ADODB.Stream object

VtCreateVBScriptControl() = Return MSScriptControl.ScriptControl object

VtCreateWebRequest() = Create web request object

VtCreateWScriptShell() = Return WScript.Shell object

VtCreateXmlDocument() = Return an XML document

VtDateToJs(dt) = Convert a variant date to JScript

VtDictionaryKeysToJs(d) = Convert variant array of dictionary keys to JScript array

VtDictionaryKeysToList(d) = Convert variant array of dictionary keys to list

VtDictionaryToJs(d) = Convert a variant dictionary to JScript

VtDictionaryToXml(dItems, sFile) = Save dictionary to XML file

VtEvalVbs(sCode, dParams) = Evaluate VBScript code and return the result

VtEvalVbsParam(sCode, vParam) = Evaluate VBScript code and return result, passing single argument

VtGetWMIObject() = Get WMI object

VtInitDictionary(vValue) = Create a variant dictionary and initialize it with a single key/value pair

VtInitXmlDocument(sXml) = Create and initialize an Xml document with a string of XML

VtListFilterByExtension(lPaths, lExtensions) = Get a subset from a list of paths that match an extension

VtListFilterByRegExp(lItems, sMatch, bIgnoreCase) = Return list of matches of a regular expression

VtListFilterByWildcard(lItems, sMatch) = Return list of matches of a wildcard filter expression

VtListGetExtensions(lPaths) = Get a list of extensions from a list of paths, converting to lower case, removing duplicates, and sorting

VtListToJs(l) = Convert variant list to JScript array

VtListToString(lItems, sDelimiter) = Convert a list to a string with a specified delimiter

VtSleep(iMilliseconds) = var sCode = 'Sleep(d("v"))'
return VtEvalVbsParam(sCode, iMilliseconds) = } VtSleep method

VtTrim(sText) = Trim space from both ends of a string

VtTypeName(vVariant) = Get variant subtype

WebFetch(dParams) = Fetch files from web according to specifications in dictionary of parameters

WebListDownload(lUrls, sFolder, bUnique) = Download a list of URLs, specifying folder and whether to ensure unique file names

WebRequest(sType, sUrl, dData, dHeaders, sUser, sPassword) = Send a web request and return the response

WebRequestGet(sUrl, dData, dHeaders, sUser, sPassword) = Send a get request

WebRequestGetToFile(sUrl, dData, dHeaders, sUser, sPassword, sFile) = Send a get request and save response to file

WebRequestGetToString(sUrl, dData, dHeaders, sUser, sPassword) = Send a get request and return response as string

WebRequestHead(sUrl, dData, dHeaders, sUser, sPassword) = Send a head request

WebRequestHeader(sUrl, sHeader) = Get response header

WebRequestPost(sUrl, dData, dHeaders, sUser, sPassword) = Send a post request

WebRequestPostToFile(sUrl, dData, dHeaders, sUser, sPassword, sFile) = Send a post request and save response to file

WebRequestPostToString(sUrl, dData, dHeaders, sUser, sPassword) = Send a post request and return response as string

WebRequestToFile(sType, sUrl, dData, dHeaders, sUser, sPassword, sFile) = Save web resource to file

WebRequestToString(sType, sUrl, dData, dHeaders, sUser, sPassword) = Return web resource as string

WebUrlContentEncoding(sUrl) = Get encoding of a web resource

WebUrlContentLanguage(sUrl) = Get natural language code of a web resource

WebUrlContentLength(sUrl) = Get content length of a web resource

WebUrlContentLocation(sUrl) = Get redirected location of a web resource

WebUrlContentType(sUrl) = Get content type of a web resource

WebUrlDownloadPath(sUrl, sFolder, bUnique) = /Get file from URL, trying various techniques

WebUrlFileName(sUrl) = Get suggested file name of a web resource

WebUrlIsHtml(sUrl) = Test whether content type is text/html

WebUrlLastModified(sUrl) = Get last modification time stamp of a web resource

WebUrlServer(sUrl) = Get server name and version

WebUrlToFile(sUrl, sFile) = Save web resource to file

WebUrlToString(sUrl) = Return web resource as string

WebUrlToXml(sUrl) = Return web resource as XML document

XmlAppendElement(oParent, sName, sValue) = Append element to a node

XmlCreateElement(oNode, sName, sValue) = Create an XML element

XmlCreateFile(sFile) = Create a root XML file

XmlEnsureGetNode(sFile, sPath) = Return a node, creating preceding elements if necessary

XmlEnsureOpenFile(sFile) = Open an XML file, creating it if necessary

XmlGetAttribute(sFile, sPath, sAttribute, sDefault) = Get an attribute of a node

XmlGetNode(sFile, sPath) = Get a node

XmlGetNodeNames(sFile, sPath) = Get node names

XmlGetNodes(sFile, sPath) = Get a node list

XmlGetText(sFile, sPath, sDefault) = Get the text of a node

XmlGetValue(sFile, sPath, sDefault) = Get the value of a node

XmlOpenFile(sFile) = Open an XML file

XmlRemoveAttribute(sFile, sPath, sAttribute) = Remove an attribute

XmlRemoveNode(sFile, sPath) = Remove a node

XmlRemoveNodes(sFile, sPath) = Remove a node collection

XmlSetAttribute(sFile, sPath, sAttribute, sText) = Set an attribute

XmlSetText(sFile, sPath, sText) = Set text of an element

XmlSetValue(sFile, sPath, sValue) = Set a value

XmlToVtDictionary(sFile) = Convert XML file to variant dictionary

HomerAcc

HomerAcc enables an application to produce direct speech messages via the API of an active screen reader. If JAWS, System Access, or Window-Eyes is detected in memory, its API is used to speak a string of text with a call to Acc.Say. Any data type may be passed to this method, causing its string representation to be spoken.

Here is a summary of HomerAcc methods:

bool Say(object oText) = Say the string version of an object using JAWS, System Access, or Window-Eyes

bool IsScreenReaderActive() = Test whether a screen reader is active

bool IsJAWSActive() = Test whether JAWS is active

bool IsWinEyesActive() = Test whether Window-Eyes is active

int JFWRunFunction(string sText) = Run a JAWS function from the current application or default scripts

int JFWRunScript(string sText) = Run a JAWS script from the current application or default scripts

bool JAWSSay(string sText) = Say text with JAWS

bool IsSAActive() = Test whether System Access is active

bool SASay(string sText) = Say text with System Access

bool WESay(string sText) = Say text with Window-Eyes

bool SAPISay(string sText) = Say text with the default SAPI voice

object GetProperty(object o, string sProperty) = Get a COM property

object GetProperty(object o, string sProperty, object[] args) = Get a COM property

object CallMethod(object o, string sMethod, string sValue) = Call a COM method

object CallMethod(object o, string sMethod, int iValue) = Call a COM method

object CallMethod(object o, string sMethod, object[] args) = Call a COM method

HomerLbc

To create a form with Layout by Code, take the following steps:
* Instantiate an LbcForm object. For technical reasons, although this class may be used directly in a script passed to JaxForm, it must be inherited from when creating assemblies with other .NET languages. Also, a JaxForm script may pass parameters to the constructor, whereas other code must call an Init method as a seperate step. See FruitBasket.cs, FruitBasket.vb, and FruitBasket.js for examples.

The Init method takes three parameters corresponding to the title of the form, the name of the event handler to use, and a dictionary of tips to appear on the status line when each control has focus. In general, parameters of LbcForm methods are optional, and an intelligent default is chosen if null (Nothing in VB) is passed as a value.

* Add controls to the form. These instance methods start with the word "Add," and and optionally specify data for the control. If a control does not have a caption, itself, a convenience method exists that adds a label to the left of the control. For example, a TextBox could be added to a dialog with the syntax
dlg.AddTextBox(sText)

A labeled TextBox could be added with the syntax
dlg.AddInputBox(sLabel, sText)

The following controls are available: Button, CheckBox, CheckedListBox (multiple-selection ListBox with checkable items), DatePicker, ListBox, MaskedTextBox (TextBox with a configurable template to control input), MultiListBox (multiple-selection ListBox), Memo (multi-line TextBox), NumericUpDown, ProgressBar, RadioButton, TextBox, and TimePicker.

* Add controls to the form in placement order from top to bottom and left to right. Lbc arranges a form as a series of horizontal bands of controls. The last and lowest band is a centered set of buttons such as OK and Cancel. Lbc automatically adds a status bar at the bottom of the window. You can add a menu system at the top of the window by using the AddMenu and AddMenuItem methods before adding controls to the form. Menu items can include an accelerator key for activating a command directly. Use the AddBand method to start a new horizontal band of controls. This is analagous to pressing Enter to start a new line of text.

* Call the CompleteDialog method for a modal dialog or the CompleteWindow method for a modeless window. There are two possible parameters: an array of button names and a number indicating which control should initially have focus. The buttons are placed in a new, centered band at the bottom of the form. If no button array is passed, OK and Cancel buttons are assumed. Other finalization tasks are performed before displaying and activating the form. To complete the form without creating a button band, pass an empty button array.

* In general, all events that need to be monitored are passed to the event handler specified at the start of the form creation process. If no event handler is specified, the default is one called "OnEvent." The event handler has three parameters corresponding to the event name, control that sent the event, and object with properties indicating any additional arguments passed back by the event. Typically, events are managed within a switch block that checks for the event name, and then within another switch block that checks for the control name. The following events are automatically monitored: Click, Closing, GotFocus, Load, SelectedIndexChanged (for a ListBox), and Shown. If a BackGroundWorker component is used, the DoWork, ProgressChanged, and RunWorkerCompleted events are also supported. For technical reasons, the event handler must have public scope.

Lbc automatically assigns a name to each control added to the form. The name has two parts seperated by an underscore character (_): the class of the control and the label of the control. To ensure unique names, make sure that two controls of the same type do not also have the same label. For example, the label of a labeled TextBox would be a pair of controls with the names Label_Search and TextBox_Search. Lbc automatically appends a colon (:) to a label if one is not specified. It automatically prepends an ampersand (&) if none is specified, thereby making the initial letter the default access key of the control (so the control can be focused or activated with Alt+Letter). An Lbc form has a property called Names, which is a dictionary that associates control names and control objects. Thus, you can get a reference to a TextBox with syntax likeTextBox txt = dlg.Names["TextBox_Search"];

Here is a summary of HomerLbc methods:

DialogBrowseForFolder(sTitle, sDir) = Get a folder path to browse

DialogChoose(sTitle, aButtons, iFocus) = Choose a button

DialogConfirm(sTitle, sMessage, sDefault) = Confirm the answer to a Yes/No question

DialogDatePicker(sTitle, sLabel, dtValue, dtMinValue, dtMaxValue) = Pick a date value

DialogInfo(sTitle, sLabel, sText) = Show multiple lines of scrollable information

DialogInput(sTitle, sName, sValue) = Input a value

DialogInputAndChoose(sTitle, sName, sValue, aButtons, iFocus) = Input a value and choose a button

DialogMemo(sTitle, sLabel, sText) = Edit a multiline memo

DialogMultiCheck(sTitle, sLabel, aNames, aValues, aSelect, bSort, iIndex) = Check multiple values

DialogMultiInput(sTitle, aNames, aValues, iFocus) = Input multiple values

DialogMultiPick(sTitle, sLabel, aNames, aValues, aSelect, bSort, iIndex) = Pick multiple values

DialogOpenFile(sTitle, sPath) = Get a file path to open

DialogOpenFolder(sTitle, sFolder) = Get a folder path to open

DialogPick(sTitle, sLabel, aNames, aValues, bSort, iIndex) = Pick a value

DialogPickAndChoose(sTitle, sLabel, aNames, aValues, bSort, iIndex, aButtons, iFocus) = Pick a value and choose a button

DialogPickInputAndChoose(sTitle, sLabel, aNames, aValues, bSort, iIndex, sName, sValue, aButtons, iFocus) = Pick a value, input a value, and choose a button

DialogSaveFile(sTitle, sPath) = Get a file path to save

DialogShow(oTitle, oMessage) = Show two values in the title and message of a message box

DialogTimePicker(sTitle, sLabel, dtValue, dtMinValue, dtMaxValue) = Pick a time value

Init() = Initialize values for code, import, and export files

StringToKey(sKey:String):Keys
Convert a string to a Keys object

LbcDialog() = Instantiate an LbcDialog

LbcDialog(sTitle, sHandler, dFocusStatus) = Instantiate an LbcDialog, passing values for its title, event handler, and status messages

Init(sTitle, sHandler, dFocusStatus) = Initialize an LbcDialog

AddBand() = Start a new band of controls

AddButton(sText):Button
Add a button

AddButtonBand(aButtons) = Add a centered band of buttons

AddCheckBox(sText, bState):CheckBox
Add a checkbox

AddCheckedListBox(aItems, aSelect, bSort, iIndex):CheckedListBox
Add a checked listbox

AddInputBox(sLabel, sText):Control[]

AddComboBox(aItems, bSort, iIndex):ComboBox
Add a combobox

AddComboPickBox(sLabel, aItems, bSort, iIndex):ComboBox
Add a labeled combobox

AddDatePicker(dtValue, dtMinValue, dtMaxValue):DateTimePicker
Add a date picker

AddDatePickerBox(sLabel, dtValue, dtMinValue, dtMaxValue):DateTimePicker
Add a labeled date picker

AddInputBox(sLabel, sText):TextBox
Add a labeled TextBox

AddMemoBox(sLabel, sText, bReadOnly):RichTextBox

AddLabel(sText):Label
Add a label

AddListBox(aItems, bSort, iIndex):ListBox
Add a listbox

AddMemo(sText, bReadOnly):TextBox
Add a multiline memo

AddMemoBox(sLabel, sText, bReadOnly):TextBox
Add a labeled memo

AddPickBox(sLabel, aItems, bSort, iIndex):Control[]

AddMenu(sText):ToolStripMenuItem
Add a menu pulldown

AddMenuItem(sText, oKeys):ToolStripMenuItem
Add a menu item and accelerator key

AddMultiCheckBox(sLabel, aItems, aSelect, bSort, iIndex):CheckedListBox
Add a labeled checked listbox

AddMultiListBox(aItems, aSelect, bSort, iIndex):ListBox
Add a multiple selection listbox

AddMultiPickBox(sLabel, aItems, aSelect, bSort, iIndex):ListBox
Add a labeled multiple selection listbox

AddComboPickBox(sLabel, aItems, bSort, iIndex):Control[]

AddPickBox(sLabel, aItems, bSort, iIndex):ListBox
Add a labeled listbox

AddRadioButton(sText, bState):RadioButton
Add a RadioButton

AddStatus(sText) = Append status text

AddStatusBar():StatusStrip
Add a status bar

AddTextBox(sText):TextBox
Add a textbox

AddMemo(sText, bReadOnly):RichTextBox

AddTimePicker(dtValue, dtMinValue, dtMaxValue):DateTimePicker
Add a time picker

AddTimePickerBox(sLabel, dtValue, dtMinValue, dtMaxValue):DateTimePicker
Add a labeled time picker

AddMultiCheckBox(sLabel, aItems, aSelect, bSort, iIndex):Control[]

CollectionToArray(oCollection) = Convert a collection to an array

CompleteDialog(aButtons, iFocus):Button[]
Complete a dialog with a button band and focus position

CreateFlowPanel(direction) = Create a FlowLayoutPanel

CreateHorizontalPanel() = Create a horizontal FlowLayoutPanel

CreateMainMenu():MenuStrip
Create the main menu of the dialog

CreateMenu(sText) = Create a menu pulldown

CreateMenuItem(sText, sKey) = Create a menu item

CreateTablePanel(iColumns, iRows) = Create a TableLayoutPanel

CreateVerticalPanel() = Create a vertical FlowLayoutPanel

CurrentBand() = Return the current band number

CurrentControl() = Return the control last added

CurrentMenu() = Return the menu pulldown last added

CurrentMenuItem() = Return the menu item last added

Export(sFile) = Export data from a file into controls of the current dialog

FindControl(sClass) = Find the first control with a class name

GetClass(ctl) = Get the class of a control

GetFocus() = Get the control with focus

GetStatus() = Get status text

HandleClick(oSender:Object, oArgs:EventArgs) = Handler for Click event

HandleClosing(oSender:Object, oArgs:CancelEventArgs) = Handler for Closing event of a dialog

HandleDialogChoose(sEvent, oSender, oArgs) = Custom event handler for Choose dialog

HandleDialogDatePicker(sEvent, oSender, oArgs) = Custom event handler for date picker dialog

HandleDialogInfo(sEvent, oSender, oArgs) = Custom event handler for Info dialog

HandleDialogInputAndChoose(sEvent, oSender, oArgs) = Custom event handler for InputAndChoose dialog

HandleDialogMemo(sEvent, oSender, oArgs) = Custom event handler for Memo dialog

HandleDialogMultiCheck(sEvent, oSender, oArgs) = Custom event handler for multi check dialog

HandleDialogMultiInput(sEvent, oSender, oArgs) = Custom event handler for MultiInput dialog

HandleDialogMultiPick(sEvent, oSender, oArgs) = Custom event handler for multi pick dialog

HandleDialogOpenFolder(sEvent, oSender, oArgs) = Custom event handler for OpenFolder dialog

HandleDialogPick(sEvent, oSender, oArgs) = Custom event handler for Pick dialog

HandleDialogPickAndChoose(sEvent, oSender, oArgs) = Custom event handler for PickAndChoose dialog

HandleDialogPickInputAndChoose(sEvent, oSender, oArgs) = Custom event handler for PickInputAndChoose dialog

AddButtonBand(aButtons):Button[]

HandleDialogTimePicker(sEvent, oSender, oArgs) = Custom event handler for time picker dialog

HandleGotFocus(oSender:Object, oArgs:EventArgs) = Handler for GotFocus event of a control

HandleKeyDown(oSender:Object, oArgs:KeyEventArgs) = Handler for KeyDown event

HandleLoad(oSender:Object, oArgs:EventArgs) = Handler for Load event

HandleSelectedIndexChanged(oSender:Object, oArgs:EventArgs) = Handler for SelectedIndexChanged event of a ListBox

HandleSelectionChanged(oSender:Object, oArgs:EventArgs) = Handler for SelectionChanged event of a RichTextBox

HandleShown(oSender:Object, oArgs:EventArgs) = Handle for Shown event of a dialog

Import(sFile) = Import data from a file into controls of the current dialog

MakeAccessibleName(sLabel) = Make an accessible control name

MakeCaption(sText) = Make a control caption

MakeFriendlyKeyName(sKey) = Make a key string more friendly

MakeLabel(sText) = Make a control label

MakeName(ctl, sLabel) = Make a control name

SetStatus(sText) = Set status text

HomerIni

String ReadValue(String sFile, String sSection, String sKey, string sDefault) = Read a value

bool WriteQuote(String sFile, String sSection, String sKey, String sValue) = Write a value surrounded by quotes

bool WriteValue(String sFile, String sSection, String sKey, String sValue) = Write a value

bool WriteValue(String sFile, String sSection, String sKey, String sValue, bool bQuote) = Write a value, optionally surrounding it with quotes

bool DeleteKey(String sFile, String sSection, String sKey) = Delete a key

bool DeleteSection(String sFile, String sSection) = Delete a section

bool FlushFile(String sFile) = Flush any pending changes to disk

string[] ReadKeys(string sFile, string sSection) = Get an array of key names

string[] ReadKeys(string sFile, string sSection, bool bIncludeComments) = Get an array of key names, optionally including commented lines (leading semicolon)

string[] ReadSections(string sFile) = Get an array of section names

HomerZip

bool Add(string sZip, string[] aFiles) = Add array of files to archive (or null for * wildcard)

object[] Contents(string sZip) = Get array of dictionaries of archive contents

bool Delete(string sZip, string[] aFiles) = Delete array of files from archive (or null for * wildcard)

bool Extract(string sZip, string[] aFiles, string sDir, bool bSubdirs) = Extract array of files from archive (or null for * wildcard)

string GetProgramOutput(string sExe, string sParams) = Get standard output from running console executable

bool Test(string sZip) = Test integrity of archive

Interactive JScript

InJs may be used to run or test code in either standard JavaScript or the enhanced Microsoft JScript 8.0, which also serves as the script language for web development with ASP.NET. The home page of the language is at
http://msdn2.microsoft.com/en-us/library/72bd815a(VS.80).aspx

For example, a .js file can define a sophisticated snippet that may be invoked with the Alt+V command of the EdSharp editor, available at
http://www.EmpowermentZone.com/edsetup.exe

JScript code can also be evaluated by IronCOM, a COM server that provides traditional Win32 applications with access to functionality of the .NET Framework, available at
http://www.EmpowermentZone.com/comsetup.exe

The HomerKit library for JAWS
http://EmpowermentZone.com/kitsetup.exe
or
http://EmpowermentZone.com/kitsetup.zip

includes a function called JSEval that wraps a JScript call via IronCOM, thereby enabling JAWS scripts to make .NET calls for functionality not available in the native scripting language.

InJs may also be helpful for programming in .NET languages other than JScript. Built in commands are defined for inquiring about available methods, properties, and events via reflection. You can explore an object model, test expressions, save working code, and then convert it to the syntax of another .NET language.

Another assembly, XmlComments.dll (with source code in XmlComments.cs), is included for querying documentation of .NET types. I found this by Stephen Toub at
http://msdn.microsoft.com/msdnmag/code/?url=http://msdn.microsoft.com/msdnmag/issues/04/06/NETMatters/Default.aspx

Reflecting on a COM object requires that a DLL be registered on the computer, described in the article
"Inspect COM Components Using the TypeLib Information Object"
http://msdn.microsoft.com/msdnmag/issues/1200/TypeLib/

Registering this DLL (also included in the archive) may be done at a command prompt as follows:
RegSvr32 TlbInf32.dll
Installing EdSharp does this automatically, and makes InJs conveniently available with the Go to Environment command, Control+Shift+G.

InJs works well with a screen reader, since new output to the console is automatically read. Periodically, the cls command is useful for clearing the screen and eliminating extra verbiage. InJs may also be used as a simple, speech-friendly calculator, since most algebraic, trigonometric, or date calculations may be done with JScript.

Below is the online documentation, available by entering the help command in Interactive JScript:

Type a JScript statement, followed by Enter
(a closing semicolon is not needed).
Use UpArrow to repeat a command.
End a line of input with a space and underline ( _) to continue
a multiline block of code.
The prompt then changes from a > to _ character.

Most classes of the .NET Framework 2.0 may be used in expressions.
Variable types are inferred.
To ease typing, the following namespaces are imported
(there classes may be referenced without a namespace prefix):
Accessibility
Microsoft.VisualBasic
System
System.Collections
System.ComponentModel
System.Data
System.Diagnostics
System.Drawing
System.IO
System.Net
System.Reflection
System.Runtime.InteropServices
System.Text
System.Text.RegularExpressions
System.Web
System.Windows.Forms
System.Xml

In addition, several built-in commands and functions are available.
A command name is lower case, with a space before each argument,
and no quotes around it. A function name is lower camel case
(words after the first are capitalized).

quit = end this program
cls = clear the screen
eval FileName = execute a JScript file
eval clipboard = execute JScript code on the clipboard
cmd = pass any statement to the Windows command interpreter (cmd.exe)
dos = execute a console-mode command and display its output
log FileName = log output to a file
log off = suspend logging
log on = continue logging
net Type = list members of .NET Type
constructors Type = list its constructors only
events Type = list its events only
fields Type = list its fields only
methods Type = list its methods only
properties Type = list its properties only
com Object = list members of COM Object
dir Type/Object = directory of members of either .NET Type or COM Object
doc Type = documentation for constructors of .NET Type
doc Type Member = documentation for Member of .NET Type
comCreate(sProgID) = alias for new ActiveXObject(sProgID)
output(Object) = alias for Console.WriteLine(Object)

If Window-Eyes is running, itsApplication object is
automatically assigned to the we variable for typing convenience.

Change Log

Homer.NET 0.73 on September 19, 2009
Added documentation to further explain Lbc concepts. Added SAAPI32.dll for support of the System Access screen reader.

Development Notes

The .NET Framework 2.0 Software Development Kit (SDK) is available at
http://msdn.microsoft.com/en-us/netframework/aa731542.aspx

I developed Homer.NET with the EdSharp editor available at
http://EmpowermentZone.com/edsetup.exe

The latest version is available at
http://EmpowermentZone.com/hnsetup.zip

Jamal Mazrui
jamal@EmpowermentZone.com