Прорисовка меню
От: Glas  
Дата: 05.11.09 14:41
Оценка:
Столкнулся с такой проблемой. Создан класс на основе CMenu с перегруженной функцией DrawItem. В ней, помимо отрисовки итемов меню, задаю стиль окна этой самой меню(прозрачность и регион), но при вызове этой самой меню сначала появляется меню без изменений и лишь когда наводишь мышь оно резко меняется. Пробовал отловить сообщения OnInitMenu и OnInitPopupMenu не помогло, меняется главное диалоговое окно, а не меню. Где еще можно отловить инициализацию окна меню?
Re: Прорисовка меню
От: Vis Украина  
Дата: 06.11.09 01:45
Оценка:
Здравствуйте, Glas, Вы писали:

G>Столкнулся с такой проблемой. Создан класс на основе CMenu с перегруженной функцией DrawItem. В ней, помимо отрисовки итемов меню, задаю стиль окна этой самой меню(прозрачность и регион), но при вызове этой самой меню сначала появляется меню без изменений и лишь когда наводишь мышь оно резко меняется. Пробовал отловить сообщения OnInitMenu и OnInitPopupMenu не помогло, меняется главное диалоговое окно, а не меню. Где еще можно отловить инициализацию окна меню?


Я думаю, придется это делать через хук.
Вот здесь кусок кода..

HHOOK CFlatMenu::m_hHook = NULL;

const TCHAR _WndPropName_OldProc[] = _T("XPWndProp_OldProc");
const TCHAR _WndPropName_MenuXP[] = _T("XPWndProp_MenuXP");


LRESULT CALLBACK CFlatMenu::FlatMenuWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    WNDPROC oldWndProc = (WNDPROC)::GetProp (hWnd, _WndPropName_OldProc);

    //LPWINDOWPOS lpPos;
    switch ( uMsg )
       {                    
        case WM_СREATE:
                   // Тебе сюды.
        break;
    }

    return CallWindowProc(oldWndProc, hWnd, uMsg, wParam, lParam);    
}


LRESULT CALLBACK CFlatMenu::HookProc(int code, WPARAM wParam, LPARAM lParam)
{
    TCHAR sClassName[10];
    CWPSTRUCT* pStruct = (CWPSTRUCT*)lParam;

    // Not a real loop (just for 'break' branchment)
    while ( code == HC_ACTION )
    {
        HWND hWnd = pStruct->hwnd;

        int Count = ::GetClassName (hWnd, sClassName, sizeof(sClassName)/sizeof(TCHAR));
        
        // Check for the menu-class
        if ( Count != 6 || _tcscmp (sClassName, _T("#32768")) != 0 )
        {            
            break;
        }        
        // Normal and special handling for menu 0x10012
        if ( pStruct->message != WM_CREATE && pStruct->message != WM_NCCREATE && pStruct->message != 0x01E2 )
        {
            break;
        }               
        
        //VERIFY(CWndMenuXP::FromHandle (pStruct->hwnd, false) != NULL);

        if ( ::GetProp (pStruct->hwnd, _WndPropName_OldProc) != NULL )
        {
            // Already subclassed
            break;
        }
        // Subclass the window
        WNDPROC oldWndProc = (WNDPROC)(LONG_PTR)::GetWindowLong (pStruct->hwnd, GWL_WNDPROC);

        if ( oldWndProc == NULL )
        {
            break;
        }
        ASSERT(oldWndProc != FlatMenuWndProc);

        if ( !SetProp (pStruct->hwnd, _WndPropName_OldProc, oldWndProc) )
        {
            break;
        }

        if ( !SetWindowLong (pStruct->hwnd, GWL_WNDPROC,(DWORD)(DWORD_PTR)FlatMenuWndProc) )
        {
            ::RemoveProp (pStruct->hwnd, _WndPropName_OldProc);
            break;
        } 
    
        ATLTRACE(_T("Success\r\n"));    
        // Success !
        break;
    }

    return CallNextHookEx (m_hHook, code, wParam, lParam);
}

void CFlatMenu::InitializeHook()
{
    m_hHook = SetWindowsHookEx(WH_CALLWNDPROC, HookProc, NULL, ::GetCurrentThreadId());
}

void CFlatMenu::UninitializeHook()
{
    UnhookWindowsHookEx(m_hHook);
}
Re[2]: Прорисовка меню
От: Glas  
Дата: 06.11.09 08:57
Оценка:
Здравствуйте, Vis, Вы писали:

Vis>Здравствуйте, Glas, Вы писали:


G>>Столкнулся с такой проблемой. Создан класс на основе CMenu с перегруженной функцией DrawItem. В ней, помимо отрисовки итемов меню, задаю стиль окна этой самой меню(прозрачность и регион), но при вызове этой самой меню сначала появляется меню без изменений и лишь когда наводишь мышь оно резко меняется. Пробовал отловить сообщения OnInitMenu и OnInitPopupMenu не помогло, меняется главное диалоговое окно, а не меню. Где еще можно отловить инициализацию окна меню?


Vis>Я думаю, придется это делать через хук.

Vis>Вот здесь кусок кода..

Глупый вопрос, конечно, а куда это добавлять? Ногами не бить, я еще только учусь работать MFC .
Re[3]: Прорисовка меню
От: Vis Украина  
Дата: 06.11.09 09:25
Оценка:
Здравствуйте, Glas, Вы писали:

Vis>>Я думаю, придется это делать через хук.

Vis>>Вот здесь кусок кода..
G>Глупый вопрос, конечно, а куда это добавлять? Ногами не бить, я еще только учусь работать MFC .
Для начинающего — очень даже неглупый... Хуки — это продвинутая техника...

Строго говоря, чтоьбы только испытать этот код, можно все функции сделать глобальными.
У меня они объединены в класс и являются статическими. Так что можно создать класс СFlatMenu у которого все методы статические.

InitializeHook() нужно вызвать перед прорисокой первого меню, а скорее всего — в начале приложения, где-то в InitInstance. UninitializeHook() — где-то в конце. Как вариант — создать глобальный экземпляр класса CFlatMenu а InitializeHook() вызвать в конструкторе.
Re[2]: Прорисовка меню
От: Glas  
Дата: 06.11.09 09:42
Оценка:
Так разобрался с кодом, только вот окно не меняется, да еще и следы от менюшки остаются после закрытия.

...
case WM_CREATE:
    if (hWnd == FindWindow(_T("#32768"), NULL))
    {
    SetWindowLong(hWnd, GWL_EXSTYLE, GetWindowLong(hWnd, GWL_EXSTYLE) | WS_EX_LAYERED);
    SetLayeredWindowAttributes(hWnd, 0, 150, LWA_ALPHA);
    }
break;
...
Re[4]: Прорисовка меню
От: Glas  
Дата: 06.11.09 12:54
Оценка:
Здравствуйте, Vis, Вы писали:

Vis>Здравствуйте, Glas, Вы писали:


Vis>>>Я думаю, придется это делать через хук.

Vis>>>Вот здесь кусок кода..
G>>Глупый вопрос, конечно, а куда это добавлять? Ногами не бить, я еще только учусь работать MFC .
Vis>Для начинающего — очень даже неглупый... Хуки — это продвинутая техника...

Vis>Строго говоря, чтоьбы только испытать этот код, можно все функции сделать глобальными.

Vis>У меня они объединены в класс и являются статическими. Так что можно создать класс СFlatMenu у которого все методы статические.

Vis>InitializeHook() нужно вызвать перед прорисокой первого меню, а скорее всего — в начале приложения, где-то в InitInstance. UninitializeHook() — где-то в конце. Как вариант — создать глобальный экземпляр класса CFlatMenu а InitializeHook() вызвать в конструкторе.


эх, все гениальное как всегда просто Я поставил не те флаги в TrackPopupMenu вот оно и менялось только при наведении.
Re[5]: Прорисовка меню
От: Vis Украина  
Дата: 06.11.09 15:10
Оценка:
Здравствуйте, Glas, Вы писали:

G>Здравствуйте, Vis, Вы писали:


Vis>>Здравствуйте, Glas, Вы писали:


Vis>>InitializeHook() нужно вызвать перед прорисокой первого меню, а скорее всего — в начале приложения, где-то в InitInstance. UninitializeHook() — где-то в конце. Как вариант — создать глобальный экземпляр класса CFlatMenu а InitializeHook() вызвать в конструкторе.


G>эх, все гениальное как всегда просто Я поставил не те флаги в TrackPopupMenu вот оно и менялось только при наведении.


Флаги — один из этого списка?
TPM_HORNEGANIMATION
TPM_HORPOSANIMATION
TPM_NOANIMATION
TPM_VERNEGANIMATION
TPM_VERPOSANIMATION
Re[6]: Прорисовка меню
От: Glas  
Дата: 06.11.09 17:08
Оценка:
Здравствуйте, Vis, Вы писали:

Vis>Здравствуйте, Glas, Вы писали:


G>>Здравствуйте, Vis, Вы писали:


Vis>>>Здравствуйте, Glas, Вы писали:


Vis>>>InitializeHook() нужно вызвать перед прорисокой первого меню, а скорее всего — в начале приложения, где-то в InitInstance. UninitializeHook() — где-то в конце. Как вариант — создать глобальный экземпляр класса CFlatMenu а InitializeHook() вызвать в конструкторе.


G>>эх, все гениальное как всегда просто Я поставил не те флаги в TrackPopupMenu вот оно и менялось только при наведении.


Vis>Флаги — один из этого списка?

Vis>TPM_HORNEGANIMATION
Vis>TPM_HORPOSANIMATION
Vis>TPM_NOANIMATION
Vis>TPM_VERNEGANIMATION
Vis>TPM_VERPOSANIMATION

Ага, выставил TPM_NOANIMATION и все ок. Но все равно спасибо за отклик, зато с хуками познакомился
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.