Why does SetFocus fail without telling me why?
One of my colleagues was debugging a program and discovered that a call to
NULL, which the documentation calls out as indicating an error condition. However, a follow-up call to
GetLastError() returned 0, which means “Everything is just fine.”
After much debugging, they figured it out: There was a
CBT hook that was intercepting the
SetFocus call and rejecting the focus change by returning
“It would have been nice to have received a useful error code like
You don’t get a useful error because the window manager doesn’t know that the hook is screwing with you. You called
SetFocus. The window hook said, “Nope, don’t change focus. It’s all good. No worries.” The window manager says, “Okay, well, then I guess it’s all taken care of.”
Hooks let you modify or even replace certain parts of the window manager. If you do that, then it’s on you to do so in a manner that will not confuse the rest of the system. If your hook wants to make
SetFocus fail, and not set an error code, we’ll that’s your decision. The system is not going to call
HOOK) because that might overwrite an error code set by the hook.
In this specific example, the point of the
CBT hook is to assist with computer-based training: The program installs a CBT hook, which can then do things like prevent the program from changing focus so that the window containing the training materials retains focus. The underlying assumption is that a CBT hook is going to mess around only with windows that it is already in cahoots with.
“Oh, this is my print dialog. I’m going to prevent it from taking focus so that my instructions on how to use the printer stays on screen with focus. I’m also going to make changes to my print dialog function so it doesn’t freak out when it fails to get focus.”
Whatever program installed this CBT hook didn’t limit their meddling to windows they already controlled. This means that their actions sowed confusion among other windows that weren’t part of their little game.
I suspect no actual computer-based training was going on at all. The CBT hook was being used not for its stated purpose of computer-based training, but rather because it provided a way to alter the behavior of the window manager in very fundamental ways, and being able to make those alterations fit into the program’s world view somehow.
Somebody who installs a hook can alter the behavior of the system, and it’s important that they do it right, so that their changes still maintain the contracts promised by the system. One of those being that when
SetFocus fails, it tells you why.