Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Системное программирование и WinAPI > Hook && WM_ERASEBKGND


Автор: TGrey 20.6.2010, 14:22
Здравствуйте, рисую в контексте другого окна свою картинку, но временами, другое приложение вызывает очистку фона, что создает блики моей картинки. Проверку отрисовки своей картинки я выполняю через хук окна в котором нужно рисовать. Мне интересно, как из хука запретить стирать фон? Я же не могу вернуть ложь, нужно вызывать след. хук?!

Автор: GremlinProg 23.6.2010, 10:41
Цитата(TGrey @  20.6.2010,  16:22 Найти цитируемый пост)
Я же не могу вернуть ложь, нужно вызывать след. хук?!

а кто мешает?

Автор: TGrey 23.6.2010, 17:59
Все равно, Спай++ показывает, что что ШеллТрей принимает\отсылает очистку фона с true.
А мой хук это сообщение вообще не видит.
Код

extern "C" __declspec(dllexport) bool TurnON()
{
    //MessageBox(NULL, "Hook ON", "ON", 0);
    HWND hTray = FindWindow( "Shell_TrayWnd", 0);
    hook = SetWindowsHookEx(WH_GETMESSAGE, HookProc,hin, GetWindowThreadProcessId(hTray, &dw));
    return true;
}

LRESULT CALLBACK HookProc( int nCode, WPARAM wParam,LPARAM lParam)
{
    MSG * st = (MSG*)lParam;
    HWND hTray, start, trayn;

    hTray = FindWindow( "Shell_TrayWnd", 0);
    if( nCode == HC_ACTION )
    {
         if( st->message == WM_ERASEBKGND  )
        {
            //MessageBox(0, "222", "a",0);
            CallNextHookEx(hook, nCode, wParam, lParam);
            return false;
        }
        else if( st->message == WM_NCLBUTTONDOWN  )
        {
            //SendMessage(hTray, WM_USER+100, 0, 0);
            MessageBox(0, "111l", "a",0);
        }
    }
    return CallNextHookEx(hook, nCode, wParam, lParam);
}

WM_NCLBUTTONDOWN - хукается, сообщение выводится, а очистка фона - нет.

Автор: Earnest 23.6.2010, 20:00
Скорее всего, WM_GETMESSAGE здсь не годится. Насколько я помню, ERASEBACKGND не через очередь приходит, а прямо. Т.е. нужен другой хук.

Автор: TGrey 23.6.2010, 22:14
А что мне хукать тогда?

Автор: Earnest 24.6.2010, 09:17
Попробуй WH_CALLWNDPROC

Автор: TGrey 24.6.2010, 13:43
На это сообщение, тоже, ничего ловить не хочет.

Автор: Earnest 24.6.2010, 17:02
Не сообщение, а тип хука, который ты ставишь в SetWindowsHookEx. 

Автор: TGrey 24.6.2010, 20:23
Ой извиняюсь, я и имел ввиду тип хука. Не хочет ничего. Даже Клик мышкой и тот не обрабатывает.
Код

extern "C" __declspec(dllexport) bool TurnON()
{
    //MessageBox(NULL, "Hook ON", "ON", 0);
    HWND hTray = FindWindow( "Shell_TrayWnd", 0);
    HWND trayn = FindWindowEx( hTray, NULL, "TrayNotifyWnd", 0);
    DWORD dw;
    //hook = SetWindowsHookEx(WH_GETMESSAGE, HookProc,hin, GetWindowThreadProcessId(hTray, &dw));
    hook = SetWindowsHookEx(WH_CALLWNDPROC, HookProc,hin, GetWindowThreadProcessId(hTray, &dw));
    return true;
}

extern "C" __declspec(dllexport) bool TurnOFF()
{
    UnhookWindowsHookEx(hook);
    return true;
}

LRESULT CALLBACK HookProc( int nCode, WPARAM wParam,LPARAM lParam)
{
    MSG * st = (MSG*)lParam;
    HWND hTray, start, trayn;
    if( nCode == HC_ACTION )
    {
         if( st->message == WM_ERASEBKGND  )
        {
            MessageBox(0, "фф", "a",0);
            //CallNextHookEx(hook, nCode, wParam, lParam);
            //return false;
        }
        else if( st->message == WM_NCLBUTTONDOWN  )
        {
            MessageBox(0, "вв", "a",0);
        }
    }
    return CallNextHookEx(hook, nCode, wParam, lParam);
}

Автор: Earnest 25.6.2010, 06:14
Цитата(TGrey @  24.6.2010,  21:23 Найти цитируемый пост)
 MSG * st = (MSG*)lParam;

Посмотри в MSDN, как параметры нужно распаковывать.У каждого хука по своему.

Автор: TGrey 25.6.2010, 11:16
Да я понял, использовал не ту структуру. Хорошо, сейчас ловит, но как запретить то перерисовку?
Код

    CWPSTRUCT *st2 = (CWPSTRUCT*)lParam;

    if( nCode == HC_ACTION )
    {
         if( st2->message == WM_ERASEBKGND  )
        {
            //CallNextHookEx(hook, nCode, wParam, lParam);
            return false;
        }

Не очень помогает.
Если до хука сообщения выглядят как
WM_ERASEBKGND hdc:<........>
WM_ERASEBKGND fErased: True
То после хука
WM_ERASEBKGND fErased: True

В итоге моя картинка по прежнему мигает.

Автор: GremlinProg 25.6.2010, 11:24
Цитата(TGrey @  25.6.2010,  13:16 Найти цитируемый пост)
return false;

return TRUE;
Цитата(WM_ERASEBKGND Notification @  MSDN)

An application should return nonzero if it erases the background; otherwise, it should return zero. 


Добавлено через 4 минуты
только это не поможет, если приложение само заливает фон на WM_PAINT

Автор: TGrey 25.6.2010, 11:40
Кстати да, пробовал я и Истину возвращать. Видимо оно так и делает.
А как можно организовать хук сообщение и очистки фона и прорисовки? Я понимаю, что прорисовку нужно же ловить на WH_GETMESSAGE. Или если можно и через WH_CALLWNDPROC, то смысл было делать разные способы?

Автор: GremlinProg 25.6.2010, 11:56
несколькими хуками,
WH_CALLWNDPROC и WH_GETMESSAGE - не разные сами по себе,
просто они приложены в разных местах, поэтому есть шанс пропустить сообщение, если не реализовать оба,

к примеру такая посылка 2-х сообщений:
Код

SendMessage( hwnd, WM_USER + 123, ... );
PostMessage( hwnd, WM_USER + 123, ... );

будет перехвачена разными хуками

Автор: TGrey 25.6.2010, 12:06
Ну то есть из одной ДЛЛ можно подряд создать 2 хука и 2 процедуры фильтра, запустить и все будет нормально работать?

Автор: GremlinProg 25.6.2010, 12:18
конечно можно

Автор: TGrey 25.6.2010, 12:22
Тогда последний вопрос, как же запретить перерисовку фона? Или сообщения типа
Цитата

WM_ERASEBKGND hdc:<........>
WM_ERASEBKGND fErased: True
То после хука
WM_ERASEBKGND fErased: True

и есть признак что перерисовка запрещена? Или как вернуть fErased:false

Автор: Earnest 25.6.2010, 12:26
Может я ошибаюсь, но, по-моему, WH_CALLWNDPROC ловит все (ну, за исключением, возможно, низкоуровневого ввода). В MSDN написано, что этот хук стоит на входе CallWndProc, а мимо этого, вроде бы, ничего не проскакивает. WH_GETMESSAGE - да, только на очереди. 

Автор: GremlinProg 25.6.2010, 12:31
Цитата(TGrey @  25.6.2010,  14:22 Найти цитируемый пост)
Или сообщения типа ... и есть признак что перерисовка запрещена?

флага fErased у WM_ERASEBKGND нет, это spy скорее всего интерпретирует результат обработки WH_CALLWNDPROCRET, а конкретно: PAINTSTRUCT::fErase

fErased = TRUE означает что фон закрашивать не надо, он уже закрашен, т.е. если приложение принимает этот флаг во внимание, то ничего закрашивать не будет,

нет - значит не судьба, претензии тут могут быть только к разработчикам этой программы, а не к хукам

Добавлено через 4 минуты и 28 секунд
Цитата(Earnest @  25.6.2010,  14:26 Найти цитируемый пост)
Может я ошибаюсь, но, по-моему, WH_CALLWNDPROC ловит все (ну, за исключением, возможно, низкоуровневого ввода). В MSDN написано, что этот хук стоит на входе CallWndProc, а мимо этого, вроде бы, ничего не проскакивает. WH_GETMESSAGE - да, только на очереди. 

я тоже немного сомневаюсь, это можно проверить, залогировав работу обоих хуков

если DispatchMessage вызывает CallWindowProc, то да - будет ловить все

Добавлено через 5 минут и 35 секунд
TranslateAccelerator, кстати тоже тогда должна звать CallWindowProc в этом случае

Добавлено через 6 минут и 36 секунд
фу ты, CallWndProc, конечно

Автор: TGrey 25.6.2010, 12:39
А такой еще вопрос, написано что WH_CALLWNDPROC 
Цитата

The CallWndProc hook procedure can examine the message, but it cannot modify it. After the hook procedure returns control to the system, the message is passed to the window procedure. 

Как же так, а если я и ставлю хук для того, чтобы изменить что-то. То смысл мне просто словить его?
Вот взять к примеру из моей другой темы, шлется сообщение WM_USER+100, мне надо изменить ширену часов, изменю ее в хуке, а потом оно все равно отправит оригинал дальше?

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)