Zdravím, má tu někdo zkušenosti s ručně kreslěným progressbarem? Chtěl bych udělat jakousi minutku na odpočet času a indikovat zbývající čas na "kulatém" progressbaru. Předem díky ;-]
Fórum › C / C++
"Kulatý" progressbar - winapi
#1 ProXicT
ProgressBar nepodporuje WM_OWNERDRAW, takže buď si ho subclassovat (přesměrovat jeho proceduru okna na vlastní) a v obsluze WM_PAINT si tam podle libosti nějak vykreslit ten stav, nebo vůbec nepoužít progress bar jako control (okno) ale v obsluze WM_PAINT toho "rodičovského okna" na příslušné místo vykreslovcat stav (samozřejmě při požadavku na "posun" zavolat ručně RedrawWindow, čímž se vyvolá výše zmíněná obsluha WM_PAINT.
Radek Chalupa
- vývoj software na zakázku
- školení programování (C/C++, WinAPI, ATL, COM, ActiveX, C#, NET Framework, MFC)
http://www.radekchalupa.cz
Zkoušel jsem nejprve nakreslit jednoduchou kružnici pomocí (cos(x), sin(y)) a snažil jsem se vykreslit pixel, pomocí SetPixel(), vždy se mi ale vykreslil pouze jeden bod. Hlavně pro přesnou krunici bych měl použít double nebo float, ale to je v rastru nemožné...
#4 ProXicT
A pokud to chceš mít "hezčí", tj. s vyhlazením hran a oblouků, můžeš použít GDI+, např. takhle:
Gdiplus::Graphics* g = new Gdiplus::Graphics(hdc);
Gdiplus::SolidBrush br(Gdiplus::Color(0xA0,0,0));
Gdiplus::Rect rect(10, 10, 100, 100);
g->SetSmoothingMode(Gdiplus::SmoothingModeHighQuality);
g->FillPie(&br, rect, 0.0f, 145.0f);
delete g;
Radek Chalupa
- vývoj software na zakázku
- školení programování (C/C++, WinAPI, ATL, COM, ActiveX, C#, NET Framework, MFC)
http://www.radekchalupa.cz
#5 Radek Chalupa
Celý den se náhodou snažím vymyslet, jak bych to mohl vyhladit, přemýšlel jsem nad vykreslením všeho do bitmapy několikrát větší něž rozměr okna a pak tu bitmapu zmenšit a vykreslit. Vždy se mi ale vykresluje bílé okno. S GDI+ zatím nemám žádné zkušenosti, ale časem bych se to chtěl také naučit.
hdc = BeginPaint(hwnd, &ps);
HDC mdc = CreateCompatibleDC(hdc);
HBITMAP mbmp = CreateBitmap(960, 600, 1, 24, NULL);
HBITMAP moldbmp = (HBITMAP)SelectObject(mdc, mbmp);
HBRUSH brush = CreateSolidBrush(RGB(255, 0, 0));
HBRUSH brush2 = CreateSolidBrush(RGB(240, 240, 240));
HPEN pen = CreatePen(PS_SOLID, 1, RGB(255, 0, 0));
HPEN pen2 = CreatePen(PS_SOLID, 1, RGB(240, 240, 240));
int CenterX = RESx / 2;
int CenterY = RESy / 2;
int Radius = 30;
int StartptX = RESx / 2;
int StartptY = RESy / 2 - Radius;
int EndptX = RESx / 2 + Radius;
int EndptY = RESy / 2;
int width = 5;
SelectObject(mdc, brush);
SelectObject(mdc, pen);
Pie(mdc, CenterX - Radius, CenterY - Radius, CenterX + Radius, CenterY + Radius, StartptX, StartptY, EndptX, EndptY);
SelectObject(mdc, brush2);
SelectObject(mdc, pen2);
Ellipse(mdc, CenterX - Radius + width, CenterY - Radius + width, CenterX + Radius - width, CenterY + Radius - width);
StretchBlt(hdc, 0, 0, RESx, RESy, mdc, 0, 0, 960, 600, SRCCOPY);
SelectObject(mdc, moldbmp);
DeleteObject(mbmp);
DeleteDC(mdc);
EndPaint(hwnd, &ps);
#6 ProXicT
Odhadoval bych že důvod bílého okna bude v CreateBitmap. Místo toho bys v tomhle případě měl použít CreateCompatibleBitmap.
Jinak pokud jde o použití paměťového HDC, ukázku s vysvětlením najdeš tady: http://www.radekchalupa.cz/clanky/default.aspx?kod=205&obsah=6
Radek Chalupa
- vývoj software na zakázku
- školení programování (C/C++, WinAPI, ATL, COM, ActiveX, C#, NET Framework, MFC)
http://www.radekchalupa.cz
#7 z
Fungovalo to, když jsem to kreslil přímo do DC toho okna, ale když to kreslím do DC té bitmapy, kterou chci následně vykreslit, tak se nevykreslí nic. Předtím to vypadalo takto:
hdc = BeginPaint(hwnd, &ps);
HBRUSH brush = CreateSolidBrush(RGB(255, 0, 0));
HBRUSH brush2 = CreateSolidBrush(RGB(240, 240, 240));
HPEN pen = CreatePen(PS_SOLID, 1, RGB(255, 0, 0));
HPEN pen2 = CreatePen(PS_SOLID, 1, RGB(240, 240, 240));
int CenterX = RESx / 2;
int CenterY = RESy / 2;
int Radius = 30;
int StartptX = RESx / 2;
int StartptY = RESy / 2 - Radius;
int EndptX = RESx / 2 + Radius;
int EndptY = RESy / 2;
int width = 5;
SelectObject(hdc, brush);
SelectObject(hdc, pen);
Pie(hdc, CenterX - Radius, CenterY - Radius, CenterX + Radius, CenterY + Radius, StartptX, StartptY, EndptX, EndptY);
SelectObject(hdc, brush2);
SelectObject(hdc, pen2);
Ellipse(hdc, CenterX - Radius + width, CenterY - Radius + width, CenterX + Radius - width, CenterY + Radius - width);
EndPaint(hwnd, &ps);
Je to ale šíleně kostrbaté.
#8 Radek Chalupa
Neuvěřitelné, na všechno znáte odpověď ;] Bylo to tím, jen jsem čekal, že to bude vyhlazené, to jsem asi čekal špatně :-D Kód vypadá takto:
hdc = BeginPaint(hwnd, &ps);
HDC mdc = CreateCompatibleDC(hdc);
HBITMAP mbmp = CreateCompatibleBitmap(hdc, 960, 600);
HBITMAP moldbmp = (HBITMAP)SelectObject(mdc, mbmp);
RECT r;
SetRect(&r, 0, 0, 960, 600);
HBRUSH brush = CreateSolidBrush(RGB(255, 0, 0));
HBRUSH brush2 = CreateSolidBrush(RGB(240, 240, 240));
HPEN pen = CreatePen(PS_SOLID, 1, RGB(255, 0, 0));
HPEN pen2 = CreatePen(PS_SOLID, 1, RGB(240, 240, 240));
FillRect(mdc, &r, CreateSolidBrush(RGB(240, 240, 240)));
int CenterX = 480;
int CenterY = 300;
int Radius = 75;
int StartptX = CenterX;
int StartptY = CenterY - Radius;
int EndptX = CenterX + Radius;
int EndptY = CenterY;
int width = 15;
SelectObject(mdc, brush);
SelectObject(mdc, pen);
Pie(mdc, CenterX - Radius, CenterY - Radius, CenterX + Radius, CenterY + Radius, StartptX, StartptY, EndptX, EndptY);
SelectObject(mdc, brush2);
SelectObject(mdc, pen2);
Ellipse(mdc, CenterX - Radius + width, CenterY - Radius + width, CenterX + Radius - width, CenterY + Radius - width);
StretchBlt(hdc, 0, 0, RESx, RESy, mdc, 0, 0, 960, 600, SRCCOPY);
SelectObject(mdc, moldbmp);
DeleteObject(mbmp);
DeleteDC(mdc);
EndPaint(hwnd, &ps);
Výsledek je však nemilý:
#10 ProXicT
Možná by pomohlo jak výše naznačil kolega použít SetStretchBltMode; Ale z důvodu rychlosti bych cestu zmenšování neviděl jako nejlepší, myslím že GDI+ by bylo lepší řešení.
A pokud chceš zůstat u tohoto, a nemění se velikost cílové plochy tu bitmapu bych vytvořil jednou a nechal v globální proměnné než znova při každém předkreslení. Stejně tak je možné dát do globálu ty štětce a pera.
Radek Chalupa
- vývoj software na zakázku
- školení programování (C/C++, WinAPI, ATL, COM, ActiveX, C#, NET Framework, MFC)
http://www.radekchalupa.cz
#11 Radek Chalupa
Klidně bych to udělal pomocí GDI+, ale zatím je to pro mě španělská vesnice. Zkusil jsem ten SetStretchBltMode a nějaký rozdíl tam je. Pořád to není tak "dokonalé" jak jsem čekal, ale myslím, že to postačí. Ty proměnné jsem nechal ve funkci, ale se static. Jsem na to zvyklý.
hdc = BeginPaint(hwnd, &ps);
static HDC mdc = CreateCompatibleDC(hdc);
static HBITMAP mbmp = CreateCompatibleBitmap(hdc, 960, 600);
static HBITMAP moldbmp = (HBITMAP)SelectObject(mdc, mbmp);
static RECT r;
SetRect(&r, 0, 0, 960, 600);
static HBRUSH brush = CreateSolidBrush(RGB(255, 0, 0));
static HBRUSH brush2 = CreateSolidBrush(RGB(240, 240, 240));
static HPEN pen = CreatePen(PS_SOLID, 1, RGB(255, 0, 0));
static HPEN pen2 = CreatePen(PS_SOLID, 1, RGB(240, 240, 240));
FillRect(mdc, &r, CreateSolidBrush(RGB(240, 240, 240)));
static int CenterX = 480;
static int CenterY = 300;
static int Radius = 75;
static int StartptX = CenterX;
static int StartptY = CenterY - Radius;
static int EndptX = CenterX + Radius;
static int EndptY = CenterY;
static int width = 15;
SelectObject(mdc, brush);
SelectObject(mdc, pen);
Pie(mdc, CenterX - Radius, CenterY - Radius, CenterX + Radius, CenterY + Radius, StartptX, StartptY, EndptX, EndptY);
SelectObject(mdc, brush2);
SelectObject(mdc, pen2);
Ellipse(mdc, CenterX - Radius + width, CenterY - Radius + width, CenterX + Radius - width, CenterY + Radius - width);
SetStretchBltMode(hdc, HALFTONE);
StretchBlt(hdc, 0, 0, RESx, RESy, mdc, 0, 0, 960, 600, SRCCOPY);
SelectObject(mdc, moldbmp);
DeleteObject(mbmp);
DeleteDC(mdc);
EndPaint(hwnd, &ps);
Ještě k tomu GDI+...zatím bych se chtěl naučit "čisté" winapi na nějakou slušnou úroveň a pak bych šel dál. Nedávno jsem začal číst váš článek o winapi, tak uvidíme, co z toho poberu.
#12 ProXicT
U těch grafických objektů jde spíš než o static (ušetříš jen opakované vytváření na stacku) o to, že pokud se z nějaké příčiny bude za běhu rychle opakovat překreslování, tak vytvoření (a rušení) těch GDI objektů (zejména té bitmapy) má určitou časovou režii, která samozřejmě může nebo nemusí být významná, záleží na situaci.
Radek Chalupa
- individuální konzultace, školení programování (C/C++, WinAPI, COM, ActiveX, ATL, C#, NET Framework, MFC)
- vývoj software na zakázku
http://www.radekchalupa.cz
Přidej příspěvek
Ano, opravdu chci reagovat → zobrazí formulář pro přidání příspěvku
×Vložení zdrojáku
×Vložení obrázku
×Vložení videa
Uživatelé prohlížející si toto vlákno
Podobná vlákna
ProgressBar — založil Frank
ProgressBar — založil Anderos
Multithread a progressbar — založil aerkain
Silverlight - dataBinding z kódu - ProgressBar — založil Petrroll
C# Progressbar fungující i pod zatížením — založil Attila
Moderátoři diskuze