Dies ist ohne umfangreiche Manipulation der Windows-Interna nicht möglich und Sie müssen darüber hinwegkommen.
Im täglichen Gebrauch des Computers gibt es Momente, in denen es wirklich wichtig ist, dass Sie eine Aktion ausführen, bevor das Betriebssystem Ihnen eine andere Aktion erlaubt. Dazu muss der Fokus auf bestimmte Fenster beschränkt werden. In Windows ist dieses Verhalten weitgehend den Entwicklern der einzelnen von Ihnen verwendeten Programme überlassen.
Nicht jeder Entwickler trifft die richtigen Entscheidungen, wenn es um dieses Thema geht.
Ich weiß, dass dies sehr frustrierend und ärgerlich ist, aber Sie können Ihren Kuchen nicht essen und auch nicht essen. Es gibt wahrscheinlich viele Fälle in Ihrem täglichen Leben, in denen Sie vollkommen in Ordnung sind, wenn der Fokus auf ein bestimmtes Oberflächenelement oder eine Anwendung verlagert wird, in der Sie aufgefordert werden, den Fokus darauf zu beschränken. Die meisten Anwendungen sind jedoch einigermaßen gleich, wenn es darum geht, zu entscheiden, wer gerade die Führungsrolle innehat, und das System kann niemals perfekt sein.
Vor einiger Zeit beschäftigte ich mich intensiv mit der Lösung dieses Problems ein für alle Mal (und ist gescheitert). Das Ergebnis meiner Recherche ist auf der Projektseite des Ärgernisses zu finden .
Das Projekt enthält auch eine Anwendung, die wiederholt versucht, den Fokus durch Aufruf aufzurufen:
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;
Wie wir an diesem Ausschnitt erkennen können, konzentrierte sich meine Forschung auch auf andere Aspekte des Benutzeroberflächenverhaltens, die mir nicht gefallen.
Ich habe versucht, dieses Problem zu lösen, indem ich in jeden neuen Prozess eine DLL lade und die API-Aufrufe einhakt, die ein anderes Fenster aktivieren.
Der letzte Teil ist dank der hervorragenden API-Hooking-Bibliotheken ganz einfach. Ich habe die sehr tolle mhook-Bibliothek benutzt :
#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; }
Bei meinen Tests hat das gut funktioniert. Außer beim Laden der DLL in jeden neuen Prozess. Wie man sich vorstellen kann, ist das nichts zu leichtes. Ich habe damals den AppInit_DLLs- Ansatz verwendet (was einfach nicht ausreicht).
Grundsätzlich funktioniert das großartig. Ich habe jedoch nie die Zeit gefunden, etwas zu schreiben, das meine DLL ordnungsgemäß in neue Prozesse einfügt. Und die Zeit, die dafür aufgewendet wird, überschattet den Ärger, den das Focus-Stehlen verursacht.
Neben dem Problem mit der DLL-Injektion gibt es auch eine Methode zum Stehlen des Fokus, die ich bei der Implementierung von Google Code nicht behandelt habe. Ein Mitarbeiter hat tatsächlich einige Nachforschungen angestellt und diese Methode behandelt. Das Problem wurde auf SO besprochen: https://stackoverflow.com/questions/7430864/windows-7-prevent-application-from-losing-focus