*** warning: below contains the answer to the homework assignment; don't
read if you're still trying to work this out yourself.
' Early Draft of class #8 examples: (4/10/2011)
' example 1
' using an event handler to watch newly opened windows.
' and another event handler to watch closing windows.
' (this is a modified version of a script from last week)
option explicit
' this is a fully working script, which you could load on your system by:
dim n1, n2
dim NP
set NP = createObject("scripting.dictionary") ' this dictionary will hold
the titles of all NotePad windows
' now use the window object's onChildCreate event, and do it on the desktop
window itself, to look for new windows
' (remember the desktopWindow is a "root level" object because it's a
property of the application object, which is always available).
n1 = connectEvent ( desktopWindow , "onChildCreate", "myNewWindowHandler")
' now look at windows which close, and take them out of the dictionary to
prevent false reports.
n2 = connectEvent (desktopWindow, "onChildClose", "myCloseWindowHandler")
' end of main body
sub myNewWindowHandler(win)
' this is the event handler for the onChildCreate event of the desktop
window
' since we may say something, and we also need to pause slightly to allow
the application to have time enough to set the window title, we have to use
the queue method
queue "checkWin", win
end sub
sub checkWin(win)
sleep 500 ' give application half a second to initialize window
' below tests to see if we have a top level window (we haven't covered this
yet, just take my word)
if win.style.overlapped or win.style.MDIChild then
' it is an application top-level window
if win.className = "Notepad" then
' it's a notepad document window
if NP.exists(win.title) then
' found this window title in the dictionary
silence
sleep 1000 ' pause one second after going quiet
speak "Warning! " & win.title & " is opened more than once!"
else
' first time opening, just add it (with it's handle) to the dictionary
NP.add win.title, win.handle
end if ' NP.exists(win.title)
end if ' win.className = "Notepad"
end if ' win.style.overlapped or win.style.MDIChild
end sub
sub myCloseWindowHandler(handle)
' this is a onChildClose handler which gets called for all windows
' (it doesn't do anything time consuming, so we don't need to use a queue
command)
dim curTitle
' search our dictionary for this handle, and if it's found, remove this
entry
for each curTitle in NP.keys
' note the use of .exists below; without it, we'd create an NP entry just by
looking for it
if NP.exists(curTitle) then
if NP(curTitle) = handle then
NP.remove(curTitle) ' remove this dictionary entry
end if
end if
next
end sub
' end of example 1
' example 2
' using an event handler to watch newly opened windows.
' and another event handler to watch when the opened window closes.
' (this is a modified version of the script above; it handles windows
closing in a different way)
option explicit
' this is a fully working script, which you could load on your system by:
dim n
dim NP
set NP = createObject("scripting.dictionary") ' this dictionary will hold
the titles of all NotePad windows
' now use the window object's onChildCreate event, and do it on the desktop
window itself, to look for new windows
' (remember the desktopWindow is a "root level" object because it's a
property of the application object, which is always available).
n = connectEvent ( desktopWindow , "onChildCreate", "myNewWindowHandler")
' end of main body
sub myNewWindowHandler(win)
' this is the event handler for the onChildCreate event of the desktop
window
' since we may say something, and we also need to pause slightly to allow
the application to have time enough to set the window title, we have to use
the queue method
queue "checkWin", win
end sub
sub checkWin(win)
sleep 500 ' give application half a second to initialize window
' below tests to see if we have a top level window (we haven't covered this
yet, just take my word)
if win.style.overlapped or win.style.MDIChild then
' it is an application top-level window
if win.className = "Notepad" then
' it's a notepad document window
if NP.exists(win.title) then
' found this window title in the dictionary
silence
sleep 1000 ' pause one second after going quiet
speak "Warning! " & win.title & " is opened more than once!"
else
' first time opening, just add it (with it's handle) to the dictionary
NP.add win.title, win.handle
' now set things up so the window closing event is only called for a
dictionary window, and not all windows
' (the window we use to connect to it's event is the window which just
opened, not the desktopWindow as before)
connectEvent win, "onClose", "myCloseWindowHandler" ' this connects to
a different event from example 1
' (this event only tells us when this specific window closes, not when all
children windows closed as did example 1).
end if ' NP.exists(win.title)
end if ' win.className = "Notepad"
end if ' win.style.overlapped or win.style.MDIChild
end sub
sub myCloseWindowHandler(handle)
' this is an onClose event handler; it gets called for only windows in our
NP dictionary, and so a lot less often than example 1
dim curTitle
' search our dictionary for this handle, and if it's found, remove this
entry
for each curTitle in NP.keys
' note the use of .exists below; without it, we'd create an NP entry just by
looking for it
if NP.exists(curTitle) then
if NP(curTitle) = handle then
NP.remove(curTitle) ' remove this dictionary entry
end if
end if
next
end sub
' end of example 2
' note that these examples still have a problem: if the user opens the same
file 3 times or more, then closes down two of the files, and then with one
still open opens a second occurance, it will not give a warning message!
' (welcome to the world of real scripting debugging!)
' example 3
' this is a modified version of the script above; it handles Notepad windows
in a different way;
' instead of using a dictionary, it uses a method of the "windows"
collection (a property of the application object, and so a "root level"
object).
' the method it uses (filterByTitle) examines all the currently open windows
which have a given title.
' this technique solves the problem mentioned at the end of example 2 with
having more than two windows open with the same title, and allows us not to
have to use a dictionary at all.
option explicit
' this is a fully working script, which you could load on your system by:
dim n
' now use the window object's onChildCreate event, and do it on the desktop
window itself, to look for new windows
n = connectEvent ( desktopWindow , "onChildCreate", "myNewWindowHandler")
' end of main body
sub myNewWindowHandler(win)
' this is the event handler for the onChildCreate event of the desktop
window
' since we may say something, and we also need to pause slightly to allow
the application to have time enough to set the window title, we have to use
the queue method
queue "checkWin", win
end sub
sub checkWin(win)
dim objWins , objCurWin
sleep 500 ' give application half a second to initialize window
' below tests to see if we have a top level window (we haven't covered this
yet, just take my word)
if win.style.overlapped or win.style.MDIChild then
' it is an application top-level window
if win.className = "Notepad" then
' it's a notepad document window
set objWins = windows.filterByTitle(win.title) ' returns a collection of
currently open windows with a given title
for each objCurWin in objWins
if objCurWin.handle <> win.handle then
' this isn't the window being opened at the moment
if objCurWin.className = "Notepad" then
' it's a notepad document window
silence
sleep 1000 ' pause one second after going quiet
speak "Warning! " & win.title & " is opened more than once!"
end if ' objCurWin.className = = "Notepad"
end if ' objCurWin.handle <> win.handle
next
end if ' win.className = "Notepad"
end if ' win.style.overlapped or win.style.MDIChild
end sub
' end of example 3
Below are select properties, methods, and events of the application object,
which you are most likely to use.
All of the properties and methods are "root level", and so can be access
without having to use the application. as part of their names.
Properties:
ActiveMDIChild
ActiveWindow
ClientInformation
DesktopWindow
FocusedWindow
INIFile
Keyboard
Mouse
MSAAEventSource
Screen
SharedObjects
Speech
Text
Utilities
Windows
Methods:
Dialog
ExecuteHotkey
Menu
PlaySound
ScreenPoint
ScreenRectangle
Strings
Events:
OnCursorKey
OnHotkey
OnQuit
Below are select properties, methods, and events of the window object, which
you are most likely to use.
Properties:
Accessible
AlwaysOnTop
Children
ClassName
DirectChildren
Enabled
FieldName
Handle
IsValid
ModuleName
Name
NativeObjectModel
OnScreenVisibility
OriginalClassName
OriginalType
Overlap
Parent
Process
Status
Style
Title
Type
Visible
Methods:
Activate
ClientPoint
ClientRectangle
Clips
Close
Control
Focus
WindowPoint
WindowRectangle
Events:
OnAfterChildSelect
OnAfterSelect
OnBeforeChildSelect
OnBeforeSelect
OnChildFieldData
OnChildFieldName
OnChildSelection
OnChildSummary
OnFieldData
OnFieldName
OnActivate
OnBlur
OnChildActivate
OnChildBlur
OnChildClipRendered
OnChildClose
OnChildCreate
OnChildDeactivate
OnChildFocus
OnClipRendered
OnClose
OnDeactivate
OnFocus
OnMDIActivate
OnMDIChildActivate
OnMDIChildDeactivate
OnMDIDeactivate
OnMenuOpened
OnMenuClosed
OnMenuSelection
OnSelection
OnSummary