| Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате |
| Форум программистов > C/C++: Системное программирование и WinAPI > Свой класс CWindow, субклассирование |
| Автор: Alca 29.7.2009, 15:54 | ||||||
Есть класс:
От него наследую класс CXFrame, потом CXMyFrame. Если создаю окно с помощью ::CreateWindowEx:
то все нормально работает, а если из ресурсов:
то окно содается, но не реагирует ни на какие действия (не идет обработка сообщений), только можно перемещять мышкой. Где-то косяк в методе s_BaseWndProc... Если чего-то в коде не хватает - выложу. |
| Автор: GremlinProg 29.7.2009, 17:46 | ||||
по-видимому, проблема в самом подходе к объединению функционала диалога и обычного окна в одном сишном классе: если свойство Class в шаблоне указывает на нормальный класс окна, то CreateDialog создает окно уже не класса 32770, а именно этого класса, указанного в свойстве Class ) короче говоря, основная ошибка в функции bIsDialog, она никогда не вернет TRUE вот с этого момента и разбирай функционал дальше: значит для диалога не будет вызвана процедура окна его предка, отсюда - он будет работать как простое окно, ни какой инициализации компонентов из ресурсов оно уже не сделает и т.д. т.е. это не синтаксическая ошибка, а логическая, ты создал окно диалогового класса, но не даешь этому классу с ним работать, полностью перекрыл функционал предка, точнее даже исключил предка из цепочки наследования (т.к. DefWindowProc все же вызываешь) мы ведь уже обсуждали проблему идентификации диалога при суперклассинге, изнутри твоего класса эту проблему решить можно, если сохранять процедуру класса-предка в самом объекте, а в последствии, изучать ее: если она равна DefDlgProc, то это диалог, иначе - нет, конечно, это верно только при условии, что цепочка предков состоит только из одного класса (судя по коду, этого более чем достаточно) т.е. заведи в сишном классе поле
а заполняй его только в методах: bCreateEx, bCreate и bCreateRes для всех методов инициируй его в DefWindowProc, кроме bCreateRes, тут ставь DefDlgProc тогда в s_BaseWndProc вместо компаратора bIsDialog ставь просто вызов
|
| Автор: Alca 29.7.2009, 20:57 | ||
Отладчиком заходил в TRUE. Добавлено через 5 минут и 48 секунд |
| Автор: Alca 29.7.2009, 22:36 | ||
|
| Автор: Alca 30.7.2009, 08:56 | ||||||
Спасибо.
|
| Автор: Alca 30.7.2009, 09:20 | ||
| Мне хотя бы полноценный примерчик субклассирования с ::CreateDialog (без ::CreateWindowEx) Добавлено через 12 минут и 3 секунды
Теперь вообще не попадаю в s_BaseWndProc. |
| Автор: Alca 30.7.2009, 11:04 |
| |
| Автор: GremlinProg 30.7.2009, 13:35 | ||||||
| хорошо, привожу пример суперклассинга для диалога, а чтобы ни кого особенно не напрягал объем кода, объясняю: я просто создал обычный проект Win32 Project, так что по большей части, это чуть-чуть подправленный стандартный Win32-шаблон
файл ресурсов:
Добавлено через 1 минуту и 16 секунд да, совсем забыл, файл Resource.h:
|
| Автор: Alca 30.7.2009, 14:24 |
| Попробую чего-то наваять... |
| Автор: Alca 30.7.2009, 16:10 | ||
Что-то нихрена не получается:
|
| Автор: GremlinProg 30.7.2009, 16:25 |
| так, в приложении пример того, что получилось |
| Автор: GremlinProg 30.7.2009, 16:30 |
| а теперь в приложении сам проект |
| Автор: GremlinProg 30.7.2009, 16:37 |
Alca, загляни в проект, посмотри на его логику, разбери код, повторяю, 95-97% от того, что у меня написано - стандартный проект win32 CreateWindow заменен на CreateDialog + небольшие изменения/дополнения в классе окна, процедуре окна и цикле сообщений |
| Автор: Alca 30.7.2009, 16:40 | ||
Спасибо. У меня этот проект работает. А вот код, который был чуть выше - нет Где я накосячил? |
| Автор: GremlinProg 30.7.2009, 17:44 |
во первых, не указана процедура окна, не надо так радикально расставлять NULL'ы ), я же писал только о CreateDialog без _m_WndClass.lpfnWndProc класс-потомок просто не будет зарегистрирован во вторых, непонятно, какое имя у этого класса, предполагаю "", судя по тому, как _m_sClassName инициализируется в конструкторе ну и в третьих, т.к. я не вижу твоего шаблона, для суперклассинга диалога требуется четкое соответствие свойства CLASS в шаблоне диалога и имени класса _m_sClassName, т.е., судя по всему, у тебя эти значения должны быть равны и не должны быть пустыми в моем примере, имя класса "Мой диалоговый класс", а оконная процедура для диалога - WndProc |
| Автор: Alca 30.7.2009, 20:44 | ||||||||||||||
А данная структура должна быть членом класса или не обязательно?
Добавлено @ 20:52
исправил:
Инициализировано:
Добавлено @ 20:54
Добавлено @ 20:59
Самое интересное, что в эту функцию s_BaseWndProc я не попадаю на брейкпоинты, т,е, ваще сюда "не заходиться" |
| Автор: GremlinProg 30.7.2009, 22:17 | ||
а свойство CLASS в шаблоне диалога?
Добавлено через 2 минуты и 28 секунд нет, не обязательно |
| Автор: Alca 30.7.2009, 22:47 | ||||||||
Исправил:
Добавлено @ 22:48
Добавлено через 14 минут и 36 секунд Какое сообщение ловить WM_INITDIALOG или WM_NCCREATE?
|
| Автор: Alca 30.7.2009, 23:06 |
| Раньше (до исправлений) у меня сообщения заходили в метку WM_INITDIALOG, а теперь в WM_NCCREATE. Кажись что-то продвигается. |
| Автор: GremlinProg 31.7.2009, 08:18 | ||||
да, теперь работает процедура окна, тут все сообщения будут приходить
там параметра-то нет, используй CreateDialogIndirectParam, и в последний параметр передай this вообще, это нужно ловить на WM_INITDIALOG, тогда этот параметр придет в lParam если после WM_NCCREATE сразу приходит WM_DESTROY, значит некорректно обрабатываешь WM_NCCREATE, посмотри s_BaseWndProc, она должна передавать сообщение дальше, по цепочке:
|
| Автор: Alca 31.7.2009, 10:08 | ||
|
| Автор: GremlinProg 31.7.2009, 13:47 | ||
Alca, чтобы особенно не заморачиваться, я предлагаю тебе сделать так:
объясняю: lpInitObject - это статический указатель, который будет хранить объект окна в момент создания окна InitWndProc - это первичная процедура окна, задача которой - принять любое первое сообщение от окна, инициализировать GWL_USERDATA и переставить процедуру окна на BaseProc BaseProc - вторичная процедура окна, эта процедура независимо от стилей окна всегда имеет доступ к корректному GWL_USERDATA, поэтому она просто извлекает этот объект и передает управление его методу WndProc WndProc - это уже не статический метод, в ее обязанности входит управление цепочкой оконных классов, она вызывает CallWindowProc, switch я поставил просто для примера, если тебе надо в этом классе перехватывать какие-нибудь сообщения, а вообще, это можно делать уже в потомках CreateFromResource - делает то же самое, что и у тебя, за исключением того, что перед вызовом CreateDialog устанавливает lpInitObject теперь, от класса XWindow наследуй свои классы, можешь перекрывать метод WndProc в потомках и делать что хошь Добавлено через 3 минуты и 28 секунд делать что хошь с диалоговым окном в парадигме ООП |