Dies ist ohne umfangreiche Manipulation von Windows-Interna nicht möglich und Sie müssen darüber hinwegkommen.
Es gibt Momente im täglichen Computereinsatz, in denen es wirklich wichtig ist, dass Sie eine Aktion ausführen, bevor das Betriebssystem die Ausführung einer anderen zulässt. Dazu muss Ihr Fokus auf bestimmte Fenster fixiert werden. In Windows liegt die Kontrolle über dieses Verhalten weitgehend bei den Entwicklern der einzelnen Programme, die Sie verwenden.
Nicht jeder Entwickler trifft die richtigen Entscheidungen, wenn es um dieses Thema geht.
Ich weiß, dass das sehr frustrierend und nervig ist, aber Sie können Ihren Kuchen nicht haben und ihn auch 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 Benutzeroberflächenelement oder eine Anwendung verschoben wird, in der der Fokus darauf verriegelt bleiben soll. Die meisten Anwendungen sind jedoch bei der Entscheidung, wer gerade die Nase vorn hat, ziemlich gleich und das System kann niemals perfekt sein.
Vor einiger Zeit habe ich ausführliche Nachforschungen angestellt, um dieses Problem ein für alle Mal zu lösen (und bin gescheitert). Das Ergebnis meiner Recherche finden Sie auf der Projektseite Ärger .
Das Projekt enthält auch eine Anwendung, die wiederholt versucht, den Fokus zu erreichen, indem sie Folgendes aufruft:
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 aus diesem Snippet ersehen können, konzentrierte sich meine Forschung auch auf andere Aspekte des Verhaltens der Benutzeroberfläche, die mir nicht gefallen.
Ich habe versucht, dieses Problem zu lösen, indem ich in jeden neuen Prozess eine DLL geladen und die API-Aufrufe angehängt habe, die dazu führen, dass ein anderes Fenster aktiviert wird.
Der letzte Teil ist einfach, dank der hervorragenden API-Hooking-Bibliotheken. Ich habe die sehr gute 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 damaligen Tests hat das super geklappt. Mit Ausnahme des Teils des Ladens der DLL in jeden neuen Prozess. Wie man sich vorstellen kann, ist das nichts, was man zu leicht nehmen sollte. Ich habe damals den AppInit_DLLs- Ansatz verwendet (was einfach nicht ausreicht).
Grundsätzlich funktioniert das super. Aber ich habe nie die Zeit gefunden, etwas zu schreiben, das meine DLL richtig in neue Prozesse einfügt. Und die dafür aufgewendete Zeit überschattet größtenteils den Ärger, den der Fokusraub mir bereitet.
Neben dem DLL-Injection-Problem gibt es auch eine Focus-Stealing-Methode, die ich in der Implementierung von Google Code nicht behandelt habe. Ein Mitarbeiter hat tatsächlich zusätzliche Nachforschungen angestellt und sich mit dieser Methode befasst. Das Problem wurde auf SO diskutiert: https://stackoverflow.com/questions/7430864/windows-7-prevent-application-from-losing-focus