C++/WinAPI Button + obrazek w tle - IMAGELIST,Button_SetImageList()

0

Witam... Mam problem z ustawieniem Imagelist dla buttona (chcialbym zeby przed kliknieciem wyswietlana byla 1 bitmapa, w trakcie trzymania przycisku inna i znowu po puszczeniu przycisku poprzednia). Wczytuje 2 bitmapy do IMAGELIST, robie niby wszystko jak w msdn pisze ale nijak nie widze bitmapy na buttonie...

CreateWindowEx(NULL, "BUTTON", "Polacz!", BS_BITMAP | WS_VISIBLE | WS_CHILD | WS_BORDER, 650, 40, 140, 30, hOkna, (HMENU)3, hThisInstance, NULL);

BUTTON_IMAGELIST bi;
HIMAGELIST lista=ImageList_Create(140,30,ILC_COLOR24,1,0);
	
HBITMAP obraz=(HBITMAP)LoadImage(0,"D:\\tlobtn.bmp",IMAGE_BITMAP,0,0,LR_LOADFROMFILE);
ImageList_Add(lista,obraz,NULL);

obraz=(HBITMAP)LoadImage(0,"D:\\tlobtn2.bmp",IMAGE_BITMAP,0,0,LR_LOADFROMFILE);
ImageList_Add(lista,obraz,NULL);

bi.himl = lista;

//SendMessage(GetDlgItem(hOkna, 3), BCM_SETIMAGELIST, NULL, (LPARAM)&lista);
Button_SetImageList(GetDlgItem(hOkna, 3),lista);
 

Prosze o jakas wskazowke... pozdro

PS. uzywalem wyszukiwarki, niestety wiekszosc tematow dotyczy ustawienia sztywno jednej bitmapy a mi chodzi zeby byl tez efekt klikniecia przycisku.

0

Nie lista tylko bi przesyłasz w SetImageList oraz NIGDY nie używaj liczb określających zasób, tylko stałych zdefionowanych.

Button_SetImageList(GetDlgItem(hOkna, IDC_KOLOROWY_BUTTON), &bi);

@Edit:
Aha, tak w ogóle to chyba źle korzystasz (no chyba, że tak chciałeś, a nie na pałę przepisałeś skądś) z tworzenia listy:
http://msdn.microsoft.com/en-us/library/bb761522(VS.85).aspx

0

Niestety nic to nie dalo... moze brakuje mi jakiegos stylu w buttonie?

HWND hbut=CreateWindowEx(NULL, "BUTTON", "Polacz!", BS_BITMAP | WS_VISIBLE | WS_CHILD | WS_BORDER, 650, 40, 140, 30, hOkna, (HMENU)3, hThisInstance, NULL);

Probowalem bez BS_BITMAP ale to samo ;/. Podpiac liste probowalem na 2 sposoby:

SendMessage(hbut, BCM_SETIMAGELIST, NULL, (LPARAM)&bi);
Button_SetImageList(hbut,&bi);

Moze ten kod powinien byc w obsludze jakiegos komunikatu? Bo wstawiam go normalnie po utworzeniu przycisku... Dzieki za zainteresownie ;)

@Edit
nie widze bledow w tworzeniu listy, poza przedostatnim parametrem ktory powinien wynosic 2 - poprawione ale ten sam efekt

0

Super... Myslalem ze Button_SetImageList to juz tylko formalnosc a tu false ;o. W WM_CREATE nie robie nic oprocz wczytania bitmapy na tlo glownego okna, mysle ze to nie moze wplywac na dzialanie Button_SetImageList. Tylko wlasnie, dlaczego nie dziala ;/? (getlasterror zwraca 0)

0

Ja już nie pamiętam jak to robiłem w WinAPI, ale chyba obsługiwałem zawsze najechanie myszką, przyciśnięcie buttona, disable buttona i standardową bitmapę. Jak jakieś zdarzenie następowało, to podmieniałem bitmapę. Poczytaj o tym :)
Co do WM_CREATE, to nie Ty nie tworzysz TAM swojego buttona? Jeśli nie, to gdzie w takim razie?

0

Ogolnie to napisalem klase okna - rejestruje klase okna towrze je i Od razu tworze kontrolki - pozniej pokazuje okno. A co do Twojego rozwiazania fakt, byloby ok ale troche "naokoło". Jezeli nic nie wydumam/y to zrobie tak jak piszesz.

edit
Wymiekam... nie mam pojecia czemu to nie dziala, latam po stronach i jeszcze nic nie znalazlem ;/ aktualnie kod wyglada tak:

 
CreateWindowEx(NULL, "BUTTON", "Polacz!", WS_VISIBLE | WS_CHILD | WS_BORDER, 650, 40, 140, 30, hOkna, (HMENU)3, hThisInstance, NULL);
...
...

BUTTON_IMAGELIST bi;
HIMAGELIST lista=ImageList_Create(140,30, ILC_COLOR24 ,2,0);          
	
if(lista==NULL)
	MessageBox(0, "ERROR0", "", 0);
obraz=(HBITMAP)LoadImage(0,"D:\\tlobtn.bmp",IMAGE_BITMAP,0,0,LR_LOADFROMFILE);
obraz2=(HBITMAP)LoadImage(0,"D:\\tlobtn2.bmp",IMAGE_BITMAP,0,0,LR_LOADFROMFILE);

if(obraz==NULL || obraz2==NULL)
	MessageBox(0, "ERROR1", "", 0);
	
	
if(ImageList_Add(lista,obraz,NULL)<0)
	MessageBox(0, "ERROR2", "", 0);
 
if(ImageList_Add(lista,obraz2,NULL)<0)
	MessageBox(0, "ERROR3", "", 0);

bi.himl = lista;
bi.margin.bottom=1;
bi.margin.left=1;
bi.margin.right=1;
bi.margin.top=1;

bi.uAlign=BUTTON_IMAGELIST_ALIGN_TOP;


if(Button_SetImageList(GetDlgItem(hwnd, 3),&bi)==FALSE)
	MessageBox(0, "ERROR4", "", 0);

Znajduje sie w obsludze WM_CREATE, oczywiscie msg ktory pojawia sie na ekranie to "ERROR4", zaden z poprzednich. Probowalem juz chyba wszystkiego... Myslalem tez nad obsluga komunikatu WM_DRAWITEM, przy czym musialem dodac styl buttona BS_OWNERDRAW a razem z nim przesal dzialac msg BM_SETIMAGE wiec to sie chyba mija z celem. Chyba ze lecialbym z bitblt ale czy to ma sens? Prosze o pomoc bo zwariuje. ;/

EDIT
Dobra, problem rozwiazany za pomoca BS_OWNERDRAW & WM_DRAWITEM.

case WM_DRAWITEM:
			{
				//static std::ofstream out("D:\\else.txt");
				DRAWITEMSTRUCT* dr=(DRAWITEMSTRUCT*)lParam;
				if(wParam==3)
				{
					//out<<dr->itemState<<std::endl;
					if( dr->itemState==ODS_FOCUS || dr->itemState==0)
					{
						HDC hdcBitmapy=CreateCompatibleDC(dr->hDC);
						HBITMAP hdcStary=(HBITMAP)SelectObject(hdcBitmapy,obraz2);
						BitBlt(dr->hDC,0,0,140,30,hdcBitmapy,0,0,SRCCOPY);
						SelectObject(hdcBitmapy,hdcStary);
						DeleteDC(hdcBitmapy);
						ReleaseDC(dr->hwndItem, hdcBitmapy );
						return TRUE;
					}
					else
					if( dr->itemState==17)
					{
						//out<<dr->itemState<<std::endl;
						HDC hdcBitmapy=CreateCompatibleDC(dr->hDC);
						HBITMAP hdcStary=(HBITMAP)SelectObject(hdcBitmapy,obraz);
						BitBlt(dr->hDC,0,0,140,30,hdcBitmapy,0,0,SRCCOPY);
						SelectObject(hdcBitmapy,hdcStary);
						DeleteDC(hdcBitmapy);
						ReleaseDC(dr->hwndItem, hdcBitmapy );
						return TRUE;
					}
					
					return FALSE;

				}
				
			};
			break;
 

Co dziwnego ODS_FOCUS byl jedynym statusem kontrolki jaki dostawalem w DRAWITEMSTRUCT, patrzylem kazy inny ktory zostal opisany na msdn po kolei i nic... az dalem else i wypisywalem do notatnika wartosci dr->itemState - tak doszedlem do rozwiazania problemu ;D. Mimo wszystko dziekuje stfu za zaangazowanie. Pozdro ;)

edit
Problemow ciag dalszy... Ustawiam tlo edita na przezroczyste w ten sposob:

 
case WM_CTLCOLOREDIT:
{
	SetBkMode((HDC)wParam,TRANSPARENT);
	return (LRESULT)GetStockObject(NULL_BRUSH);
};
break;

Jest ok, napisze cos w edicie, pozniej jak kasuje tekst to normalnie kursor sie cofa a litery zostaja... Tak jakby sie nie odswiezal ;/. Jak temu zaradzic?

Problem z editem rozwiazany (moj poprzednik mial podobny problem ze static, po naprawieniu jego kodu dziala ;)) dla potomnych:

 
HBRUSH CreateTransparentBrush(HWND hwndParent, HWND hwndStatic)
{

HBRUSH hbr = (HBRUSH)GetProp(hwndStatic, "BRUSH");
if (!hbr)
{
RECT rc;
GetWindowRect(hwndStatic, &rc);
ScreenToClient(hwndParent, (POINT*)&rc); 


HDC hdcBitmapy, hdc;
hdc = GetDC(hwndParent);
hdcBitmapy=CreateCompatibleDC(hdc);

HDC hdctmp=CreateCompatibleDC(GetDC(hwndParent));

HBITMAP bmptmp=CreateCompatibleBitmap(hdc,rc.right-rc.left,rc.bottom-rc.top);

SelectObject(hdctmp,bmptmp);

BitBlt(hdctmp,0,0,rc.right-rc.left,rc.bottom-rc.top,hdc,rc.left,rc.top,SRCCOPY);


DeleteDC(hdcBitmapy);
ReleaseDC(hwndParent, hdcBitmapy );
DeleteDC(hdctmp);
ReleaseDC(hwndParent, hdctmp );

hbr = CreatePatternBrush(bmptmp);

SetProp(hwndStatic, "BRUSH", (HANDLE)hbr);
}
return hbr;
} 
} 
 
		case WM_CTLCOLOREDIT:
			{
				SetBkMode((HDC)wParam,TRANSPARENT);
				return (LRESULT)CreateTransparentBrush(hwnd, GetDlgItem(hwnd, 301));
			};
			break;

Pozostaje jeszcze 'tylko' problem z listview... pozdro

0

bi.margin.bottom=1;
bi.margin.left=1;
bi.margin.right=1;
bi.margin.top=1;

Czy sprawdzałeś z innymi wartościami? Chodzi o to, że takie coś tworzy strukturę RECT o zerowej wielkości. Raczej spodziewałbym się czegoś takiego (zgodnie z http://msdn.microsoft.com/en-us/library/windows/desktop/dd162897%28v=vs.85%29.aspx):
bi.margin.left = 1;
bi.margin.right = bi.margin.left + 130;
bi.margin.top = 1;
bi.margin.bottom = bi.margin.top + 30;

130 i 30 to tylko przykład, wartości zależą od tego jak duży jest twój Button.

P.S. jeszcze jedna uwaga z MSDN z powyższego linka:
"Note To use this macro, you must provide a manifest specifying Comclt32.dll version 6.0. For more information on manifests, see Enabling Visual Styles."

Czy masz to spełnione?

1 użytkowników online, w tym zalogowanych: 0, gości: 1