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


Автор: Nastya 2.10.2006, 15:37
Итак задача сделать красивенькие меню (причем как системное, так и попап (контекстное))
Можне решить 2-мя способами:
1. Каким-то боком через хуки или еще чего, зная имя класса окна #32768. Получить HWND меню и подставить ему другую WNDPROC. Там уже резвится в паинте
2. Вместо меню подсунуть диаложек, ну очень на него  похожий с овнердровавскими кнопочками. Но тут траблы со стилем диаложка, должен быть он popup, но при этом при появлении родительское окно должно выглядить как активное (вопрос как????) 
Кроме того соотвествнно при работе с таким меню прийдется работать как с диалогом, хорошо это или плохо не знаю.

Выбор варианта, плиз, обоснуйте. 
Если есть еще идеи, пишите smile

Автор: Earnest 2.10.2006, 16:00
Первый вариант не проходит, т.к. меню - это не окно, и нет у него никакого hWnd и никакой оконной процедуры. Можно в стандартном меню кое-что менять самому, но очень ограниченно.

Остается только второй вариант, только не диаложек, конечно, а просто поп-ап окно. Что тут может быть третье (не окно и не меню - не представляю).
Траблов много: нужно корректно отслеживать потерю фокуса, capture, черта лысого... Но все они решаемы. Что подтверждает масса коммерческих и не очень библиотек, использующих именно этот метод. Вот, скажем, BCG, которую я использую, делает именно так.

Та проблема, на которую ты указала, в MFC, например, решается силовым методом: введен дополнительный стиль поп-апов SYNACTIVE, у главного окна при потери активности из-за такого поп-апа нагло возвращается активный заголовок. Как-то так.  
Т.е. самопальное меню на основе окна не может существовать в вакууме само по себе: ему нужен минимальный фреймворк, который будет его поддерживать.

Добавлено @ 16:06 
Ну, в общем, меню итем можно сделать OwnerDraw, хотя это и не окно. Рисовать его тогда должно окно, которое им владеет. Не знаю в каких пределах можно извращаться, но ясно одно: нужно придумать способ отделения кода рисования меню от окна, что-то типа Reflection в MFC, иначе овчинка не стоит выделки.
Тоже меню совсем отдельно не напишешь (нужна какая-то поддерживающая оболочка).


Автор: Nastya 2.10.2006, 16:11
Цитата

Первый вариант не проходит, т.к. меню - это не окно, и нет у него никакого hWnd и никакой оконной процедуры

Как оказывается есть, если бы не было тогда что бы было бы вторым параметром в WM_ENTERIDLE при показе меню?
ms-help://MS.MSDNQTR.v80.en/MS.MSDN.v80/MS.WIN32COM.v10.en/winui/winui/windowsuserinterface/windowing/dialogboxes/dialogboxreference/dialogboxmessages/wm_enteridle.htm

У меня даже есть опенсоурсный классик, который как раз ставит хуки и отлавливает HWND меню а потом меняет его WNDPROC. Но мне как-то не хочется у себя самой же хуки ставить бр-р-р smile

Добавлено @ 16:16 
Цитата

Та проблема, на которую ты указала, в MFC, например, решается силовым методом: введен дополнительный стиль поп-апов SYNACTIVE

Ой, а что за стиль такой, я его не MSDN не нахожу smile

Автор: Earnest 2.10.2006, 16:26
Цитата(Nastya @  2.10.2006,  17:11 Найти цитируемый пост)
Как оказывается есть, если бы не было тогда что бы было бы вторым параметром в WM_ENTERIDLE при показе меню?

WM_ENTERIDLE приходит не только при показе меню, но и при входе в модальный диалог, когда в нем все устаканится. А если меню, то там хандл окна-владельца:
Цитата

Handle to the dialog box (if wParam is MSGF_DIALOGBOX) or window containing the displayed menu (if wParam is MSGF_MENU). 


Цитата(Nastya @  2.10.2006,  17:11 Найти цитируемый пост)
У меня даже есть опенсоурсный классик, который как раз ставит хуки и отлавливает HWND меню 

Хм... ну кто их знает, может оно и реализовано в глубине души как окно... никогда не сталкивалась...

Цитата(Nastya @  2.10.2006,  17:11 Найти цитируемый пост)
Ой, а что за стиль такой, я его не MSDN не нахожу 

Правильное имя MFS_SYNCACTIVE...

Автор: Nastya 3.10.2006, 11:38
Цитата

Правильное имя MFS_SYNCACTIVE...


Если я правильно поняла, то что бы работал этот штук, надо что бы и родительское и дочернее окна наследовались от каких-то специальных MFC - шных классов.
такой код: эффекта не дает :
Код

    m_SysMenu.Create(IDD_SYSMENU, this->GetParent());
    LONG style = ::GetWindowLongPtr(m_SysMenu.m_hWnd, GWL_STYLE);
    LONG old = ::SetWindowLongPtr(m_SysMenu.m_hWnd, GWL_STYLE, style | MFS_SYNCACTIVE);
    


Добавлено @ 11:39 
http://www.rsdn.ru/Forum/Message.aspx?mid=642366 - вот тут кое-чего по этому поводу smile

Сорри за офтоп, ну до чего же все коряво - то, а?

Добавлено @ 11:39 
Я пытаюсь выкрутится через SW_SHOWNA smile посмотрим че получится smile

Автор: GremlinProg 3.10.2006, 17:48
На самом деле, меню - это тоже окно, только совсем не потому, что в функциях меню фигурирует HWND, а потому что существует MSDN: http://msdn.microsoft.com/library/en-us/winui/winui/windowsuserinterface/windowing/windowclasses/aboutwindow.asp?frame=true#system
Но чтобы слепить красивое меню, достаточно и простого окна.
Цитата(Nastya @  2.10.2006,  17:37 Найти цитируемый пост)
но при этом при появлении родительское окно должно выглядить как активное (вопрос как????) 

это решается перехватом сообщения WM_NCACTIVATE у главного окна. wParam = FALSE, если окно деактивируется и TRUE при активации. Активность можно сохранить перехватив момент деактивации, в этом случае lParam будет указывать на дескриптор окна, которое собирается быть активировано. Нужно просто сравнить этот дескриптор с вашим попап-окном(новоявленным меню) и если они совпадают, то вернуть TRUE, не вызывая DefWindowProc и т.п.

Автор: Earnest 3.10.2006, 18:55
Цитата(Nastya @  3.10.2006,  12:38 Найти цитируемый пост)
такой код: эффекта не дает :

Естественно, я ведь писала, что нужна поддержка со стороны главного окна. А WinAPI вообще про этот стиль не знает.
Ну вот GremlinProg написал, как. Т.е. если не MFC, то можно сделать что-то подобное.


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