Preventing applications from stealing focus
This is not possible without extensive manipulation of Windows internals and you need to get over it.
There are moments in daily computer use when it is really important that you make one action before the operating system allows you to do another. To do that, it needs to lock your focus on certain windows. In Windows, control over this behavior is largely left to the developers of the individual programs that you use.
Not every developer makes the right decisions when it comes to this topic.
I know that this is very frustrating and annoying, but you can't have your cake and eat it too. There are probably many cases throughout your daily life where you're perfectly fine with the focus being moved to a certain UI element or an application requesting that the focus remains locked on it. But most applications are somewhat equal when it comes to deciding who is the lead right now and the system can never be perfect.
A while ago I did extensive research on solving this issue once and for all (and failed). The result of my research can be found on the annoyance project page.
The project also includes an application that repeatedly tries to grab focus by calling:
switch( message ) {
case WM_TIMER:
if( hWnd != NULL ) {
// Start off easy
// SetForegroundWindow will not move the window to the foreground,
// but it will invoke FlashWindow internally and, thus, show the
// taskbar.
SetForegroundWindow( hWnd );
// Our application is awesome! It must have your focus!
SetActiveWindow( hWnd );
// Flash that button!
FlashWindow( hWnd, TRUE );
}
break;
As we can see from this snippet, my research was also focused on other aspects of user interface behavior I don't like.
The way I tried to solve this was to load a DLL into every new process and hook the API calls that cause another windows to be activated.
The last part is the easy one, thanks to awesome API hooking libraries out there. I used the very great mhook library:
#include "stdafx.h"
#include "mhook-2.2/mhook-lib/mhook.h"
typedef NTSTATUS( WINAPI* PNT_QUERY_SYSTEM_INFORMATION ) (
__in SYSTEM_INFORMATION_CLASS SystemInformationClass,
__inout PVOID SystemInformation,
__in ULONG SystemInformationLength,
__out_opt PULONG ReturnLength
);
// Originals
PNT_QUERY_SYSTEM_INFORMATION OriginalFlashWindow =
(PNT_QUERY_SYSTEM_INFORMATION)::GetProcAddress(
::GetModuleHandle( L"user32" ), "FlashWindow" );
PNT_QUERY_SYSTEM_INFORMATION OriginalFlashWindowEx =
(PNT_QUERY_SYSTEM_INFORMATION)::GetProcAddress(
::GetModuleHandle( L"user32" ), "FlashWindowEx" );
PNT_QUERY_SYSTEM_INFORMATION OriginalSetForegroundWindow =
(PNT_QUERY_SYSTEM_INFORMATION)::GetProcAddress(
::GetModuleHandle( L"user32" ), "SetForegroundWindow" );
// Hooks
BOOL WINAPI
HookedFlashWindow(
__in HWND hWnd,
__in BOOL bInvert
) {
return 0;
}
BOOL WINAPI
HookedFlashWindowEx(
__in PFLASHWINFO pfwi
) {
return 0;
}
BOOL WINAPI
HookedSetForegroundWindow(
__in HWND hWnd
) {
// Pretend window was brought to foreground
return 1;
}
BOOL APIENTRY
DllMain(
HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
) {
switch( ul_reason_for_call ) {
case DLL_PROCESS_ATTACH:
Mhook_SetHook( (PVOID*)&OriginalFlashWindow, HookedFlashWindow );
Mhook_SetHook( (PVOID*)&OriginalFlashWindowEx, HookedFlashWindowEx );
Mhook_SetHook( (PVOID*)&OriginalSetForegroundWindow, HookedSetForegroundWindow );
break;
case DLL_PROCESS_DETACH:
Mhook_Unhook( (PVOID*)&OriginalFlashWindow );
Mhook_Unhook( (PVOID*)&OriginalFlashWindowEx );
Mhook_Unhook( (PVOID*)&OriginalSetForegroundWindow );
break;
}
return TRUE;
}
From my tests back then, this worked great. Except for the part of loading the DLL into every new process. As one might imagine, that's nothing to take too lightly. I used the AppInit_DLLs approach back then (which is simply not sufficient).
Basically, this works great. But I never found the time to write something that properly injects my DLL into new processes. And the time invested in this largely overshadows the annoyance the focus stealing causes me.
In addition to the DLL injection problem, there is also a focus-stealing method which I didn't cover in the implementation on Google Code. A co-worker actually did some additional research and covered that method. The problem was discussed on SO: https://stackoverflow.com/questions/7430864/windows-7-prevent-application-from-losing-focus
In Windows 7, the ForegroundLockTimeout
registry entry is no longer checked, you can verify this with Process Monitor. In fact, in Windows 7 they disallow you from changing the foreground window. Go and read about its details, it has even been there since Windows 2000.
However, the documentation sucks and they chase each other and find ways around that.
So, there is something buggy going on with SetForegroundWindow
, or similar API functions...
The only way to really do this properly is to make a small application which periodically calls LockSetForegroundWindow
, virtually disabling any calls to our buggy API function.
If that's not enough (another buggy API call?) you can go even further and do some API monitoring to see what's going on, and then you simply hook the API calls on every process after which you can get rid of any calls that mess up the foreground. However, ironically, this is discouraged by Microsoft...
There is an option in TweakUI which does this. It prevents most of the usual tricks dubious software developers employ to force focus on their app.
It's an ongoing arms war though, so I don't know if it works for everything.
Update: According to EndangeredMassa, TweakUI does not work on Windows 7.