Commenter ulric
suggested that
two functions for obtaining the "current" window should exist,
one for normal everyday use and one for "special use" when you want
to interact with windows outside your process.
I'd be more at ease however if the default behaviour of the API
was to return HWND for the current process only,
and the apps that really need HWND from
other potentially other processes
would have to be forced to use
another API that is specifically just for that.
This is an excellent example of
suggesting something that Windows already does.
The special function has become so non-special,
you don't even realize any more that it's special.
Originally, in 16-bit Windows, the function for getting the "current"
window was GetActiveWindow.
This obtained the active window across the entire system.
One of the major changes in Win32 is the asynchronous input model,
wherein windows from different input queues receive separate input.
That way, one program that has stopped responding to input
doesn't clog up input for other unrelated windows.
Win32 changed the meaning of GetActiveWindow to mean
the active window from the current input queue.
In 16-bit Windows, there was only one input queue, the global one.
In 32-bit Windows, each thread (or group of input-attached threads)
gets its own input queue.
As a result of this finer granularity,
when a program was ported from 16-bit Windows to 32-bit Windows,
it didn't "see" windows from other programs when it called
functions like GetFocus
or GetActiveWindow.
As every Win32 programmer should know,
these states are local to your input queue.
Okay, let's look at what we've got now.
GetFocus and GetActiveWindow give you
the status of your input queue.
In other words, in a single-threaded program (which, if you're
coming from 16-bit Windows, is the only type of program there is),
calling
GetActiveWindow gives you the active window from
your program.
It doesn't return the active window from another program.¹
Things are exactly as ulric suggested!
Now let's look at the second half of the suggestion.
If a program really needs to get a window from potentially
other processes, it would have to use some other function that
is specifically just for that.
And indeed, that's why the
GetForegroundWindow function was added.
The GetForegroundWindow function is
the special
function specifically designed for obtaining windows from
other processes.
Therefore, we did exactly what ulric recommended,
and it still turned into a mess.
Why?
Because once you create something special,
it doesn't remain special for long.
It may take a while, but eventually people find that the
regular function "doesn't work"
(for various definitions of "work"),
and they ask around for help.
"When I call GetActiveWindow,
I'm not getting the global active window;
I'm just getting the local one.
How do I get the global one?"
Actually, they probably don't even formulate the question
that clearly.
It's probably more like
"I want to get the active window, but GetActiveWindow
doesn't work."
And then somebody responds with
"Yeah, GetActiveWindow doesn't work.
I've found that GetForegroundWindow works a lot better."
The response is then
"Wow, that works great! Thanks!"
Eventually, the word on the street is
"GetActiveWindow doesn't work.
Use GetForegroundWindow instead."
Soon, people are using it for everything,
waxing their car,
calming a colicky baby,
or improving their sexual attractiveness.
What used to be a function to be used "only in those rare
occasions when you really need it"
has become
"the go-to function that gets the job done."
In fact, the unfashionableness of the active window has reached the point
that people have given up on calling it the active window at all!
Instead, they call it
the foreground window from the current process.
It's like calling a land line a "wired cell phone".
Requiring a new flag to get the special behavior
doesn't change things at all.
It's the same story, just with different names for the characters.
"GetFocalWindow² doesn't work unless you pass the
GFW_CROSSPROCESS flag."
Soon, everybody will be passing the
GFW_CROSSPROCESS not because they understand what it does
but just because "That's what I was told to do"
and "It doesn't work if I don't pass it."
Footnotes
¹Assuming you haven't run around attaching your thread
to some other program's input queue.
This is a pretty safe assumption
since the AttachThreadInput function
didn't exist in 16-bit Windows either.
²GetFocalWindow is an imaginary function created
for the purpose of the example.
[Raymond is currently away; this message was pre-recorded.]
