Ini tidak mungkin tanpa manipulasi internal Windows yang ekstensif dan Anda harus mengatasinya.
Ada saat-saat dalam penggunaan komputer sehari-hari ketika sangat penting bagi Anda untuk melakukan satu tindakan sebelum sistem operasi memungkinkan Anda melakukan hal lain. Untuk melakukan itu, Anda perlu mengunci fokus Anda pada jendela tertentu. Di Windows, kontrol atas perilaku ini sebagian besar diserahkan kepada pengembang program individual yang Anda gunakan.
Tidak semua pengembang membuat keputusan yang tepat dalam hal topik ini.
Saya tahu ini sangat membuat frustrasi dan menjengkelkan, tetapi Anda tidak dapat memiliki kue dan memakannya juga. Mungkin ada banyak kasus sepanjang kehidupan sehari-hari Anda di mana Anda baik-baik saja dengan fokus dipindahkan ke elemen UI tertentu atau aplikasi yang meminta agar fokus tetap terkunci di sana. Tetapi sebagian besar aplikasi agak sama ketika memutuskan siapa yang memimpin saat ini dan sistem tidak akan pernah sempurna.
Beberapa waktu yang lalu saya melakukan penelitian yang luas untuk menyelesaikan masalah ini sekali dan untuk semua (dan gagal). Hasil penelitian saya dapat ditemukan di halaman proyek gangguan .
Proyek ini juga mencakup aplikasi yang berulang kali mencoba meraih fokus dengan menelepon:
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;
Seperti yang dapat kita lihat dari cuplikan ini, penelitian saya juga difokuskan pada aspek lain dari perilaku antarmuka pengguna yang tidak saya sukai.
Cara saya mencoba menyelesaikan ini adalah dengan memuat DLL ke dalam setiap proses baru dan menghubungkan panggilan API yang menyebabkan windows lain diaktifkan.
Bagian terakhir adalah yang mudah, berkat pustaka hooking API yang luar biasa di luar sana. Saya menggunakan perpustakaan mhook yang sangat hebat :
#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;
}
Dari tes saya saat itu, ini bekerja dengan baik. Kecuali untuk bagian memuat DLL ke dalam setiap proses baru. Seperti yang bisa dibayangkan, itu bukan masalah. Saya menggunakan pendekatan AppInit_DLL saat itu (yang tidak cukup).
Pada dasarnya, ini bekerja dengan baik. Tapi saya tidak pernah menemukan waktu untuk menulis sesuatu yang benar menyuntikkan DLL saya ke dalam proses baru. Dan waktu yang diinvestasikan dalam hal ini sebagian besar menutupi kekesalan yang mencuri perhatian saya.
Selain masalah injeksi DLL, ada juga metode mencuri fokus yang tidak saya bahas dalam implementasi di Google Code. Seorang rekan kerja sebenarnya melakukan riset tambahan dan membahas metode itu. Masalahnya dibahas pada SO: https://stackoverflow.com/questions/7430864/windows-7-prevent-application-from-losing-focus