Frage Verhindern, dass Anwendungen den Fokus stehlen


Gibt es Lösungen, um zu verhindern, dass Anwendungen den Fokus vom aktiven Fenster stehlen?

Das ist besonders ärgerlich, wenn ich eine Anwendung starte, etwas anderes mache und die neue Anwendung einen halben Satz Text erhält.


174
2017-08-05 08:48


Ursprung


@Ivo Windows 7 in meinem Fall, aber ich denke, für SuperUser alle Windows-Versionen wäre relevant - svandragt
Der Moderator hat diese Frage zusammengeführt: superuser.com/questions/199821/ ... mit dem aktuellen. Das ist falsch, die Antwort auf die aktuelle Frage gilt nicht für Windows 7, daher sollte sie nicht zusammengeführt werden. Bis jetzt konnte ich in Windows 7 keine Lösung für dieses Problem finden - Alex Angelico
Dies ist eines meiner Lieblingstiere mit jeder GUI, die ich jemals benutzt habe. Du tippst und tust blam, ein Piep-Dialog stiehlt den Fokus und die Hälfte deiner Tastenanschläge gehen woanders hin. Man könnte meinen, dass die Entwickler von Windowing-Systemen dies schon vor Jahrzehnten herausgefunden hätten. Wenn Aktivität in einem Fenster vorhanden ist, verzögern Sie die Belichtung des neuen Fensters. Z.B. Auf der Benutzeroberfläche sollten Sie erst drei oder vier Sekunden nach dem letzten Klicken oder Tastenanschlag im aktuell fokussierten Fenster etwas auf der Benutzeroberfläche anzeigen. Do! - Kaz
Ich fand, wenn ich meine externe Festplatte (von Seagate) oder meinen iPod nano (ahem, Apple) an meine Windows 7 Maschine angeschlossen habe, würde es scheinen, als ob der "Desktop" alle 30 Sekunden oder so den Fokus stehlen würde Ich surfte, sei es Itunes Musik, Chrome Suchergebnisse oder Firefox E-Mails. Ich deaktivierte die Autoplay-Funktion, und das half eine Weile, aber das Problem kam zurück, selbst nachdem Autoplay deaktiviert wurde. Ich denke, dass ich meine externen HD - und Flash - Laufwerke größtenteils getrennt halten muss, was saugt, denn das ist, wo all meine Musik ist :( Es ist ein wirklich nerviger Bug, der mich dazu bringt, S zu wollen
This is especially annoying when I'm starting an application, switch to do something else and the new application starts receiving half a sentence of text.Noch ärgerlicher ist es, wenn ein Dialog erscheint und Sie ihn unbeabsichtigt ablehnen, ohne die Nachricht zu sehen, weil Sie zufällig gedrückt haben Space oder Enter während Sie einen Satz eingeben. - Synetech


Antworten:


Vor einiger Zeit habe ich umfangreiche Nachforschungen angestellt, um dieses Problem ein für allemal zu lösen (und gescheitert). Das Ergebnis meiner Forschung findet sich auf der Ärgerprojektseite.

Das Projekt enthält auch eine Anwendung, die wiederholt versucht, den Fokus durch Aufruf von:

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 Ausschnitt sehen können, konzentrierte sich meine Forschung auch auf andere Aspekte des Benutzeroberflächenverhaltens, die ich nicht mag.

Die Art und Weise, wie ich dies zu lösen versuchte, bestand darin, eine DLL in jeden neuen Prozess zu laden und die API-Aufrufe zu haken, die dazu führten, dass ein anderes Fenster aktiviert wurde.
Der letzte Teil ist der einfache, dank genialer API-Hooking-Bibliotheken. Ich habe das sehr toll genutzt Mhook-Bibliothek:

#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;
}

Das hat bei meinen Tests damals gut funktioniert. Bis auf den Teil des Ladens der DLL in jeden neuen Prozess. Wie man sich vorstellen kann, ist das nichts zu leicht zu nehmen. Ich habe das benutzt AppInit_DLLs dann zurückkommen (was einfach nicht ausreicht).

Im Grunde funktioniert das großartig. Aber ich habe nie die Zeit gefunden, etwas zu schreiben richtig spritzt meine DLL in neue Prozesse ein. Und die investierte Zeit überschattet weitgehend die Belästigung, die mich der Fokus-Diebstahl verursacht.

Neben dem DLL-Injection-Problem gibt es auch eine Fokus-Stealing-Methode, die ich in der Implementierung auf Google Code nicht behandelt habe. Ein Mitarbeiter hat tatsächlich zusätzliche Forschung betrieben und diese Methode abgedeckt. Das Problem wurde auf SO diskutiert: https://stackoverflow.com/questions/7430864/windows-7-prevent-application-from-losing-focus


45
2018-03-24 09:56



Denkst du, dass diese Lösung von dir nach Java portiert werden könnte? Ich habe gesucht und Fragen gestellt, aber nichts gefunden. Vielleicht könnte ich die Hook-Bibliothek selbst in Java mit importieren jne? - Tomáš Zato
@ TomášZato: Keine Ahnung. Ich verwende diesen Code nicht selbst aktiv. - Der Hochstapler
Ich versuche es zumindest als C ++ zu kompilieren (und dann die kompilierte DLL aus Java zu injizieren / entfernen). Aber das geht auch nicht so gut. Ich möchte es hier nicht in Kommentaren diskutieren, aber wenn Sie mir helfen könnten, es zur Arbeit zu bringen, wäre ich sehr anmutig! Ich habe einen Chat-Raum erstellt, wenn ich das zur Arbeit bekomme, werde ich einen Kommentar schreiben, wie es hier geht: chat.stackexchange.com/rooms/21637/... - Tomáš Zato


In Windows 7 wird die ForegroundLockTimeout Registrierungseintrag wird nicht mehr überprüft, Sie können dies mit Process Monitor überprüfen. In Windows 7 können Sie das Vordergrundfenster nicht ändern. Geh und lies über seine DetailsEs ist sogar seit Windows 2000 da gewesen.

Jedoch, die Dokumentation saugt und sie jagen sich gegenseitig und finden Wege um das herum.

Also, da ist etwas Buggy los SetForegroundWindowoder ähnliche API-Funktionen ...

Der einzige Weg, dies richtig zu machen, ist eine kleine Anwendung, die regelmäßig anruft LockSetForegroundWindowpraktisch alle Aufrufe unserer fehlerhaften API-Funktion deaktiviert.

Wenn das nicht genug ist (ein weiterer Buggy-API-Aufruf?), Können Sie noch weiter gehen und etwas tun API-Überwachung um zu sehen, was vor sich geht, und dann einfach Haken Sie die API-Aufrufe bei jedem Prozess nach dem Sie loswerden können irgendein Anrufe, die den Vordergrund durcheinander bringen. Ironischerweise wird dies jedoch von Microsoft abgeraten ...


22
2018-03-22 09:52



Hat jemand in Windows 7 einen nachvollziehbaren Anwendungsfall davon? Angesichts der Tatsache, dass die Leute eher das Gegenteil erleben (zum Beispiel finde ich häufig, dass Windows hinter meinem aktuellen Fenster versteckt ist) und dass ich dies in Windows 7 noch nicht sehen kann, wäre es ziemlich ärgerlich, eine Anwendung zu schreiben, aber nicht in der Lage zu sein Probier es aus. Darüber hinaus, wie Microsoft sagt, sollte dies nicht mehr mit Windows 7 passieren. Im besten Fall haben die Leute entdeckt, dass es nur versehentlich den Fokus der Tastatur wechseln kann. Dieser API-Aufruf würde das beheben, aber ich weiß nicht, wie es funktioniert. . - Tom Wijsman
Das Installationsprogramm (basierend auf InnoSetup) startet andere Prozesse und mögliche andere (versteckte) Setups, aber ich weiß nicht, auf welchem ​​Setup-Creator sie basieren. - Daniel Beck♦
@TomWijsman: Öffnen Sie regedit, suchen Sie nach zufälligem Text, der nicht gefunden wird. Geh in eine andere App und fange an zu tippen. Wenn die Suche beendet ist, wird regedit den Fokus stehlen. - endolith
@endolith: Nicht reproduzierbar, mit Windows 8 Replay Vorschau hier. Welches Betriebssystem verwenden Sie? In meinem Fall hebt es nur die Anwendung am unteren Rand hervor, unterbricht aber mein Browsen überhaupt nicht ... - Tom Wijsman
Ja, Win7 Pro 64-Bit. Und Fokus-Diebstahl ist noch schlimmer für erhöhte Prozesse, da sie Ihre <Enter> drücken, wenn sie nicht sollten, und Sie sagen, dass sie Ihr System versehentlich schleusen. Nichts sollte je in der Lage sein, den Fokus zu stehlen. - endolith


Es gibt eine Option in TweakUI was macht das. Es verhindert die meisten Tricks, die zweifelhafte Softwareentwickler anwenden, um den Fokus auf ihre App zu legen.

Es ist jedoch ein andauernder Waffenkrieg, also weiß ich nicht, ob es für alles funktioniert.

Aktualisieren: Gemäß GefährdetMassa, TweakUI funktioniert nicht unter Windows 7.


18
2017-08-05 09:12



ist Tweakui kompatibel mit Windows 7? - frankster
@Frankster. Keine Ahnung, tut mir leid, ich vermute es wahrscheinlich nicht. Laden Sie es herunter und probieren Sie es aus. Melden Sie sich zurück, wenn Sie dies tun, jeder weiß es. - Simon P Stevens
Auch die Verwendung der Registrierungseinstellung, die TweakUI setzt, funktioniert nicht auf Win7. - EndangeredMassa
@ EndangeredMassa welcher Registrierungsschlüssel ist das? - n611x007
Der Registrierungsschlüssel ist HKEY_CURRENT_USER \ Control Panel \ Desktop \ ForegroundLockTimeout (in Millisekunden). Und ja, unter Windows 7 funktioniert es nicht mehr. - foo


Ich glaube, dass einige Verwirrung existieren kann, da es zwei Möglichkeiten gibt, "Fokus zu stehlen": (1) ein Fenster, das in den Vordergrund kommt, und (2) das Fenster, das Tastenanschläge empfängt.

Das Problem, auf das hier Bezug genommen wird, ist wahrscheinlich das zweite, bei dem a Windows beansprucht den Fokus, indem es sich selbst in den Vordergrund stellt - ohne die Anfrage oder Erlaubnis des Benutzers.

Die Diskussion muss hier zwischen XP und 7 aufgeteilt werden.

Windows XP

In XP gibt es ein Registry-Hack, der XP genauso wie Windows 7 beim Verhindern des Stehlens von Anwendungen verhindert:

  1. Verwenden Sie regedit, um zu gehen: HKEY_CURRENT_USER\Control Panel\Desktop.
  2. Doppelklicken Sie auf ForegroundLockTimeout und setze seinen Wert in hexadezimal auf 30d40.
  3. Drücken Sie OK und beenden Sie regedit.
  4. Starten Sie Ihren PC neu, damit die Änderungen wirksam werden.

Windows 7

(Die folgende Diskussion trifft meistens auch auf XP zu.)

Bitte haben Sie Verständnis dafür, dass Windows Anwendungen nicht daran hindern kann, den Fokus zu stehlen und funktionsfähig zu bleiben. Wenn zum Beispiel während einer Dateikopie Ihr Antivirenprogramm eine mögliche Bedrohung erkannt hat und möchte ein Fenster öffnen, in dem Sie gefragt werden, welche Aktion ausgeführt werden soll, wenn dieses Fenster blockiert ist dann würdest du nie verstehen, warum die Kopie niemals endet.

In Windows 7 ist nur eine Änderung am Verhalten von Windows selbst möglich das benutzen MS-Windows Fokus-folgt-Maus Registry-Hacks, wobei der Fokus und / oder die Aktivierung immer zu den Fenstern unter dem Cursor gehen. Es kann eine Verzögerung hinzugefügt werden, um zu verhindern, dass Anwendungen auf dem Desktop angezeigt werden.
Siehe diesen Artikel: Windows 7 - Mouse Hover macht Fenster aktiv - Aktivieren.

Ansonsten muss man das schuldige Programm erkennen und neutralisieren: Wenn dies immer die gleiche Anwendung ist, die den Fokus erhält, dann diese Anwendung ist darauf programmiert, den Fokus zu nehmen und dies zu verhindern, indem Sie entweder den Start des Computers deaktivieren oder eine Einstellung verwenden, die von dieser Anwendung bereitgestellt wird, um dieses Verhalten zu vermeiden.

Sie könnten das VBS-Skript verwenden enthalten in VB-Code, der identifiziert, wer den Fokus stiehlt, mit dem sich der Autor identifiziert hat der Übeltäter als "Call Home" Updater für eine Druckersoftware.

Eine verzweifelte Maßnahme, wenn alles andere fehlschlägt, und wenn Sie diese schlecht programmierte Anwendung identifiziert haben, ist es zu minimieren und hoffe, dass sich das dann nicht nach vorne bringen wird. Eine stärkere Form der Minimierung ist das Tablett, indem Sie eines der kostenlosen Produkte verwenden, die in aufgelistet sind Beste kostenlose Anwendung Minimizer.

Letzte Idee in der Reihenfolge der Verzweiflung ist es, Ihren Desktop virtuell zu zerbrechen, indem Sie ein Produkt verwenden sowie Desktops oder Dexpot, und mache deine Arbeit auf einem anderen Desktop als dem Standard.

[BEARBEITEN]

Da Microsoft die Archiv-Galerie zurückgezogen hat, ist hier der obige VB-Code wiedergegeben:

Declare Auto Function GetForegroundWindow Lib "user32.dll" () As Integer
Declare Auto Function GetWindowThreadProcessId Lib "user32.dll" (ByVal hwnd As Integer, ByRef procid As Integer) As UInteger

    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        Me.RichTextBox1.AppendText("Starting up at " & Now & vbCrLf)
    End Sub

    Private Sub GoingAway(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Deactivate, Me.LostFocus

        Dim hwnd As Integer = GetForegroundWindow()
        ' Note that process_id will be used as a ByRef argument
        ' and will be changed by GetWindowThreadProcessId
        Dim process_id As Integer = 1
        GetWindowThreadProcessId(hwnd, process_id)

        If (process_id <> 1) Then
            Dim appExePath As String = Process.GetProcessById(process_id).MainModule.FileName() 
            Me.RichTextBox1.AppendText("Lost focus at " & Now & " due to " & appExePath & vbCrLf)
        Else
            Me.RichTextBox1.AppendText("Lost focus due to unknown cause.")
        End If

    End Sub

14
2018-06-09 09:22



"Wenn dieses Fenster blockiert ist, würdest du nie verstehen, warum die Kopie niemals beendet wird" Das ist nicht wahr. Das richtige Verhalten besteht darin, den Benutzer mit einem blinkenden Taskleistensymbol (oder einem Popup-Popup oder einer Toasterbenachrichtigung oder etwas anderem) zu benachrichtigen. Wenn der Benutzer mit einem Fenster unterbrochen wird, das seine Tastenanschläge abfängt, weist er die Antivirensoftware an, die eine oder andere Aktion zufällig auszuführen. Definitiv kein guter Weg, Dinge zu tun. - endolith
"Wenn dieses Fenster blockiert ist, würdest du nie verstehen, warum die Kopie niemals beendet wird" Das ist nicht wahr. Das richtige Verhalten besteht darin, den Benutzer mit einem blinkenden Taskleistensymbol zu benachrichtigen ...   Es gab Zeiten, als ich auf einen Knopf oder etwas in einem laufenden Programm klickte, das verursacht, dass ein neuer modaler Dialog verursacht wird (z. B. Datei öffnen), aber dann wechsle ich zu einem anderen Programm, bevor der Dialog erstellt wird. Daher ist der Dialog ausgeblendet, und auf das andere Programm kann nicht umgeschaltet werden, und der Dialog kann nicht geschlossen werden. Weder sein Taskleisten-Button noch Alt-Tab arbeitet; Erzwingt nur den Dialog nach vorne. - Synetech
@Synetech: Manchmal ist die einzige Lösung für den Nicht-Front-Dialog, die Aufgabe zu beenden. Die Fokusalgorithmen in Windows sind wirklich mies. - harrymc
@ Harrymc, ich muss nie auf eine der Apps zurückgreifen. Ich führe gerade mein Programm zur Manipulation von Fenstern aus (WinSpy ++ macht den Trick einfach toll) und versteckt das Fenster davor, dann kann ich den stuck-back-Dialog weglassen, dann das versteckte Fenster wieder einblenden. Es ist nicht praktisch, aber es ist besser als einen der Prozesse zu töten. - Synetech
@ Harrymc, nicht wirklich; eine App zu töten und Dinge zu verlieren macht nur mehr Dampf, und wenn es ein modales Dialogfeld ist (das das Elternfenster sperrt und keine Taskleiste hat), wird es nicht in der Alt+Tab Liste, und nach meiner Erfahrung zeigt ein Fenster, das einen modalen Dialog geöffnet hat, nicht immer (nie?) den modalen Dialog mit Alt+Tabbesonders, wenn der Dialog nie geändert wurde, um den Fokus zu erhalten. :-| - Synetech


Ghacks hat eine mögliche Lösung:

Es passiert mehrmals am Tag, dass   Einige Anwendungen stehlen den Fokus von   das aktive Fenster durch Aufklappen. Dies   kann aus einer Reihe von Gründen passieren,   wenn ich Dateien oder eine Übertragung extrahiere   endet zum Beispiel. Es tut nicht   Wenn es darum geht, die meiste Zeit   passiert aber manchmal schreibe ich ein   Artikel und das bedeutet nicht nur, dass   Ich muss noch ein paar Worte eingeben, aber   auch dass ich die Konzentration verloren habe und   muss klicken, um den Fokus wieder zu erlangen.

Das Pro Reviewer Website hat einen Tipp auf   wie man das verhindern kann.   Der einfachste Weg, den Fokus zu vermeiden   Stehlen ist Tweak UI zu verwenden, die hat   eine Einstellung, die "Prevent   Anwendungen von stehlen Fokus ".   Wenn Sie diese Option aktivieren, wird dies verhindert   andere Anwendungen erscheinen plötzlich und   stehlen Sie den Fokus des Fensters, das Sie sind   arbeitet derzeit in.

Dies funktioniert nur bei der Anwendung   wurde vorher minimiert. Anstatt von   stehlen den Fokus wird es blinken a   Anzahl der Zeiten, die definiert werden können   im selben Menü in Tweak UI. Wenn du   Ich möchte Tweak UI nicht verwenden   Ändern Sie die Einstellung in Windows   Registrierung.

Navigieren Sie zum Registrierungsschlüssel   HKEY_CURRENT_USER> Systemsteuerung>   Desktop und ändern Sie die   ForegroundLockTimeout-Wert auf 30d40   (Hexadezimal) oder 200000 (Dezimal). Das   Schlüssel ForeGroundFlashCount definiert die   Anzahl der Blitze eines zu alarmierenden Fensters   der Benutzer mit 0 bedeutet unbegrenzt.


2
2017-08-05 09:13



Dies funktioniert auf keinem Betriebssystem nach XP. Dieser Registry-Wert ist bereits darauf eingestellt (standardmäßig glaube ich) und funktioniert sowieso nicht. - EndangeredMassa
Nur um zu sagen, dass ich auf Windows 7 (64-Bit) bin, beim Fokussieren stehlen (VS 2012, wenn es endlich aktiv ist, für Beispiel), und der obige Registrierungsvorschlag ist bereits vorhanden. Technische Bestätigung in dieser Antwort: superuser.com/a/403554/972 - Michael Paulukonis