Prekresľovanie okna bez blikania – C / C++ – Fórum – Programujte.com
 x   TIP: Přetáhni ikonu na hlavní panel pro připnutí webu

Prekresľovanie okna bez blikania – C / C++ – Fórum – Programujte.comPrekresľovanie okna bez blikania – C / C++ – Fórum – Programujte.com

 

iridium0
Newbie
13. 5. 2014   #1
-
0
-

Dobrý deň.

Akým spôsobom mám vo WinAPI zariadiť, aby prekresľovanie klientskej oblasti okna sa zaobišlo bez blikania objektov, ktoré v okne zostávajú?

Napríklad:
Kreslím úsečky ľavým tlačidlom myši do klientskej oblasti hlavného okna. Potrebujem, aby v určitom úseku okna stará úsečka zmizla, a nahradila ju nová, ktorú práve nakreslím. Robím to takto:

V handleri správy WM_PAINT používam kód:

RECT oblast_usecky;
SetRect(&oblast_usecky, 0, 0, 100, 300);
InvalidateRect (hWnd, &oblast_usecky, TRUE);

V handleri správy WM_LBUTTONDOWN používam:

SendMessage(hWnd, WM_PAINT, 0, 0);

....Problém je však v tom, že v tej oblasti okna sa nachádza aj jedno tlačítko, ktoré pri prekresľovaní občas preblikáva, a tomu chcem zabrániť. -V budúcnosti totiž plánujem používať rad úsečiek vedľa seba napr. ako indikátor sily signálu. Rád by som však bol, keby existovala nejaká možnosť, aby to tlačítko pri každom prekreslení nepreblikávalo. Dá sa to nejako zariadiť?

Za odpoveď vám vopred ďakujem.

Nahlásit jako SPAM
IP: 62.197.243.–
p3can
~ Anonymní uživatel
312 příspěvků
13. 5. 2014   #2
-
0
-

nejspise se jedna o problem s VSync.

reseni je nastavit property na true

http://msdn.microsoft.com/en-us/library/b367a457%28v=vs.110%29.aspx
Nahlásit jako SPAM
IP: 77.92.213.–
z
~ Anonymní uživatel
268 příspěvků
13. 5. 2014   #3
-
0
-

Jestli kreslíš přímo na hlavní okno, tak to je na prd. Udělej si vlastní "podokno" pro to "plátno", na které kreslíš. Nebudeš tak vrtat do toho hlavního a dalších oken (jako toho tlačítka) se to nedotkne.

InvalidateRect nemá v obsluze WM_PAINT co dělat a asi nepotřebuješ bErase na TRUE. Při tom kliku (resp. když potřebuješ okno překreslit) neposílej WM_PAINT "ručně", ale zavolej ten InvalidateRect, nebo rychlejší UpdateWindow. To zajistí poslání WM_PAINT.

Další věc, pokud budeš vykreslovat více objektů, je tzv. double-buffering. Tj. objekty se nekreslí přímo do okna, ale do bitmapy/dc v paměti a až ta se nakonec celá vykreslí do okna.

Nahlásit jako SPAM
IP: 88.101.8.–
Radek Chalupa
~ Redaktor
+1
Super člen
13. 5. 2014   #4
-
0
-

#3 z
Přesně tak. Jen doplním: nezapomeň v proceduře toho "plátna" zadržet WM_ERASEBKGNB (tj. vrátit 0) nebo pokud to nebude nějaký static-control, tak rovnou při vlastní registraci jeho třídy nastavit hbrBackground na NULL, v opačném případě by před tím vykreslením paměťového HDC probliklo vykreslení pozadí.

PS: a pokud bys snad chtěl za každou cenu optimalizovat rychlost a kvalitu vykreslování, nastuduj si Direct2D :-)

Radek Chalupa 
- individuální konzultace a školení programování (C/C++, C#, WinAPI, COM, ATL, ActiveX, NET Framework, MFC)
- vývoj software na zakázku 
http://www.radekchalupa.cz

Nahlásit jako SPAM
IP: 89.177.51.–
iridium0
Newbie
14. 5. 2014   #5
-
0
-

#4 Radek Chalupa
Dík za rady. Spravil som si druhé okno typu child ku hlavnému oknu, na ktoré už teraz kreslím a zadržal som správu WM_ERASEBKGND. Úsečky sa ale traz neprekresľujú. Predošlé zostávajú v okne. Keď však okno prekryjem iným oknom (napr. Mozillou), staré úsečky zmiznú, a zostane tam len tá posledná ktorú som kreslil. (potreboval by som, aby počas kreslenia zostávala v okne vždy len tá aktuálna, naposledy nakreslená)

-Naviac som stratil aj kontakt s tlačítkom v hl. okne. Keď sa naň teraz postavím kurzorom myši, nejde ho stlačiť.

Celý výpis procedúry toho nového okna:

POINTS g_point;

LRESULT CALLBACK WndProc2(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam)
{   
    switch(Message)
    {   
       case WM_PAINT:
             PAINTSTRUCT ps;
             HDC hdc;
             hdc = BeginPaint(hwnd, &ps);
             MoveToEx(hdc, 100, 0, NULL);
             LineTo(hdc, g_point.x, g_point.y);
             EndPaint(hwnd, &ps);
             break;
             
        case WM_ERASEBKGND:
             return 0;
             
        case WM_LBUTTONDOWN:
             InvalidateRect (hwnd, 0, TRUE);
             g_point = MAKEPOINTS(lParam);
             break;
             
        case WM_DESTROY:
             PostQuitMessage(0);
             break;      
    }
    return DefWindowProc(hwnd, Message, wParam, lParam);
}

....Keď nezadržujem správu WM_ERASEBKGND, tak to funguje. V okne zostáva počas kreslenia vždy len jedna úsečka, ktorú som nakreslil ako poslednú. Problém je ale vtedy ten, že pozadie tohoto detského okna ("plátna"), prekryje hl. okno, takže zmiznú všetky jeho prvky (vrátane tlačítka).

...Chcel som vyskúšať aj kreslenie do bitmapy/dc v pamäti, ale neviem presne, ako na to. Chcem sa spýtať: To je to kreslenie, ktoré využíva na získanie bitmapy/dc funkciu CreateCompatibleDC() a na skopírovanie do dc funkciu BitBlt() ?

Nahlásit jako SPAM
IP: 62.197.243.–
Radek Chalupa
~ Redaktor
+1
Super člen
14. 5. 2014   #6
-
0
-

#5 iridium
To zadržení WM_ERASEBKGND jsem myslel v případě že použiješ buffering, jak radil kolega "Z".

Jak na buffering s využitím paměťového HDC najdeš např. zde http://www.radekchalupa.cz/clanek/gdi-buffering/

Radek Chalupa 
- individuální konzultace a školení programování (C/C++, C#, WinAPI, COM, ATL, ActiveX, NET Framework, MFC)
- vývoj software na zakázku 
http://www.radekchalupa.cz

Nahlásit jako SPAM
IP: 89.177.51.–
iridium0
Newbie
14. 5. 2014   #7
-
0
-

#6 Radek Chalupa
Dík, vyskúšal som to. Funguje to dobre. Avšak potreboval by som, aby pozadie tej pamäťovej bitmapy bolo priesvitné. V hlavnom okne mám už totiž určité pozadie načítané zo zdrojov, a potreboval by som, aby pri kreslení zostalo zachované. Skúšal som aj vynechať FillRect(), ale nepomohlo to. Pozadie bolo čierne. Existuje nejaká možnosť, ako docieliť priesvitnosť?

Nahlásit jako SPAM
IP: 62.197.243.–
Radek Chalupa
~ Redaktor
+1
Super člen
14. 5. 2014   #8
-
0
-

#7 iridium
Přijde na to jak to vykresluješ do té paměťové bitmapy. Možná bude stačit SetBkMode(hdc, TRANSPARENT); To ti nechá netknuté pozadí za textem a objekty kreslenými perem (HPEN).

Radek Chalupa 
- individuální konzultace a školení programování (C/C++, C#, WinAPI, COM, ATL, ActiveX, NET Framework, MFC)
- vývoj software na zakázku 
http://www.radekchalupa.cz

Nahlásit jako SPAM
IP: 89.177.51.–
iridium0
Newbie
14. 5. 2014   #9
-
0
-

SetBkMode(hdc,TRANSPARENT) som skúšal, ale nepomohlo to.

Zasláno z mobilního telefonu.

Nahlásit jako SPAM
IP: 85.237.224.–
Zjistit počet nových příspěvků

Přidej příspěvek

Toto téma je starší jak čtvrt roku – přidej svůj příspěvek jen tehdy, máš-li k tématu opravdu co říct!

Ano, opravdu chci reagovat → zobrazí formulář pro přidání příspěvku

×Vložení zdrojáku

×Vložení obrázku

Vložit URL obrázku Vybrat obrázek na disku
Vlož URL adresu obrázku:
Klikni a vyber obrázek z počítače:

×Vložení videa

Aktuálně jsou podporována videa ze serverů YouTube, Vimeo a Dailymotion.
×
 
Podporujeme Gravatara.
Zadej URL adresu Avatara (40 x 40 px) nebo emailovou adresu pro použití Gravatara.
Email nikam neukládáme, po získání Gravatara je zahozen.
-
Pravidla pro psaní příspěvků, používej diakritiku. ENTER pro nový odstavec, SHIFT + ENTER pro nový řádek.
Sledovat nové příspěvky (pouze pro přihlášené)
Sleduj vlákno a v případě přidání nového příspěvku o tom budeš vědět mezi prvními.
Reaguješ na příspěvek:

Uživatelé prohlížející si toto vlákno

Uživatelé on-line: 0 registrovaných, 26 hostů

Podobná vlákna

WinApi bez okna — založil aTTix

Okna — založil hans

Okna — založil keet

Moderátoři diskuze

 

Hostujeme u Českého hostingu       ISSN 1801-1586       ⇡ Nahoru Webtea.cz logo © 20032024 Programujte.com
Zasadilo a pěstuje Webtea.cz, šéfredaktor Lukáš Churý