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

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

Ответить
Настройки темы
C/C++ - Button со стилем BS_OWNERDRAW - класс для быстрого создания кнопки

Аватара для crashtuak

Старожил


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


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

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


Изменения
Автор: crashtuak
Дата: 28-03-2010
Была у меня проблема создания кнопки BS_OWNERDRAW. Впринципе проблему я решил, создав для себя удобный класс. Для загрузки и отрисовки картинок использовал стороннюю либу CxImage.
Код класса
Код: Выделить весь код
class PNG_Button
{
public:
	int Create(int x_pos,int y_pos,int x_sz,int y_sz,HWND parent,
		LPCSTR normalimage,
		LPCSTR lightedimage,
		LPCSTR pushedimage)
	{
		x_position=x_pos, y_position=y_pos, x_size=x_sz, y_size=y_sz, B_Parent=parent;
		Handle=CreateWindowEx(0,"Button",NULL,WS_CHILD | WS_VISIBLE | BS_OWNERDRAW, x_position, y_position, x_size,y_size,B_Parent,NULL,NULL,NULL);
		SetWindowLong(Handle, GWL_USERDATA, (LONG)this);
		oldbtnproc=(WNDPROC)SetWindowLong(Handle, GWL_WNDPROC, (LONG)BNG_Button_Procedure);
		bMouseTrack=false;
		
		btnrect.left=x_pos,btnrect.top=y_pos,btnrect.right=x_pos+x_sz,btnrect.bottom=y_pos+y_sz;
		
		//"E:\\TMP2\\btn_normal.png"
		image[0].Load(normalimage,CXIMAGE_FORMAT_PNG);
		image[1].Load(lightedimage,CXIMAGE_FORMAT_PNG);
		image[2].Load(pushedimage,CXIMAGE_FORMAT_PNG);

		draw=0;
		if(Handle!=0)
		{
			//MessageBox(NULL,"Вызван конструктор PNG_Button","Диагностика",MB_OK);
			return 0;
		}
		else
		{
			MessageBox(NULL,"Ошибка при создании\nкнопки.","Диагностика",MB_OK);
			return -1;
		}
		
	}
	
	int Draw()
	{
		HDC hdc;
		PAINTSTRUCT  ps;
		hdc = BeginPaint(Handle, &ps);
		image[draw].Draw(hdc,0,0,-1,-1,0,false);
		EndPaint(Handle, &ps);
		return 0;
	}
	
	static LRESULT CALLBACK BNG_Button_Procedure ( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam )
	{
		PNG_Button* pThis = (PNG_Button*)GetWindowLong(hwnd, GWL_USERDATA);
		switch ( msg )
		{ 
		case WM_LBUTTONDOWN:
			//MessageBox(NULL, "Pushed", "Pushed", MB_ICONHAND);
			pThis->draw=2;
			InvalidateRect(pThis->B_Parent,&pThis->btnrect,false);
			return 0;
		case WM_MOUSELEAVE:
			pThis->bMouseTrack = false;
			//MessageBox(NULL,"Leaved","Leaved",MB_OK);
			pThis->draw=0;
			InvalidateRect(pThis->B_Parent,&pThis->btnrect,false);
			return 0;
		case WM_LBUTTONUP:
			pThis->draw=1;
			InvalidateRect(pThis->B_Parent,&pThis->btnrect,false);
			return 0;
		case WM_MOUSEMOVE:
			if(pThis->bMouseTrack==false)
			{
				pThis->TrackMouse(pThis->Handle);
				pThis->bMouseTrack = true;
				pThis->draw=1;
			    InvalidateRect(pThis->B_Parent,&pThis->btnrect,false);
			}
			return 0;
		}
		return CallWindowProc(pThis->oldbtnproc, hwnd, msg, wParam, lParam);
	}
private:
	int draw;
	CxImage image[3];
	RECT btnrect;
	WNDPROC oldbtnproc;
	HWND Handle;
	HWND B_Parent;
	int x_position;
	int y_position;
	int x_size;
	int y_size;
	BOOL bMouseTrack;
	BOOL TrackMouse(HWND i_hwnd)
	{
		TRACKMOUSEEVENT treMouse;
		treMouse.cbSize=sizeof(TRACKMOUSEEVENT);
		treMouse.hwndTrack=i_hwnd;
		treMouse.dwFlags=TME_LEAVE ;
		treMouse.dwHoverTime=1;
		if (!TrackMouseEvent(&treMouse))
		{
			MessageBox(0, "::TrackMouseEvent failed!", "Error", MB_ICONHAND);
			return false;
		}
		else
		{
		return true;
		}
	}
};

Использование класса
Делаем глобальными нужное число екземпляров класса PNG_Button pngbtn1, pngbtn2;, Далее код для создания самих кнопок:
Код: Выделить весь код
	pngbtn1.Create(100,100,31,31,hWnd,
		"E:\\TMP2\\btn_normal.png",
		"E:\\TMP2\\btn_lighted.png",
		"E:\\TMP2\\btn_pushed.png");
	pngbtn2.Create(200,200,75,23,hWnd,
		"E:\\TMP2\\Новая папка\\400.bmpx",
		"E:\\TMP2\\Новая папка\\402.bmpx",
		"E:\\TMP2\\Новая папка\\401.bmpx");
При обработке события WM_PAINT окна, в котором находятся наши кнопки, надо выполнить функции:
Код: Выделить весь код
                pngbtn1.Draw();
		pngbtn2.Draw();

Цитата pva:
этому коду характерен баг »
У моей кнопке такого бага нету, потому что при WM_MOUSELEAVE картинка по любому сменяется на отжатую.
ПС: это черновая версия класса для кнопки, кому будет интересно, можно будет доработать.

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


Отправлено: 19:29, 29-01-2010

 
pva pva вне форума

Аватара для pva

Ветеран


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

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


Вообще-то BUTTON со стилем BS_OWNERDRAW должна сама вызывать WM_DRAWITEM когда необходимо. Причём обработчик WM_DRAWITEM перерисовывает кнопку полностью (сама кнопка ничего не рисует).
______________________________________________

если будешь ваять кнопку руками:
На событие нажатия ставим обработчик:
Код: Выделить весь код
case WM_LBUTONDOWN:
case WM_LBUTONUP:
  myButtonPushed = (message==WM_LBUTONDOWN); // запомнили, что надо рисовать нажатую
  HDC dc = GetDC(buttonHWND); // взяли DC всего окна
  myButtonPaint(dc); // перерисовали
  ReleaseDC(buttonHWND, dc); // разрушили dc
  if (message==WM_LBUTONUP) myButtonOnClick(); // реагируем на событие
или
Код: Выделить весь код
case WM_LBUTONDOWN:
case WM_LBUTONUP:
  myButtonPushed = (message==WM_LBUTONDOWN);
  InvalidateRect(buttonHWND, 0, 0); // отрисуем потом
  if (message==WM_LBUTONUP) myButtonOnClick(); // реагируем на событие
  // если myButtonOnClick() выполняется долго, кнопка долго не будет перерисовываться (выглядеть нажатой)
этому коду характерен баг: если нажать кнопку и стащить указатель с кнопки, то она не отожмётся. Чтобы решить эту проблему, нужно захватить мышь:
Код: Выделить весь код
case WM_CAPTURECHANGED: // кто-то вызвал SetCapture или ReleaseCapture
  myButtonPushed = false;
  InvalidateRect(buttonHWND, 0, 0); // отрисуем потом
  break;

case WM_LBUTONDOWN:
  myButtonPushed = true;
  SetCapture(buttonHWND);
  InvalidateRect(buttonHWND, 0, 0); // отрисуем потом
  break;

case WM_LBUTONUP:
  ReleaseCapture(buttonHWND); // вызовет WM_CAPTURECHANGED
  myButtonOnClick(); // реагируем на событие
  break;

case WM_PAINT:
  // myButtonPushed = (GetCapture()==buttonHWND);
  ...
Это сообщение посчитали полезным следующие участники:

Отправлено: 10:14, 30-01-2010 | #2



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

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


Аватара для crashtuak

Старожил


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

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


Доделал класс для создания BS_OWNERDRAW кнопки, смотрим шапку темы.

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


Отправлено: 08:54, 28-03-2010 | #3

pva pva вне форума

Аватара для pva

Ветеран


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

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


crashtuak, ты по ходу дела не понял, как работает BS_OWNERDRAW. Саму кнопку трогать не надо, надо дописать к тому, кто её держит обработку сообщения WM_DRAWITEM и WM_MEASUREITEM. Чтобы посчитать свой размер, кнопка шлёт хозяину сообщение WM_MEASUREITEM с параметром MEASUREITEMSTRUCT, чтобы отрисоваться - сообщение WM_DRAWITEM параметром DRAWITEMSTRUCT. Всё остальное - делает сама.
Смысл в том, что у родителя есть какие-то детальки, которые он умеет рисовать и измерять. А дальше их можно запихать в BUTTON, LISTBOX, COMBOBOX и MENU. Везде будет выглядеть красиво, кроме кнопки. У ней автоматически не отрисуюется кнопочная часть.
Борландовские библиотеки субклассят все контролы, а обработку WM_*ITEM перенаправляют тому, кто его прислал (CM_*ITEM = 3000 + WM_*ITEM), в дальнейшем обёртка над кнопкой всё и отрисовывает.
Это сообщение посчитали полезным следующие участники:

Отправлено: 15:24, 28-03-2010 | #4


Аватара для crashtuak

Старожил


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

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


pva, та я понял что я не понял, каким образом работает данная фича. Я просто решил не углублятся, и пошел по пути наименшего сопротивления

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


Отправлено: 22:28, 28-03-2010 | #5

pva pva вне форума

Аватара для pva

Ветеран


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

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


тогда предлагаю ещё меньшее сопротивление: заранее загрузить PNG и отрисовать в HBITMAP, на форме сделать кнопку со стилем BS_BITMAP.

Отправлено: 13:19, 29-03-2010 | #6


Аватара для crashtuak

Старожил


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

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


pva, а полупрозрачность картинки в таком случае сохраниться?

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


Отправлено: 13:36, 29-03-2010 | #7

pva pva вне форума

Аватара для pva

Ветеран


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

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


не сохранится, то и её можно отрисовать (берём фон кнопки...) А вот с красивым стилем будет облом. У меня, например, ХРюшка сразу рисует кнопку старым стилем, как только битмап ей назначишь

Отправлено: 19:34, 29-03-2010 | #8


Аватара для crashtuak

Старожил


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

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


pva, а мне надо, что б у кнопки вообще небыло фона. Ну, будет время, буду чтото думать ёще. Хотя, и так работает, и довольно быстро (на слабом ноуте проверял).

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


Отправлено: 21:08, 29-03-2010 | #9



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

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

Похожие темы
Название темы Автор Информация о форуме Ответов Последнее сообщение
Red Button 3.9 OSZone Software Новости программного обеспечения 0 21-12-2009 11:30
Службы - Не работает S Button на Sony Vaio. vadja Microsoft Windows 2000/XP 0 31-12-2008 19:05
Проблема со стилем оформления после патча uxtheme.dll Vitasphere Microsoft Windows 2000/XP 8 16-12-2006 06:34
[решено] Помогите со стилем!!! Scorpion666 Вебмастеру 2 26-06-2006 14:03
Button,caption Roman Go Программирование и базы данных 1 15-01-2003 14:12




 
Переход