Bu, Windows dahili dosyalarının kapsamlı bir şekilde 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 rahatsız edici proje 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ıdır, orada bulunan harika API kütüphaneleri sayesinde. Çok iyi 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şleme DLL dosyasını yükleme bölümü hariç. İnsanın hayal edebileceği gibi, bu çok hafif alınacak bir şey değildir. Kullandığım AppInit_DLLs (sadece yeterli değildir) sonra tekrar yaklaşım.
Temel olarak, bu harika çalışıyor. Ancak, DLL'mi yeni işlemlere düzgün bir şekilde enjekte eden bir şey yazmaya zaman 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 ekleme sorununa ek olarak, Google Kodundaki uygulamada kapsamadığı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