|
Компьютерный форум OSzone.net » Программирование, базы данных и автоматизация действий » Программирование и базы данных » C/C++ - Как правильно "запихнуть" оконную процедуру в самодельный класс? |
|
C/C++ - Как правильно "запихнуть" оконную процедуру в самодельный класс?
|
![]() Старожил Сообщения: 467 |
Как правильно "запихнуть" оконную процедуру в самодельный класс, и как потом правильно прикрутить ту процедуру к нужному окну(в данном случае-к кнопке)? Вот собственно код класса, прошу строго не судить, мой первый класс в жизни
![]() class PNG_Button { public: HWND bt_hwnd; HWND bt_parent_hwnd; int x_position; int y_position; int x_size; int y_size; LPCSTR normal_image; LPCSTR focused_image; LPCSTR pushed_image; LPCSTR draw_image; BOOL g_bMouseTrack; WNDPROC btnOld; //вот она-процедура LRESULT CALLBACK ButtonSubclassProc ( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam ) { switch ( msg ) { case WM_MOUSELEAVE: { g_bMouseTrack = FALSE; draw_image=normal_image; InvalidateRect(bt_parent_hwnd,0,true); } return 0; case WM_MOUSEHOVER: { draw_image=focused_image; InvalidateRect(bt_parent_hwnd,0,true); } return 0; case WM_LBUTTONDOWN: { draw_image=pushed_image; InvalidateRect(bt_parent_hwnd,0,true); } return 0; case WM_LBUTTONUP: { draw_image=focused_image; InvalidateRect(bt_parent_hwnd,0,true); } return 0; case WM_MOUSEMOVE: if(g_bMouseTrack==FALSE) { TrackMouse(bt_hwnd); g_bMouseTrack = TRUE; } return 0; } return CallWindowProc(btnOld, hwnd, msg, wParam, lParam); } //конец оконной процедуры //конструктор PNG_Button(LPCSTR bt_text,int x_pos,int y_pos,int x_sz,int y_sz, HWND bt_parent, LPCSTR n_image, LPCSTR f_image, LPCSTR p_image) { x_position=x_pos, y_position=y_pos, x_size=x_sz ,y_size=y_sz; draw_image=n_image, normal_image=n_image, focused_image=f_image, pushed_image=p_image; bt_parent_hwnd=bt_parent; g_bMouseTrack = FALSE; bt_hwnd=CreateWindowEx(NULL,"Button",bt_text,WS_CHILD | WS_VISIBLE | BS_OWNERDRAW, x_pos, y_pos, x_sz, y_sz,bt_parent, NULL,NULL,NULL); //на слудующую строчку очень сильно ругается компилятор btnOld = (WNDPROC)SetWindowLong(bt_hwnd, GWL_WNDPROC, (LONG)ButtonSubclassProc); TrackMouse(bt_hwnd); return 1; } //конец конструктора HWND Get_BT_HWND() { return bt_hwnd; } int DrawBTN() { HDC hdc; PAINTSTRUCT ps; hdc = BeginPaint(bt_hwnd, &ps); CxImage image; image.Load(draw_image,CXIMAGE_FORMAT_PNG); image.Draw(hdc,0,0,-1,-1,0,true); EndPaint(bt_hwnd, &ps); return 1; } }; |
|
------- Отправлено: 10:03, 14-02-2010 |
![]() Старожил Сообщения: 232
|
Профиль | Сайт | Отправить PM | Цитировать Цитата crashtuak:
static LRESULT CALLBACK ButtonSubclassProc ( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam ) Цитата crashtuak:
|
||
------- Отправлено: 17:42, 14-02-2010 | #2 |
Для отключения данного рекламного блока вам необходимо зарегистрироваться или войти с учетной записью социальной сети. Если же вы забыли свой пароль на форуме, то воспользуйтесь данной ссылкой для восстановления пароля. |
![]() Старожил Сообщения: 467
|
Профиль | Отправить PM | Цитировать ganselo, если делать статической, то пропадает доступ к членам класа. Можно подробнее про френд класа? Я вроде бы читал, что френдом класа может быть только другой клас...
|
------- Отправлено: 15:38, 19-02-2010 | #3 |
![]() Старожил Сообщения: 232
|
Профиль | Сайт | Отправить PM | Цитировать Вот простенький пример:
Что такое функция френд? Эта функция которая не является методом класса, но при этом имеет доступ к закрытым методам класса. |
------- Отправлено: 16:13, 19-02-2010 | #4 |
![]() Старожил Сообщения: 467
|
Профиль | Отправить PM | Цитировать ganselo, хм, интересно. Но так не пойдет, потому что функция-френд будет оконной процедурой, для которой добавить еще один аргумент для передачи указателя на наш клас не есть возможным. Надо как то запихнуть процедуру непосредствено в клас...
|
|
------- Отправлено: 16:41, 19-02-2010 | #5 |
![]() Ветеран Сообщения: 1180
|
Профиль | Отправить PM | Цитировать передача указателя решается несколькими путями:
1. через отображение HWND -> my_class* (самый защищённый) где-то хранится массив пар HWND, my_class*; функция WindowProc ищет в этом массиве свой HWND и для найденного(ных) указателя(лей) выполняет какой-нить виртуальный my_class::__wndproc 2. установка SetWindowLong (ИМХО самый экономный) для субклассинга лучше использовать GWL_USERDATA, хотя можно и зарегистировать новый класс на основании старого, только увеличить cbHwndExtra (или как его там), и хранить в нём нужную информацию 3. через свойства SetProps (ну тоже хороший способ) главное угадать такое название свойства, которое ещё никто не придумал. Прикрутить к этому названию свой указатель. Я замерял производительность - после 4 способа - самый быстрый, название свойства брал reinterpret_cast<wchar_t*>(1). 4. через сгенерированную в памяти функцию (самый быстроработающий) для каждого окна в памяти выделяется блок 32 байта, в который пишется машинный код Окну в качестве процедуры выставляется адрес этих 32 байт теперь у оконной процедуры вместо HWND будет указатель_на_класс. Этот способ используется во многих библиотеках. Недостаток: для правильной работы требуется правильно расположить в памяти. Например если эти 32 байта взять внутри my_class, оно может не работать (у меня не стало, а то же самое, во вновь выделенной памяти - на ура) |
Отправлено: 00:09, 23-02-2010 | #6 |
![]() |
Участник сейчас на форуме |
![]() |
Участник вне форума |
![]() |
Автор темы |
![]() |
Сообщение прикреплено |
| |||||
Название темы | Автор | Информация о форуме | Ответов | Последнее сообщение | |
Как правильно - "лицензионное" ПО или "лицензированное"? | Lutatovsky | Лицензирование продуктов Microsoft | 3 | 22-08-2011 19:36 | |
Как правильно "оторвать" процессор от радиатора | Rodrigo_F | Процесcоры | 28 | 15-09-2010 16:51 | |
7 / 2008 R2 - Как "запихнуть" аддон в Win 7 ? Спомощю чего??? | paravozik2009 | Автоматическая установка Windows 11 / 10 / 8 / 7 / Vista | 9 | 10-12-2009 13:24 | |
Интерфейс - [решено] Как удалить папку "Моя музыка","Мои Картинки", "Мое видео"? | verdix | Microsoft Windows 2000/XP | 3 | 03-10-2009 23:46 |
|