| Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате |
| Форум программистов > C/C++: Системное программирование и WinAPI > Вопрос про субклассинг |
| Автор: yngwie19 20.5.2009, 00:06 | ||
| Здравствуйте! В книге Петзольда описывается субклассинг вот на каком примере: Есть главное окно, в нем создано дочернее окно с классом "scrollbar". У каждого окна есть оконная процедура (я так полагаю что и у окна класса scrollbar тоже). В книге описывается механизм замены оконной процедуры класса scrollbar на свою, для этого делают слежующее:
вот как-то так. У меня вопрос вот в чем, правильно ли Я понимаю, что без субклассинга окно scrollbar обрабатывается в оконной процедуре родительского окна через сообщение WM_VSROLL или WM_HSCROLL соответсвенно, т.е по умолчанию заложего так. А если мы меняем адрес этой процедуры на свою, то она обрабатывается той оконной процедурой, которую мы для нее описали. А если необходимо чтобы какие-то сообщения посылаемые этому окну (scrollbar- у ) обрабатывались процедурой "по-умолчанию", то мы вызываем CallWindowProc() и передаем ей все необходимые параметры. Правильно ли Я понял суть? |
| Автор: yngwie19 20.5.2009, 07:20 |
| mes, ну да точно совсем забыл, ну а вообще правильно ли Я все понял? меня вот что интересует, любое дочернее окно по умолчанию обрабатывается оконной процедурой окна родителя так? а если этот контрол у нас создан в диалоговом окне, то тут можно также менять адрес процедуры на другой? |
| Автор: Cheloveck 20.5.2009, 07:36 | ||
нет, не так. У любого окна, дочернего или главного... есть своя процедура обработки. Разница лишь в том, что дочерние окна извещают своих родителей о своих изменениях и статусах... Добавлено через 2 минуты и 52 секунды Более правильно запомнить результат функции SetWindowLong - она вернёт предыдущую процедуру. |
| Автор: Earnest 20.5.2009, 07:40 | ||
Совсем нет. У каждого окна своя процедура. В родительское окно дочернее посылает различные уведомления (такие как WM_COMMAND, WM_NOTIFY, WM_DRAWITEM, ..., скролл-бары посылают WM_SCROLL). А обрабатываемых сообщений сотни. Кроме того, скролл-бары не обязательно являются окнами. Иногда - это просто часть неклиентской области. Например у окон со стилем WS_SCROLL. |
| Автор: yngwie19 20.5.2009, 08:33 | ||
| Earnest, ну т.е у всех окон своя оконная процедура, которая по умолчанию описана так (например для ScrollBar - a ):
Правильно Я понял, т.е она ничего не делает кроме как вызывает оконную функцию окна родителя и передает ей параметры? |
| Автор: mes 20.5.2009, 09:15 | ||||||
точно, подзабыл.. 100 лет не программил на WinApi. нет, процедура родителя (а в WinApi этому званию соответствует окно, на котором создали дочернее) не вызывается.
Т.е родитель "насладжается" лишь получаемыми сообщениями и никакого другого контакта. Каждое окно вызывает оконную процедуру предка по наследованию т.е есть главная процедура всех окон DefWindowProc () от нее (не важна на прямую или через посредников) отнаследованы: DefDialogWindowProc - которую в конечном итоге должен вызвать контрол желающий быть диалогом DefScrollBarProc () - которую вызывают скролы, DefTextCtrlProc () - .. и так далее. (названия даны условны, и с истинами именами могут не совпадать) При создании нового типа окна, в оконной процедуре мы вызываем DefWindowProc, a при субклассировании фактически создается стек окон процедур, обеспечивающий наследованное поведение, условно такоe : MyWindowProc -> SavedWindowProc () -> ScrolledWindowProcEx () -> ScrolledWindowProc() -> DefScrollWindowProc ();
Разницы нет кто впоследствии будет родителем, важно от кого отнаследовано. P.S. в winApi получается игра слов, упомяннутая выше, поэтому еще раз уточню. грубо: предок при субклассировании - окно (его процедура), от которого мы перенимаем поведение - наследуемся. родитель - окно на котором мы расположим дочернее. эти два понятия не смотря на родственное созвучие и в некоторых случаях могут называться одним и тем же словом, но обозначают совершенно разные (по отношению к рассматриваемому) окна. |
| Автор: yngwie19 20.5.2009, 10:36 |
| mes, да что-то не очень понятно, запутано очень или надо кертинку рисовать. Можно где-нибудь на русском про это почитать? |
| Автор: GremlinProg 20.5.2009, 11:11 | ||||
все будет гораздо проще, если представить оконную процедуру как полиморфное перекрытие класса:
тогда субклассинг - это наследование нового класса CMyScrollBar от CScrollBar, с перекрытием главного метода класса:
я уже приводил похожий пример, return CScrollBar::WndProc(...) - равнозначно CallWindowProc('адрес процедуры окна предка',...) слово родитель тут совсем не к месту, это предок, т.е. класс окна от которого производится субклассинг здесь можно вполне легально использовать термины ООП: инкапсуляция, наследование, полиморфизм хотя полновестное значение тут имеет только термин полиморфизм, т.е. перекрытие WndProc в потомке (CMyScrollBar) чтобы было еще и наследование, субклассинг должен осуществляться еще при регистрации класса окна, т.е. до создания окна (но такой способ перекрытия процедуры окна обычно так и называют: наследование, т.е., помимо доступа к процедуре предка, мы имеем инкапсулированные данные окна и/или класса предка) yngwie19, если понимаешь смысл основных инструментов ООП (инкапсуляция, наследование, полиморфизм), то и с субклассингом все должно быть понятно если нет, то можешь найти достаточно информации на эту тему в других разделах C/C++ |