Doug,
The Window.FieldName property is what Window-Eyes would process for the
field name of that window. It is not what any App may have done to the
field name. So yes, you could use this if you wanted in the OnFieldName
event if you wanted.
However, the Window.FieldData property is not implemented and if you use
it you will get a "Object doesn't support this action" error. We hope
to implement this at some point in the future.
Regarding performance, sure, we are talking nano seconds...but non the
less, it would still be worth thinking about at times.
As for your Desktop hooking, I see what you are doing and by doing this
you are just playing with windows you are interested in. So it really
isn't a bad approach. Just for completeness, another option would be to
hook OnActivate and if the window is of interest then you hook it for
that window. If you get a window you aren't interested in you
completely unhook the event. We use this technique quit often in our Apps.
Regards,
Doug
On 2/17/2011 10:33 AM, Doug Lee wrote:
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.