We generally shouldn't need to chain onChildField* events across
applications or WE apps, indeed. The only case I can think of for
wanting the modified "send in string and chain results" approach would
be if a WE app is comprised of modules that each might hook one of
those events. That's probably a rare situation though, at least one
would hope that even if multiple parts of one WE app hook the same
event, their handled cases won't overlap anyway. So I bet the current
approach (which as you describe it is what I figured) should be fine.
I do wonder how the Window.FieldData/Name properties are used though.
I assume they are what speaks in the absence of a non-null return from
any corresponding event, and that we could use this in our events to
test for what would speak without our events modifying anything?
Addressing the efficiency of hooking Desktop window for OnChildField*
events...
I assume these events are not called frequently. Based on my
observations, they are called (1) on focus change, (2) on user
requests such as Ctrl-Shift-N, and (3) about once every two seconds on
some edit controls, perhaps only when Braille is active (I didn't test
that carefully). So I'm not concerned with a little per-application
code running for these unless I'm missing something.
As for a case where the Desktop hook makes the most sense: My normal
approach is something like this, which does hook Desktop but then
rules out anything not related to my app - the equivalent of a process
filter, like you allow on MSAA event blocking:
' May not need to hook all three of these, depending on application.
connectEventWithParameter desktopWindow, "onChildFieldData", "onFieldInfo",
"data"
connectEventWithParameter desktopWindow, "onChildFieldName", "onFieldInfo",
"name"
connectEventWithParameter desktopWindow, "onChildSummary", "onFieldInfo",
"summary"
function onFieldInfo(window, which)
' Hooked to any of onChildFieldData, onChildFieldName, and onChildSummary.
' The "which" parameter will be "data," "name," or "summary" as appropriate.
' Fires on all Data/Name/Summary requests (even from other apps).
' Returns vbNull for other apps and for anything we don't need to change for
this one.
onFieldInfo = vbNull
on error resume next
if not (window.process.processID =
clientInformation.applicationProcess.processID) then
' This is a window from something else, so don't mess with it.
exit function
end if
on error goto 0
' if this is one of my fields
' Set onFieldInfo for whichever of data/name/summary I need.
' end if
end function
On Thu, Feb 17, 2011 at 10:14:49AM -0500, Doug Geoffray wrote:
Hello Doug,
A good rule of thumb is if the event doesn't pass any data that you can
change on return then when the data is changed no other events are
called on it. For example Speech.OnSpeak is an event that sends the
text about to be sent to the synthesizer. Since the event passes the
starting text which you can modify and return then you are guaranteed
all Apps hooking this event will get the updated string until the last
App gets called and then it goes onto the synth. But events like
Window.OnChildFieldName just pass the window, not the field name text
that would be spoken so once an App sets the text and returns it, all
remaining Apps that hooked this event will not be called.
As to the order they get called, you should assume this is random. It
just depends on the order they are hooked.
We could modify things so although Window-Eyes doesn't give you the
starting string (well, string in this case) we could pass an empty
string or whatever the last Apps created and so on until all Apps get
the event.
But I'm wondering if this is necessary. Typically you are creating an
App to fix a problem and usually that problem is specific to an
application. So I'm not sure I agree with what you said about multiple
desktop window hooks for OnChildField* as common. Yes, you could do
this but it certainly wouldn't be the most efficient unless you truly
plan on fixing every possible Field* string for all appliations. I
think the events should be filtered as best they can to only fire on
windows you potentially are interested in. For example if you are only
fixing Firefox download manager dialog field names then only hook the
events for that dialog, not globally via the desktop. Can you give me a
common case where this isn't optimal or possible?
Regards,
Doug G
On 2/17/2011 9:14 AM, Doug Lee wrote:
>Most WE events don't return values, but the OnFieldData/Name/Summary,
>and their OnChildField* parallels, return strings or vbNull. My
>understanding is that Window-Eyes speaks what these events return.
>
>So say you have three applications loaded, all of which include a
>ConnectEvent for OnChildFieldName from the Desktop window. They can
>(and absolutely should of course) filter their responses by checking
>for process Ids, but they still each have to return something - should
>be vbNull.
>
>So the question: How does Window-Eyes decide who to listen to? Does
>it just speak the first non-null result it gets back, or does it speak
>all non-null results from the different event functions? I assume if
>it speaks any one of them, it would not go ahead and speak its own
>default response as well.
>
>Btw, I regard this scenario of multiple Desktop window hooks for
>OnChildField* events as very likely, because it seems the safest way
>to avoid problems if the top-level window of an application is not
>constant. This is also very likely in the presence of pop-up dialogs
>and such. My question is mostly so I can detect any interferance one
>script might cause to another in this area.
>
--
Doug Lee, Senior Accessibility Programmer
SSB BART Group - Accessibility-on-Demand
mailto:[email protected] http://www.ssbbartgroup.com
"While they were saying among themselves it cannot be done,
it was done." --Helen Keller