Продолжение....
Код:
LRESULT CALLBACK CalcWndProcHook(int nCode, WPARAM wParam, LPARAM lParam)
{
__try{
PTHREAD_DATA pThreadData = TlsGetValue(dwDataIndex);
if( HC_ACTION == nCode){
// Убедиться лишний раз в том, что хук вызван именно в калькуляторе никогда не вредно
if(bIsCalc){
CWPSTRUCT *pcwp = (CWPSTRUCT *)lParam;
// Если хук уже нашел главное окно приложения и убедился, что это окно - калькулятор,
// то идём по сокращщенному пути. В принципе, это можно было бы решить заменой
// указателя на функцию в отдельной глобальной переменной и вызывать её здесь -
// как всегда, любую задачу можно решить множеством способов
if(hMainWindow){
if(pcwp->hwnd == hMainWindow){
if(pcwp->message == WM_COMMAND && LOWORD(pcwp->wParam) == 0x70){
// 0x70 - это команда калькулятора, вызываемая при нажатии на "="
// увеличиваем счётчик "срабатываний",
InterlockedIncrement(&ulInterceptCount);
// выставляем глобальный сигнал и выходим
SetEvent(hCommSignal);
return 0;
}
}
}
else {
// По-видимому наш хук ещё не нашел нужное окно или оно ещё не создано,
// продолжаем усиленно и разными методами проверять.
// Вообще говоря, здесь не помешает счётчик неудачных попыток
if(pcwp->hwnd && GetParent(pcwp->hwnd) == NULL){
if(GetWindowThreadProcessId(pcwp->hwnd, NULL) == GetCurrentThreadId()){
if(IsWindowUnicode(pcwp->hwnd)){
WCHAR wcClassName[32];
if(GetClassNameW(pcwp->hwnd, wcClassName, 32) > 0){
if(0 == lstrcmpW(wCalcClassName, wcClassName)) {
// По-видимому мы нашли нужное окно.
// Тогда еще перехватываем оконную функцию калькулятора
OldCalcWndProc = (WNDPROC)SetWindowLongPtrW(
pcwp->hwnd,
GWLP_WNDPROC,
(LONG_PTR)CalcSubClassWndProcW);
hMainWindow = pcwp->hwnd;
pThreadData->hGMHook = SetWindowsHookExW(
WH_GETMESSAGE,
CalcGetMsgHook,
GetModuleHandleW(HOOK_DLL_NAMEW),
GetCurrentThreadId());
}
}
}
else {
CHAR cClassName[32];
if(GetClassNameA(pcwp->hwnd, cClassName, 32) > 0){
if(0 == lstrcmpA(aCalcClassName, cClassName)) {
OldCalcWndProc = (WNDPROC)SetWindowLongPtrA(
pcwp->hwnd,
GWLP_WNDPROC,
(LONG_PTR)CalcSubClassWndProcA);
hMainWindow = pcwp->hwnd;
pThreadData->hGMHook = SetWindowsHookExA(
WH_GETMESSAGE,
CalcGetMsgHook,
GetModuleHandleA(HOOK_DLL_NAMEA),
GetCurrentThreadId());
}
}
}
}
}
}
}
}
return CallNextHookEx(pThreadData->hCWPHook, nCode, wParam, lParam);
}
__except(EXCEPTION_EXECUTE_HANDLER){
OutputDebugStringA("Exception. *** CalcWndProcHook ***\n");
return 0;
}
}
// Это хук для WH_GETMESSAGE
// Блокирует работу "большого" Enter'а и цифр на обычной клавиатуре,
// оставляет только расширенную
LRESULT CALLBACK CalcGetMsgHook(int nCode, WPARAM wParam, LPARAM lParam)
{
__try{
PTHREAD_DATA pThreadData = TlsGetValue(dwDataIndex);
if( HC_ACTION == nCode){
LPMSG pmsg = (LPMSG) lParam;
if(WM_KEYDOWN == pmsg->message || WM_KEYUP == pmsg->message){
if(
(VK_RETURN == pmsg->wParam && !(pmsg->lParam & (1 << 24)))
||
(pmsg->wParam >= '0' && pmsg->wParam <= '9')
){
FLASHWINFO fwi;
fwi.cbSize = sizeof(FLASHWINFO);
fwi.dwFlags = FLASHW_CAPTION;
fwi.uCount = 3;
fwi.hwnd = hMainWindow;
fwi.dwTimeout = 200;
FlashWindowEx(&fwi);
pmsg->message = WM_NULL;
}
}
}
return CallNextHookEx(pThreadData->hGMHook, nCode, wParam, lParam);
}
__except(EXCEPTION_EXECUTE_HANDLER){
OutputDebugStringA("Exception. *** CalcGetMsgHook ***\n");
return 0;
}
}