*** 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

Reply via email to