Имя пользователя:
Пароль:  
Помощь | Регистрация | Забыли пароль?  | Правила  

Компьютерный форум OSzone.net » Программирование, базы данных и автоматизация действий » Программирование и базы данных » C/C++ - Как правильно "запихнуть" оконную процедуру в самодельный класс?

Ответить
Настройки темы
C/C++ - Как правильно "запихнуть" оконную процедуру в самодельный класс?

Аватара для crashtuak

Старожил


Сообщения: 467
Благодарности: 25


Конфигурация

Профиль | Отправить PM | Цитировать


Как правильно "запихнуть" оконную процедуру в самодельный класс, и как потом правильно прикрутить ту процедуру к нужному окну(в данном случае-к кнопке)? Вот собственно код класса, прошу строго не судить, мой первый класс в жизни(который без оконной процедуры работает нормально):
Код: Выделить весь код
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

 

Аватара для ganselo

Старожил


Сообщения: 232
Благодарности: 90

Профиль | Сайт | Отправить PM | Цитировать


Цитата crashtuak:
Как правильно "запихнуть" оконную процедуру в самодельный класс »
Как вариант сделать её френдом класса. А можно попробовать сделать её статической:
Код: Выделить весь код
static LRESULT CALLBACK ButtonSubclassProc ( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam )
Цитата crashtuak:
и как потом правильно прикрутить ту процедуру к нужному окну »
В конструкторе например:
Код: Выделить весь код
PNG_Button()
{
      //не помню полей структуры btnOld, но примерно так
      btnOld.proc = ButtonSubclassProc; 
}

-------
К величайшему сожалению "история учит нас тому, что она ничему не учит".


Отправлено: 17:42, 14-02-2010 | #2



Для отключения данного рекламного блока вам необходимо зарегистрироваться или войти с учетной записью социальной сети.

Если же вы забыли свой пароль на форуме, то воспользуйтесь данной ссылкой для восстановления пароля.


Аватара для crashtuak

Старожил


Сообщения: 467
Благодарности: 25

Профиль | Отправить PM | Цитировать


ganselo, если делать статической, то пропадает доступ к членам класа. Можно подробнее про френд класа? Я вроде бы читал, что френдом класа может быть только другой клас...

-------
Мне надо не так много "Полезных сообщений", чтоб сровнять их количество с моими постами :).


Отправлено: 15:38, 19-02-2010 | #3


Аватара для ganselo

Старожил


Сообщения: 232
Благодарности: 90

Профиль | Сайт | Отправить PM | Цитировать


Вот простенький пример:
Код: Выделить весь код
class test
{
   public:
        testint _a, int _b) : a(_a), b(_b) {}
   private:
        int a, b;
   friend int summa(const test &t);
};

int summa(const test &t)
{
     return t->a + t->b;
}

int main()
{
    test t(10, 20);
    cout <<  summa(t);
    return 0;
}
Что такое функция френд? Эта функция которая не является методом класса, но при этом имеет доступ к закрытым методам класса.

-------
К величайшему сожалению "история учит нас тому, что она ничему не учит".

Это сообщение посчитали полезным следующие участники:

Отправлено: 16:13, 19-02-2010 | #4


Аватара для crashtuak

Старожил


Сообщения: 467
Благодарности: 25

Профиль | Отправить PM | Цитировать


ganselo, хм, интересно. Но так не пойдет, потому что функция-френд будет оконной процедурой, для которой добавить еще один аргумент для передачи указателя на наш клас не есть возможным. Надо как то запихнуть процедуру непосредствено в клас...

-------
Мне надо не так много "Полезных сообщений", чтоб сровнять их количество с моими постами :).


Отправлено: 16:41, 19-02-2010 | #5

pva pva вне форума

Аватара для pva

Ветеран


Сообщения: 1180
Благодарности: 279

Профиль | Отправить 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 байта, в который пишется машинный код
Код: Выделить весь код
mov eax, указатель_на_класс
mov[esp+4], eax
jmp WindowProc
nop
nop
nop
Окну в качестве процедуры выставляется адрес этих 32 байт
теперь у оконной процедуры вместо HWND будет указатель_на_класс. Этот способ используется во многих библиотеках. Недостаток: для правильной работы требуется правильно расположить в памяти. Например если эти 32 байта взять внутри my_class, оно может не работать (у меня не стало, а то же самое, во вновь выделенной памяти - на ура)
Это сообщение посчитали полезным следующие участники:

Отправлено: 00:09, 23-02-2010 | #6



Компьютерный форум OSzone.net » Программирование, базы данных и автоматизация действий » Программирование и базы данных » C/C++ - Как правильно "запихнуть" оконную процедуру в самодельный класс?

Участник сейчас на форуме Участник сейчас на форуме Участник вне форума Участник вне форума Автор темы Автор темы Шапка темы Сообщение прикреплено

Похожие темы
Название темы Автор Информация о форуме Ответов Последнее сообщение
Как правильно - "лицензионное" ПО или "лицензированное"? 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




 
Переход