![]() |
|
Модераторы: feodorv, GremlinProg, xvr, Fixin |
![]()
|
|
| uvsoft |
|
|||
![]() Шустрый ![]() Профиль Группа: Участник Сообщений: 123 Регистрация: 4.2.2003 Репутация: нет Всего: нет |
hi,
тут такое дело, хочу зарегистрировать класс окна пишу что-т вроде:
где MainWindowProc: LRESULT CALLBACK MainWindowProc(HWND, UINT, WPARAM, LPARAM); компилирую, все в порядке.... НО, если все это оформить в виде класса, т.е. занести функцию MainWindowProc в класс, то компилятор начинает ругаться: f:\...\file.cpp(32): error C2440: '=' : cannot convert from 'LRESULT (__stdcall MyNameSpace::CMyClass::* )(HWND,UINT,WPARAM,LPARAM)' to 'WNDPROC' тут есть какая тонкость в использовании MainWindowProc? спасибо --------------------
Старый глюк лучше новых двух. |
|||
|
||||
| srd |
|
|||
![]() Нереварин ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 951 Регистрация: 30.8.2003 Где: Владивосток Репутация: 4 Всего: 49 |
Оконная процедура должна быть глобальной функцией. Если она член класса, то должна быть статической.
-------------------- Не смей читать мою подпись!!! |
|||
|
||||
| uvsoft |
|
|||
![]() Шустрый ![]() Профиль Группа: Участник Сообщений: 123 Регистрация: 4.2.2003 Репутация: нет Всего: нет |
я так понимаю и все остальные функции обработки сообщений (OnSize, OnCommand) тож должны быть статическими, да? а от сюда следует, что и все данные, с которыми они работают в классе должны быть статическими, и тут тогда получается что уже никак нельзя использовать два экземпляра класса для разных нужд, так? --------------------
Старый глюк лучше новых двух. |
|||
|
||||
| srd |
|
|||
![]() Нереварин ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 951 Регистрация: 30.8.2003 Где: Владивосток Репутация: 4 Всего: 49 |
Вовсе нет. Оконная процедура должна быть статической, потому что вызывается она самой операционной системой, а ОСь использует именно прототип LRESULT (CALLBACK*)(HWND,UINT,WPARAM,LPARAM). Функции-члены же имеют дополнительный параметр, с помощью которой в функцию передаётся указатель this на экземпляр класса. Отсюда и проблемы. Если ты найдёшь способ сохранить связь между дескриптором окна и указателем на экземпляр класса и будешь восстанавливать этот указатель внутри оконной процедуры (существует несколько возможных вариантов), то обработчики сообщений могут быть и обычными функциями-членами. -------------------- Не смей читать мою подпись!!! |
|||
|
||||
| srd |
|
|||
![]() Нереварин ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 951 Регистрация: 30.8.2003 Где: Владивосток Репутация: 4 Всего: 49 |
Простая иллюстрация к вышесказанному:
-------------------- Не смей читать мою подпись!!! |
|||
|
||||
| jonie |
|
|||
|
Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 5613 Регистрация: 21.8.2005 Где: Владимир Репутация: 7 Всего: 118 |
static это, конечно хорошо... но уж больно хотелось бы получить доступ к членам (в т.ч. объявленных как private) созданного экземпляра класса.....
В общем и целом, я эту проблему решил так:
код написал только что и потому прошу не бить ногами)) комментарии приветсвуются! Это сообщение отредактировал(а) jonie - 31.7.2006, 15:41 -------------------- Что-то не поняли? -> Напейтесь до зеленых человечков... эта сверхцивилизация Вам поможет... |
|||
|
||||
| SeregaLBN |
|
||||||||||||||
![]() Бывалый ![]() Профиль Группа: Участник Сообщений: 178 Регистрация: 3.10.2003 Где: Киев Репутация: нет Всего: нет |
Есть несколько таких методов: 1. Самый лучшый, имхо, - реализация как в WTL, так называеме thunk'и. Почитать можно здесь - http://www.rsdn.ru/article/wtl/wtl-1.xml?print#EQZAE Опишу двумя словами. С помощью небольшой асемблерной вставочки, в стеке вызова параметров оконной процедуры заменяется параметр HWND на указатель на свой класс окна, т.е. на this. Это самый сложный метод. Для его понимания надо будет дополнительно лезть в ИНет или смотреть исходники WTL. Остальные попроще: 2. При создании С++ обьекта окна ассоциируешь этот обьект (this) с самим окном (HWND) c помощью ф-ции
Ну и выбирается этот this в своей статической WNDPROC из HWND:
И имея этот This можешь вызывать все свои методы класcа и приватные переменные. Пример моего оконного класса диалога, реализующий этот метод, приведен ниже. 3. Реализация приведённая srd. Здесь также this связывается с HWND, но уже через др. API ф-цию - именнованное свойство (property) - ф-ция SetProp. Ну и выбирается аналогично - внутри своей WNDPROC, через ф-цию GetProp. Насколько я знаю, это самый медленный способ. 4. При регистрации своего оконного класса можно указать дополнительное число байтов (extra bytes - WNDCLASSEX::cbClsExtra) которые сама система будет выделять при создании окна. Идея закл. в том, что нужно в качестве этого размера указать размер указателя на свой оконный С++ класс. И далее, при создании системой окна, сохранить в этих дополнительных данный свой this с помощью вызова:
Доставать свой this, опять аналогично - из своей статической ф-ции WNDPROC с пмощь вызова:
Как видно этот метод почти аналогичен методу №2 5. В MFC, вроде бы, реализовано так. Есть глобальная переменная, аналогичная std::map<HWND, CWindow*>. Ну и тоже самое, когда окно создаётся - указатель на С++ обьект сохраняется в глоб. переменной. И выбирается внутри WNDPROC... Более подробно некорые эти методы описаны в http://www.catch22.net/tuts/custctrl.asp в разделе 'Associating a structure with the custom control' Пример реализации немодально окна About на чистом API:
Обрати внимание, что для диалогов я делаю ассоциацию this с HWND при сообщении WM_INITDIALOG. А в примере srd - при сообщении WM_NCCREATE. Так правильнее... |
||||||||||||||
|
|||||||||||||||
| SeregaLBN |
|
|||
![]() Бывалый ![]() Профиль Группа: Участник Сообщений: 178 Регистрация: 3.10.2003 Где: Киев Репутация: нет Всего: нет |
Ах да... Тема ж называется "RegisterClassEx, Параметр WNDPROC lpfnWndProc"
Вот в догонку класс не диалога (parent окно в виде курсора) (есть вызов RegisterClassEx):
Здесь реализован ещё один метод, уже 6-ой При создании окна ф-цией CreateWindowEx в последнем параметре модно передать свои данные. И в них я и передаю this. Эти данные вернуться мне же, в ф-цию WNDPROC при приходе сообщения WM_CREATE, при котором я достаю свой this и уже сохраняю его при помощи ::SetWindowLong(m_hWnd, GWL_USERDATA, (LONG)this); для того чтобы в дальнейшем (при приходе др. оконных сообщений) выбирать с пощью GetWindoLong, опять же, свой this. |
|||
|
||||
| GremlinProg |
|
|||
|
Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Комодератор Сообщений: 2706 Регистрация: 9.8.2005 Где: Тюмень Репутация: 99 Всего: 106 |
Нужно учесть только один момент: WM_NCCREATE - это не первое сообщение, которе приходит в окно. Первым оно будет только если это дочернее окно и оно не имеет стиля WS_THICKFRAME. Поэтому, для надежности, желательно регистрировать любое такое окно с двумя процедурами окна:
1 - процедура инициализации, которая ассоциирует указатель на объект окна с самим окном и установит процедуру окна на ворую, основную; 2 - основная процедура, выделяет ваш объект окна и вызывает его встроенную функцию по обработке очереди сообщений. -------------------- "Гений всегда разумнее, чем умнее. Ум — это машина, разум — водитель этой машины." |
|||
|
||||
![]()
|
| Правила форума "C/C++: Системное программирование и WinAPI" | |
|
|
На данный раздел распространяются Правила форума и Правила раздела С++:Общие вопросы . Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Chipset, Step, Fixin, GremlinProg, xvr. feodorv. |
| 0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей) | |
| 0 Пользователей: | |
| « Предыдущая тема | C/C++: Системное программирование и WinAPI | Следующая тема » |
|
|
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности Powered by Invision Power Board(R) 1.3 © 2003 IPS, Inc. |