Столкнулся с такой проблемой. Создан класс на основе CMenu с перегруженной функцией DrawItem. В ней, помимо отрисовки итемов меню, задаю стиль окна этой самой меню(прозрачность и регион), но при вызове этой самой меню сначала появляется меню без изменений и лишь когда наводишь мышь оно резко меняется. Пробовал отловить сообщения OnInitMenu и OnInitPopupMenu не помогло, меняется главное диалоговое окно, а не меню. Где еще можно отловить инициализацию окна меню?
Здравствуйте, 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);
}
Здравствуйте, Vis, Вы писали:
Vis>Здравствуйте, Glas, Вы писали:
G>>Столкнулся с такой проблемой. Создан класс на основе CMenu с перегруженной функцией DrawItem. В ней, помимо отрисовки итемов меню, задаю стиль окна этой самой меню(прозрачность и регион), но при вызове этой самой меню сначала появляется меню без изменений и лишь когда наводишь мышь оно резко меняется. Пробовал отловить сообщения OnInitMenu и OnInitPopupMenu не помогло, меняется главное диалоговое окно, а не меню. Где еще можно отловить инициализацию окна меню?
Vis>Я думаю, придется это делать через хук.
Vis>Вот здесь кусок кода..
Глупый вопрос, конечно, а куда это добавлять? Ногами не бить, я еще только учусь работать MFC

.
Здравствуйте, Glas, Вы писали:
Vis>>Я думаю, придется это делать через хук.
Vis>>Вот здесь кусок кода..
G>Глупый вопрос, конечно, а куда это добавлять? Ногами не бить, я еще только учусь работать MFC
.
Для начинающего — очень даже неглупый... Хуки — это продвинутая техника...
Строго говоря, чтоьбы только испытать этот код, можно все функции сделать глобальными.
У меня они объединены в класс и являются статическими. Так что можно создать класс СFlatMenu у которого все методы статические.
InitializeHook() нужно вызвать перед прорисокой первого меню, а скорее всего — в начале приложения, где-то в InitInstance. UninitializeHook() — где-то в конце. Как вариант — создать глобальный экземпляр класса CFlatMenu а InitializeHook() вызвать в конструкторе.
Так разобрался с кодом, только вот окно не меняется, да еще и следы от менюшки остаются после закрытия.
...
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;
...
Здравствуйте, Vis, Вы писали:
Vis>Здравствуйте, Glas, Вы писали:
Vis>>>Я думаю, придется это делать через хук.
Vis>>>Вот здесь кусок кода..
G>>Глупый вопрос, конечно, а куда это добавлять? Ногами не бить, я еще только учусь работать MFC
.
Vis>Для начинающего — очень даже неглупый... Хуки — это продвинутая техника...
Vis>Строго говоря, чтоьбы только испытать этот код, можно все функции сделать глобальными.
Vis>У меня они объединены в класс и являются статическими. Так что можно создать класс СFlatMenu у которого все методы статические.
Vis>InitializeHook() нужно вызвать перед прорисокой первого меню, а скорее всего — в начале приложения, где-то в InitInstance. UninitializeHook() — где-то в конце. Как вариант — создать глобальный экземпляр класса CFlatMenu а InitializeHook() вызвать в конструкторе.
эх, все гениальное как всегда просто

Я поставил не те флаги в TrackPopupMenu вот оно и менялось только при наведении.
Здравствуйте, Glas, Вы писали:
G>Здравствуйте, Vis, Вы писали:
Vis>>Здравствуйте, Glas, Вы писали:
Vis>>InitializeHook() нужно вызвать перед прорисокой первого меню, а скорее всего — в начале приложения, где-то в InitInstance. UninitializeHook() — где-то в конце. Как вариант — создать глобальный экземпляр класса CFlatMenu а InitializeHook() вызвать в конструкторе.
G>эх, все гениальное как всегда просто
Я поставил не те флаги в TrackPopupMenu вот оно и менялось только при наведении.
Флаги — один из этого списка?
TPM_HORNEGANIMATION
TPM_HORPOSANIMATION
TPM_NOANIMATION
TPM_VERNEGANIMATION
TPM_VERPOSANIMATION
Здравствуйте, 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 и все ок. Но все равно спасибо за отклик, зато с хуками познакомился