Это невозможно без интенсивных манипуляций с внутренними компонентами Windows, и вам нужно преодолеть это.
В повседневном использовании компьютера бывают моменты, когда очень важно выполнить одно действие, прежде чем операционная система позволит вам выполнить другое. Для этого нужно заблокировать фокус на определенных окнах. В Windows контроль над этим поведением в основном остается за разработчиками отдельных программ, которые вы используете.
Не каждый разработчик принимает правильные решения, когда речь заходит об этой теме.
Я знаю, что это очень расстраивает и раздражает, но вы не можете съесть свой пирог и съесть его тоже. Вероятно, в вашей повседневной жизни есть много случаев, когда вы совершенно в порядке с фокусом, перемещенным на определенный элемент пользовательского интерфейса или с приложением, запрашивающим, чтобы фокус оставался на нем. Но большинство приложений примерно одинаковы, когда речь заходит о том, кто сейчас является лидером, и система никогда не может быть идеальной.
Некоторое время назад я провел обширные исследования по решению этой проблемы раз и навсегда (и не смог). Результат моего исследования можно найти на странице проекта раздражения .
Проект также включает в себя приложение, которое неоднократно пытается захватить фокус, вызывая:
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;
Как видно из этого фрагмента, мои исследования были также сосредоточены на других аспектах поведения пользовательского интерфейса, которые мне не нравятся.
Я пытался решить эту проблему, загружая DLL в каждый новый процесс и перехватывая вызовы API, которые вызывают активацию других окон.
Последняя часть проста благодаря удивительным библиотекам перехвата API. Я использовал очень большую библиотеку mhook :
#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; }
Из моих тестов тогда это работало отлично. За исключением части загрузки DLL в каждый новый процесс. Как можно себе представить, это не слишком легко. Тогда я использовал подход AppInit_DLLs (которого просто недостаточно).
В принципе, это прекрасно работает. Но я так и не нашел время написать что-то, что правильно внедрит мою DLL в новые процессы. И время, потраченное на это, в значительной степени омрачает раздражение, которое вызывает кража фокуса.
В дополнение к проблеме внедрения DLL, есть также метод кражи фокуса, который я не рассматривал при реализации в Google Code. Сотрудник действительно провел дополнительное исследование и рассказал об этом методе. Проблема обсуждалась на SO: https://stackoverflow.com/questions/7430864/windows-7-prevent-application-from-losing-focus