it-swarm.asia

Uygulamaların odağı çalmasını önleme

Etkin pencereden odağı alan uygulamaların önlenmesi için herhangi bir çözüm var mı?

Bu, özellikle bir uygulamaya başladığımda, başka bir şey yapmaya başladığımda can sıkıcı oluyor ve yeni uygulama yarım cümle almaya başlıyor.

189
svandragt

Bu, Windows dahili dosyalarının kapsamlı manipülasyonu olmadan mümkün değildir ve üstesinden gelmeniz gerekir.

Günlük bilgisayar kullanımında, işletim sisteminin başka bir işlem yapmanıza izin vermeden önce bir işlem yapmanızın gerçekten önemli olduğu anlar vardır. Bunu yapmak için, odağınızı belirli pencerelere kilitlemesi gerekir. Windows'ta, bu davranışın kontrolü, büyük ölçüde kullandığınız programların geliştiricilerine bırakılmıştır.

Bu konuyla ilgili olarak her geliştirici doğru kararları vermez.

Bunun çok sinir bozucu ve can sıkıcı olduğunu biliyorum, ama pastanı yiyip de yiyemezsin. Gündelik yaşamınız boyunca, odaklamanın belirli bir UI öğesine taşınması ya da odağın üzerinde kilitli kalmasını isteyen bir uygulamada tamamen iyi olduğunuz muhtemelen bir çok durum vardır. Ancak, çoğu uygulama şu anda kimin lider olduğuna ve sistemin hiçbir zaman mükemmel olamayacağına karar verme konusunda biraz eşittir.

Bir süre önce, bu konuyu bir kez ve herkes için (ve başarısız olarak) çözmek için kapsamlı bir araştırma yaptım. Araştırmamın sonucunu can sıkma projesi sayfasında bulabilirsiniz.

Proje aynı zamanda şunu arayarak odağı art arda almaya çalışan bir uygulama içeriyor:

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;

Bu snippet'ten görebileceğimiz gibi, araştırmam da sevmediğim kullanıcı arayüzü davranışının diğer yönlerine odaklandı.

Bunu çözmeye çalıştığım yol her yeni işleme bir DLL yüklemek ve başka bir pencerenin etkinleştirilmesine neden olan API çağrılarını bağlamaktı.
Son bölüm kolay olanı, harika API kanca takma kütüphaneleri sayesinde. Çok harikaydı mhook kütüphanesini kullandım :

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

O zamanki testlerimden itibaren, bu harika oldu. Her yeni işlem için DLL 'in yüklenmesi kısmı hariç. İnsanın hayal edebileceği gibi, bu çok hafif alınacak bir şey değildir. AppInit_DLLs yaklaşımını o zaman kullandım (bu yeterli değil).

Temel olarak, bu harika çalışıyor. Ancak, düzgün benim DLL 'i yeni işlemlere enjekte eden bir şey yazma zamanını hiç bulamadım. Buna harcanan zaman büyük ölçüde odaklanmanın bana neden olduğu sıkıntıyı gölgede bırakıyor.

DLL enjeksiyon sorununa ek olarak, Google Kodundaki uygulamada yer almadığım bir odak çalma yöntemi de var. Bir meslektaş aslında bazı ek araştırmalar yaptı ve bu yöntemi ele aldı. Sorun SO'da tartışıldı: https://stackoverflow.com/questions/7430864/windows-7-prevent-application-from-losing-focus

50
Der Hochstapler

Windows 7'de ForegroundLockTimeout kayıt defteri girdisi artık denetlenmiyor, bunu İşlem İzleyicisi ile doğrulayabilirsiniz. Aslında, Windows 7'de ön plan penceresini değiştirmenize izin vermezler. Gidin ve okuyun ayrıntıları hakkında , hatta Windows 2000'den beri de olmuştur.

Ancak, dökümantasyon berbattır ve birbirlerini kovalarlar ve bunun etrafında bir yol bulurlar .

Öyleyse, SetForegroundWindow veya benzeri API işlevleriyle ilgili bir sorun var.

Bunu gerçekten doğru şekilde yapmanın tek yolu, düzenli aralıklarla LockSetForegroundWindow adlı küçük bir uygulama yapmaktır, buggy API işlevimize yapılan çağrıları hemen hemen devre dışı bırakır.

Bu yeterli değilse (başka bir buggy API araması?) Daha da ileri gidebilir ve neler olup bittiğini görmek için API izleme yapabilirsiniz, ve sonra basitçe her işlem için API çağrısını kancalayın Bundan sonra any çağrılarından kurtulup ön plana karışabilirsiniz. Ancak, ironik olarak, bu Microsoft tarafından cesaretlendirilir ...

23
Tom Wijsman

Bunu yapan TweakUI seçeneğinde bir seçenek var. Yazılım geliştiricilerin uygulamalarına odaklanmak için kullandıkları olağan hilelerin çoğunu engeller.

Bu devam eden bir silah savaşı, bu yüzden her şey için işe yarayıp yaramadığını bilmiyorum.

Güncelleme : EndangeredMassa ’e göre TweakUI, Windows 7’de çalışmıyor.

18
Simon P Stevens

“Odak çalmanın” iki yolu olduğu için bazı karışıklıkların olabileceğine inanıyorum: (1) ön plana gelen bir pencere ve (2) tuş vuruşlarını alan pencere.

Burada sözü edilen problem, muhtemelen, kullanıcının isteği veya izni olmadan bir pencerenin kendisini ön plana çıkararak odağı talep ettiği ikincisidir.

Tartışma burada XP ve 7 arasında bölünmelidir.

Windows XP

XP'de, uygulamaların odağını çalmasını engellemek için XP'in Windows 7 ile aynı şekilde çalışmasını sağlayan bir kayıt defteri kesmesi vardır:

  1. Gitmek için regedit kullanın: HKEY_CURRENT_USER\Control Panel\Desktop.
  2. ForegroundLockTimeout üzerine çift tıklayın ve değerini onaltılık olarak 30d40 olarak ayarlayın.
  3. OK tuşuna basın ve regedit'ten çıkın.
  4. Değişikliklerin etkili olması için PC'nizi yeniden başlatın.

Windows 7

(Aşağıdaki tartışma çoğunlukla XP için de geçerlidir.)

Lütfen, Windows'un uygulamaların odağı çalmasını tamamen engellemesinin ve işlevsel kalmasının bir yolu olmadığını anlayın. Örneğin, bir dosya kopyası sırasında, virüsten koruma yazılımınız olası bir tehdit tespit ettiğinde ve sizden yapılması gereken eylemi isteyen bir pencere açmak istiyorsa, bu pencere engellenmişse, kopyanın neden sonlanmadığını asla anlayamazsınız.

Windows 7’de, Windows’un kendi davranışında mümkün olan tek bir değişiklik vardır; bu, MS-Windows fokus-takip eden-fare Kayıt Defteri saldırılarını kullanmaktır , odak ve/veya aktivasyon her zaman pencerenin altındaki pencerelere gider. imleç. Masaüstünde tüm uygulamaların ortaya çıkmasını önlemek için bir gecikme eklenebilir.
Bu makaleye bakın: Windows 7 - Fare Vurgusu Pencereyi Etkinleştiriyor - Etkinleştir .

Aksi takdirde, kişi suçlu programı tespit edip etkisiz hale getirmelidir: Bu, her zaman odağı alan aynı uygulama ise, bu uygulama odağı alacak şekilde programlanır ve bunun önlenmesi, bilgisayardan başlayarak engellenerek yapılabilir. Bu davranışı önlemek için o uygulama tarafından sağlanan bazı ayarları kullanın.

VB Kodunda yer alan VBS komut dosyasını kimlerin odağını çektiğini belirten kod kullanabilirsiniz , yazarın suçluyu bir yazıcı yazılımı için "ev arama" güncelleyicisi olarak tanımlamak için kullandığı.

Herkes başarısız olduğunda ve bu kötü programlanmış uygulamayı tanımladıysanız çaresiz bir önlem, onu en aza indirgemek ve daha sonra kendisini öne getirmeyeceğini ummaktır. En İyi Ücretsiz Uygulama Küçültücü içinde listelenen serbest ürünlerden birini kullanarak tepsiye daha güçlü bir küçültme şekli gelir.

Çaresizlik sırasındaki son fikir masaüstünüzü neredeyse - Masaüstü veya Dexpot gibi bir ürün kullanarak kırmak ve çalışmanızı varsayılandan farklı bir masaüstünde yapmaktır.

[DÜZENLE]

Microsoft, Arşiv Galerisi'nden emekli oldukça, yukarıdaki VB kodu yeniden üretildi:

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
harrymc

Der Hochstapler'in cevabından ilham alan , hem 64 hem de 32 bit işlemlerle çalışan ve Windows 7 ya da daha yenisine odaklanmayı önleyen bir DLL enjektörü yazmaya karar verdim: https: // blade.sk/stay-focused/

Çalışma şekli, yeni oluşturulan pencereleri (SetWinEventHook kullanarak) izliyor ve henüz mevcut değilse, pencerenin işlemine Der Hochstapler'in penceresine çok benzeyen DLL enjekte ediyor. DLL'leri kaldırır ve çıkışta özgün işlevselliği geri yükler.

Testlerime göre, şu ana kadar çok iyi çalışıyor. Ancak, sorun yalnızca SetForegroundWindow öğesini çağıran uygulamalardan daha derinleşiyor gibi görünüyor. Örneğin, yeni bir pencere oluşturulduğunda, otomatik olarak ön plana çıkarılır ve bu da kullanıcının başka bir pencereye yazmasını engeller.

Diğer odak çalma yöntemleriyle başa çıkmak için, daha fazla test gereklidir ve gerçekleştiği senaryolar hakkındaki geri bildirimlerini takdir ediyorum.

2
blade

Ghacks'de olası çözüm: var

Günde birkaç kez, bazı uygulamalarda, etkin pencerenin odağını açarak çalıyor. Bu, örneğin dosyaları çıkarttığımda veya bir aktarım bittiğinde çeşitli nedenlerle olabilir. Bunun ne zaman olduğu çoğu zaman önemli değil ama bazen bir makale yazıyorum ve sadece bazı kelimeleri tekrar yazmam gerektiği anlamına gelmiyor, aynı zamanda konsantrasyonu yitirdiğim ve odağı yeniden kazanmak için tıkladığım anlamına da geliyor.

Pro Yorumcu web sitesinin bunun nasıl engelleneceği konusunda bir ipucu var. Odak çalmanın önlenmesinin en kolay yolu, “Uygulamaları odağın çalmasını önle” ayarında Tweak UI kullanmaktır. Bu seçeneğin işaretlenmesi, diğer uygulamaların aniden ortaya çıkmasını ve çalışmakta olduğunuz pencerenin odağını çalmasını önler.

Bu yalnızca uygulama daha önce simge durumuna küçültüldüğünde çalışır. Odağı çalmak yerine, aynı menüde Tweak UI içinde tanımlanabilen birkaç kez yanıp söner. Tweak UI kullanmak istemiyorsanız, ayarı Windows Kayıt Defteri'nde değiştirebilirsiniz.

HKEY_CURRENT_USER> Control Panel> Desktop Kayıt defteri anahtarına gidin ve ForegroundLockTimeout değerini 30d40 (Onaltılık) veya 200000 (Ondalık) olarak değiştirin. Anahtar ForeGroundFlashCount, kullanıcıyı 0 sınırsız anlamına geldiğinde uyarmak için pencerenin yanıp sönme miktarını tanımlar.

2
Ivo Flipse

Bu işlemin ana penceresini başka bir işlemden programlı olarak etkinleştirdikten, en üst düzeye çıkardıktan ve odakladıktan sonra Görev Çubuğunun yeni etkinleştirilen bir hedef pencerenin yanıp sönmesini nasıl durduracağımı öğrendim. Her şeyden önce, bu işleme izin verilip verilmeyeceği konusunda birçok kısıtlama var.

"Sistem, hangi işlemlerin ön plan penceresini ayarlayabileceğini kısıtlar. Bir işlem yalnızca ön koşul penceresini yalnızca aşağıdaki koşullardan biri geçerli olduğunda ayarlayabilir:

  • Süreç ön plan sürecidir.
  • Süreci ön plan süreci ile başladı.
  • İşlem son girdi olayını aldı.
  • Ön plan işlemi yoktur.
  • Ön plan işlemi hata ayıklanıyor.
  • Ön plan kilitli değil (bkz. LockSetForegroundWindow).
  • Ön plan kilitleme zaman aşımı süresi doldu (bkz. SystemParametersInfo'daki SPI_GETFOREGROUNDLOCKTIMEOUT).
  • Hiçbir menü aktif değil.

https://docs.Microsoft.com/en-us/windows/desktop/api/winuser/nf-winuser-allowsetforegroundwindow

Eğer kontrolü işlemi ön planda ise, geçici olarakenablebaşka bir işlemi AllowSetForegroundWindow öğesini çağırarak ön planı tamamen çalmak için başka bir işlemi yapabilir. ileişlem kimliğihedef işlemin. Ondan sonra, hedef işlem kendi pencere tutamacını kullanarak SetForegroundWindow kendisini çağırabilir ve çalışacaktır.

Açıkçası, bu iki süreç arasında bir miktar koordinasyon gerektiriyor, ancak işe yarıyor ve eğer bunu yapıyorsanız, tüm Explorer-click işlemlerini yönlendiren birtek örnekli uygulamauygulamak için Mevcut uygulama örneği, o zaman zaten işleri koordine etmek için zaten bir boru (örneğin) adında bir borcunuz olacak.

0
Glenn Slayden