Windows 내부 를 광범위하게 조작 하지 않으면 불가능 하며이를 극복해야합니다.
운영 체제에서 다른 작업을 수행하기 전에 한 가지 작업을 수행하는 것이 중요 할 때 매일 컴퓨터를 사용하는 순간이 있습니다. 그렇게하려면 특정 창에 초점을 고정해야합니다. Windows에서이 동작에 대한 제어는 주로 사용하는 개별 프로그램 개발자에게 맡겨집니다.
이 주제와 관련하여 모든 개발자가 올바른 결정을하는 것은 아닙니다.
나는 이것이 매우 실망스럽고 성가시다는 것을 알고 있지만 케이크를 가지고 먹을 수도 없습니다. 일상 생활 전반에 걸쳐 포커스가 특정 UI 요소 또는 포커스가 고정 된 상태로 유지되도록 요청하는 응용 프로그램으로 완벽하게 이동하는 경우가 많이 있습니다. 그러나 현재 리더가 누구인지 결정하는 데있어 대부분의 응용 프로그램은 다소 동일하며 시스템은 완벽 할 수 없습니다.
얼마 전에 나는이 문제를 한 번에 해결하는 것에 대한 광범위한 연구를 수행했습니다 (그리고 실패했습니다). 내 연구 결과는 성가신 프로젝트 페이지 에서 찾을 수 있습니다 .
이 프로젝트에는 다음을 호출하여 반복적으로 포커스를 얻으려고하는 응용 프로그램도 포함됩니다.
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;
이 스 니펫에서 알 수 있듯이 내 연구는 내가 싫어하는 사용자 인터페이스 동작의 다른 측면에도 중점을 두었습니다.
이 문제를 해결하는 방법은 모든 새 프로세스에 DLL을로드하고 다른 창을 활성화시키는 API 호출을 연결하는 것입니다.
마지막 부분은 멋진 API 후킹 라이브러리 덕분에 쉬운 부분입니다. 나는 매우 훌륭한 mhook 라이브러리를 사용했습니다 :
#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;
}
당시의 테스트에서 이것은 훌륭하게 작동했습니다. 모든 새로운 프로세스에 DLL을로드하는 부분을 제외하고. 상상할 수 있듯이, 너무 가볍게 취할 필요는 없습니다. 당시 AppInit_DLLs 접근 방식을 사용했습니다 (단순하지 않습니다).
기본적으로 이것은 훌륭하게 작동합니다. 그러나 DLL을 새로운 프로세스에 올바르게 주입 하는 것을 작성할 시간을 찾지 못했습니다 . 그리고 이것에 투자 한 시간은 초점을 훔치는 것이 나를 괴롭히는 것을 크게 어둡게합니다.
DLL 삽입 문제 외에도 Google 코드 구현에서 다루지 않은 포커스 스틸 링 방법이 있습니다. 동료는 실제로 몇 가지 추가 연구를 수행하고 그 방법을 다루었습니다. 문제는 SO에서 논의되었습니다 : https : //.com/questions/7430864/windows-7-prevent-application-from-losing-focus