Draw overlay

Intrebari legate de programarea cu biblioteci precum MFC, ATL, WTL si GDI+.
mesajflaviu
Membru++
Membru++
Posts: 687
Joined: 10 Sep 2008, 21:40
Judet: Cluj

Re: Draw overlay

Post by mesajflaviu » 31 Oct 2012, 10:51

In primul rand multumesc pentru rabdare ... :oops: CDib exista in proiectul real si de aia l-am pus in aplicatia de test, o sa o scot afara, si o sa fac desenarea simpla, fara memory-device-context, intradevar, e mai greu de urmarit un proiect stufos ... imi cer scuze.

Pe bitmap-ul proiectulului real ar trebui puse 2 overlay-uri: unul care care contine linii si text, si care are o pozitie fixa (dar nu si dimensiune fixa), in stanga-jos. Al doilea overlay contine niste sageti desenate, doua la numar, cu dimensiune fixa, dar care nu au pozitie fixa, adica pot fi in partea de sus, dreapta, jos sau stanga view-ului. De ce spun asta, pentru ca aceste overlay-uri, putand avea atatea pozitii si dimensiuni, m-am gandit sa fac un layered window cat view-ul de mare, si acolo sa desenez tot ce trebuie peste bitmap, in pozitia ceruta ... de aceea am scos _ResizeWindowToFit(), si am facut fereastra layered cat view-ul ... _Draw() l-am "transformat" in OnDraw(CDC* pDC) si l-am lasat virtual.

Acum o sa incerc sa folosesc aceasta clasa pentru fiecare overlay pe un cate un view, dar nu stiu inca ce sa fac cu fereastra layered cand un alt view este peste view-ul care a creat aceasta fereastra layered ... o sa incerc si o sa pun aici "reusita".



User avatar
Ovidiu Cucu
Fondator
Fondator
Posts: 3778
Joined: 11 Jul 2007, 16:10
Judet: Iaşi
Location: Iasi
Contact:

Re: Draw overlay

Post by Ovidiu Cucu » 31 Oct 2012, 13:40

In general Layered Windows sunt ferestre cu dimensiuni relativ mici.
Daca zona client a view-ului e relativ mica (ceea ce nu prea cred, tinand cont de ceea ce vrei sa faci) si nu apar probleme de flicareli, atunci nu-i nici o problema sa faci o fereastra transparenta care s-o acopere in intregime.
Mai bine insa o limitezi la dimensiunea necesara. Daca ai mai multe chestii diferite, le poti pune in ferestre diferite.
Putem imbunatati functiile CTextLayeredWnd::SetAnchor si CTextLayeredWnd::Anchor in asa fel incat, in functie de un flag, sa ramana agatata stanga-sus, stanga, stanga-jos, s.a.m.d.

mesajflaviu
Membru++
Membru++
Posts: 687
Joined: 10 Sep 2008, 21:40
Judet: Cluj

Re: Draw overlay

Post by mesajflaviu » 31 Oct 2012, 15:41

O gluma buna:

Code: Select all

void CTestDrawView::OnActivateView(BOOL bActivate, CView* pActivateView, CView* pDeactiveView) 
{
	// TODO: Add your specialized code here and/or call the base class

	if(bActivate)m_wndOverlay.ShowWindow(SW_SHOW);
	else m_wndOverlay.ShowWindow(SW_HIDE);

	CScrollView::OnActivateView(bActivate, pActivateView, pDeactiveView);
}
si merge perfect, doar ca nu am overlay decat pe view-ul cu focusul :biggrin:

Acuma serios, daca as stii care regiune (rectangle) dintr-un view este acoperit de un alt view, cred ca as putea rezolva problema, desenand in COverlayWnd::OnDraw doar portiunea care se vede din ea ...

Cred ca e totuna daca fereastra layered este cat view-ul original (peste care sta) sau doar o portiune mica din el, as avea aceeasi problema, adica trebuie sa sterg partea care nu e vizibila la un moment dat ...
Attachments
TestDraw7.zip
(195.2 KiB) Downloaded 323 times

mesajflaviu
Membru++
Membru++
Posts: 687
Joined: 10 Sep 2008, 21:40
Judet: Cluj

Re: Draw overlay

Post by mesajflaviu » 02 Nov 2012, 13:06

Am reusit sa fac aplicatia sa mearga OK cu ferestre layered ... dar functioneaza corect doar cu 2 view-uri ...
Attachments
TestDraw8.zip
(198.91 KiB) Downloaded 344 times

User avatar
Ovidiu Cucu
Fondator
Fondator
Posts: 3778
Joined: 11 Jul 2007, 16:10
Judet: Iaşi
Location: Iasi
Contact:

Re: Draw overlay

Post by Ovidiu Cucu » 02 Nov 2012, 18:42

mesajflaviu wrote:Am reusit sa fac aplicatia sa mearga OK cu ferestre layered ... dar functioneaza corect doar cu 2 view-uri ...
Ce-ai zice de una care merge OK cu oricate view-uri? :)
MDI Child Overlay Text.jpg
MDI Child Overlay Text.jpg (95.37 KiB) Viewed 8836 times

mesajflaviu
Membru++
Membru++
Posts: 687
Joined: 10 Sep 2008, 21:40
Judet: Cluj

Re: Draw overlay

Post by mesajflaviu » 02 Nov 2012, 21:14

Nu-mi vine sa cred ... din poza asa pare, sa mearga bine ...

User avatar
Ovidiu Cucu
Fondator
Fondator
Posts: 3778
Joined: 11 Jul 2007, 16:10
Judet: Iaşi
Location: Iasi
Contact:

Re: Draw overlay

Post by Ovidiu Cucu » 05 Nov 2012, 10:13

Pai, daca-i cu Chuck Norris, cum sa nu mearga bine? :biggrin:
Iata aici si sursele:
Overlay_Text_MDI.zip
(34.59 KiB) Downloaded 1206 times
Pentru text simplu, single-line poti folosi direct COverlayTextWnd.
Pentru alte brzbriz-uri, derivezi din CLayeredAnchorWnd si suprascrii OnDraw si SizeWindowToFit.
That's all! Nu-i cea mai grozava solutie (eu as fi mers mai degraba pe solutia #3), dar functioneaza. Macar ne-am jucat putin cu ferestre layered. :)

Daca sunt observatii si nelamuriri, please feel free to ask!

mesajflaviu
Membru++
Membru++
Posts: 687
Joined: 10 Sep 2008, 21:40
Judet: Cluj

Re: Draw overlay

Post by mesajflaviu » 05 Nov 2012, 12:55

Merge brici, e altcumva gandit desenatul ferestrelor layered, fata de ce am incercat eu ... e un exemplu didactic si care a rezolvat problema overlay-ului, este ceea ce vroiam ... multumesc inca o data ...

Pe viitor, din curiozitate, as incerca si solutia 2 si 3 [Este un exercitiu bun pentru mine] ... banui ca ar trebui sa suprascriu CScrollView::OnScrollBy(...) si CScrollView::OnScroll(...), dar nu inteleg cum ar trebui sa desenez bitmap-ul si overlay-ul acolo (ca principiu ma refer) ... iar solutia 3 e asemanatoare cu 2 cu diferenta ca trebuie sa implementez eu scroll-bar-urile ?

mesajflaviu
Membru++
Membru++
Posts: 687
Joined: 10 Sep 2008, 21:40
Judet: Cluj

Re: Draw overlay

Post by mesajflaviu » 06 Nov 2012, 17:07

Solutia 2 ar fi de genul celei de aici ?

User avatar
Ovidiu Cucu
Fondator
Fondator
Posts: 3778
Joined: 11 Jul 2007, 16:10
Judet: Iaşi
Location: Iasi
Contact:

Re: Draw overlay

Post by Ovidiu Cucu » 07 Nov 2012, 00:17

Sa incercam sa lamurim un pic ce-i cu scrolbar-urile.
In Windows, acestea sunt de doua feluri:
  1. scrollbar-urile standard pentru ferestrele cu stilul WS_HSCROLL si/sau WS_VSCROLL.
  2. controalele scrollbar.
Ferestrele cu stilul WS_HSCROLL sau WS_VSCROLL primesc mesajul WM_HSCROLL respectiv WM_VSCROLL.
Controalele scrollbar trimit WM_HSCROLL sau WM_VSCROLL ferestrei parinte (de notat ca sunt si alte controlate care trimit aceste mesaje parintelui, ex. slider control).
Nici scrollbar-urile standard, nici controalele scrollbar NU fac ele insele scroll-ul. Pentru aceasta, o aplicatie trebuie sa handluiasca WM_HSCROLL si/sau WM_VSCROLL.

Clasa MFC, CScrollView foloseste scrollbar-urile standard (prin sertarea stilurilor WS_HSCROLL sau WS_VSCROLL). Are deja implement scroll-ul in modul cel mai simplu, prin apelul functiei ScrollWindow.
Cum functioneaza ScrollWindow? Pur si simplu muta continutul ferestrei in sus, in jos, la stanga sau la dreapta, apoi invalideaza zona "ramasa in urma" pentru a fi repictata (pe WM_PAINT, respectiv OnDraw).
Toate bune, simple si frumoase, insa in cazul tau, in care vrei sa ai si scroll si text/desen fix, nu mai e cu folos aceasta abordare. De aceea aveai acel text "saltaret", pentru ca mai intai se facea scroll-ul (se muta continutul cu tot cu text) apoi tu puneai din nou textul la locul lui pe OnDraw. In plus, in momentul cand ai pus Invalidate in OnHScroll si OnVScroll, marcand astfel toata zona client pentru repictare, practic ScrollWindow nu mai are sens.
Sper ca am explicat destul de clar.

In principiu, ar trebui sa suprascrii OnScrollBy sau sa renunti la CScrollView. In ambele cazuri, trebuie regandit modul de desenare.

Nu mi-e prea clar ce face chestia aia la care ai pus link, insa pare ca pe "scroll" pur si simplu schimba niste imagini, deci nu-i ceea ce vrei.

mesajflaviu
Membru++
Membru++
Posts: 687
Joined: 10 Sep 2008, 21:40
Judet: Cluj

Re: Draw overlay

Post by mesajflaviu » 07 Nov 2012, 13:41

Interesanta idee ... am incercat ceva in modul urmator: am setat o variabila membru care spune cand se deseneaza overlay-ul in OnDraw(...):

Code: Select all

void CTestDrawView::OnDraw(CDC* pDC)
{
	CTestDrawDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);
///*//// Draw the bitmap ////////////////////////////////////////////////////////////////
	CSize sizeDoc = pDoc->GetBitmapSize();
	CDC MemDC;
	MemDC.CreateCompatibleDC(pDC);
	CBitmap* pOldBitmap = MemDC.SelectObject(&pDoc->GetBitmap());
	pDC->SetStretchBltMode(HALFTONE);
	pDC->StretchBlt(0, 0, sizeLog.cx, sizeLog.cy, &MemDC, 0, 0, sizeDoc.cx, sizeDoc.cy, SRCCOPY);
	pDC->SelectObject(pOldBitmap);
///*/////////////////////////////////////////////////////////////////////////////////////
	if(m_bDrawOverlay)DrawOverlay(pDC);
....
}
in OnScrollBy desenez rectangle-ul bitmap, dar fara overlay, iar cand totul e gata, desenez si overlay-ul:

Code: Select all

BOOL CTestDrawView::OnScrollBy(CSize sizeScroll, BOOL bDoScroll) 
{
	// TODO: Add your specialized code here and/or call the base class

//	return CScrollView::OnScrollBy(sizeScroll, bDoScroll);

	// original code ...
	if (bDoScroll)
	{
		m_bDrawOverlay = FALSE;
		CRect rectClient;
		GetClientRect(&rectClient);
		InvalidateRect(rectClient, FALSE);
		UpdateWindow();
		CClientDC dc(this);
		OnPrepareDC(&dc);
		DrawOverlay(&dc);
		m_bDrawOverlay = TRUE;

		// do scroll and update scroll positions
//		ScrollWindow(-(x-xOrig), -(y-yOrig)); /// <-- removed
		if (x != xOrig)
			SetScrollPos(SB_HORZ, x);
		if (y != yOrig)
			SetScrollPos(SB_VERT, y);
	}

	return TRUE;
}
totusi, am am flickering la scroll ... Nu fac ceva bine, sau nu asta e ideea ?

User avatar
Ovidiu Cucu
Fondator
Fondator
Posts: 3778
Joined: 11 Jul 2007, 16:10
Judet: Iaşi
Location: Iasi
Contact:

Re: Draw overlay

Post by Ovidiu Cucu » 07 Nov 2012, 13:51

Un mic filmulet (cadru cu cadru) cu Chuck Norris :), care ilustreaza cum se face scroll-ul by default in CScrollView.
Sa zicem ca am incarcat acest bitmap, care are in stanga-sus un mic text.
1 - Before ScrollWindow.jpg
1 - Before ScrollWindow.jpg (35.36 KiB) Viewed 8737 times
Userul da click in scroolbar-ul vertical iar view-ul primeste WM_VSCROLL cu SB_PAGEDOWN. Daca pun un breakpoint la inceputul lui OnDraw, view-ul arata asa:
2 - After ScrollWindow.jpg
2 - After ScrollWindow.jpg (36.32 KiB) Viewed 8737 times
Undeva prin CScrollView::OnScrollBy s-a apelat ScrollWindow ceea ce a avut ca efect mutarea in sus a continutul view-ului (inclusiv acel text). In partea de jos, a ramas o zona neschimbata, care este invalidata de sistem si urmeaza sa fie repictata pe OnDraw:
3 - After OnDraw.jpg
3 - After OnDraw.jpg (36.43 KiB) Viewed 8737 times
Acuma din ceea ce ai incertat tu si de la ce a pornit aceasta discutie, lipseste cadrul #4. Adica, cel cu invalidat toata zona client in OnVScroll si scris "some text" in OnDraw la coordonate fixe. De fapt s-ar sari direct de la #2 la #4 ceea ce duce la acel efect de text saltaret. ;)

User avatar
Ovidiu Cucu
Fondator
Fondator
Posts: 3778
Joined: 11 Jul 2007, 16:10
Judet: Iaşi
Location: Iasi
Contact:

Re: Draw overlay

Post by Ovidiu Cucu » 07 Nov 2012, 14:10

mesajflaviu wrote:Interesanta idee ... am incercat ceva in modul urmator: am setat o variabila membru care spune cand se deseneaza overlay-ul in OnDraw(...):

Code: Select all

void CTestDrawView::OnDraw(CDC* pDC)
{
//...
	pDC->StretchBlt(0, 0, sizeLog.cx, sizeLog.cy, &MemDC, 0, 0, sizeDoc.cx, sizeDoc.cy, SRCCOPY);
//...
	if(m_bDrawOverlay)DrawOverlay(pDC);
//...
}
in OnScrollBy desenez rectangle-ul bitmap, dar fara overlay, iar cand totul e gata, desenez si overlay-ul:

Code: Select all

BOOL CTestDrawView::OnScrollBy(CSize sizeScroll, BOOL bDoScroll) 
{
		// do scroll and update scroll positions
//		ScrollWindow(-(x-xOrig), -(y-yOrig)); /// <-- removed
//...
Foarte bine. Dupa cum iti spuneam, in cazul nostru ScrollWindow mai mult incurca decat ajuta.
mesajflaviu wrote:totusi, am am flickering la scroll ... Nu fac ceva bine, sau nu asta e ideea ?
Bineinteles ca ai flicker. Scrii textul direct in view dupa ce faci stretch la ditamai bitmapul si il pictezi pe ditamai intreaga zona client.
Tot dupa cum iti spuneam, "trebuie regandit modul de desenare" si sa folosesti double-buffering.
Adica pictezi mai intai totul (bitmap, text si ce-o mai fi) intr-un memory DC, iar abia la urma-i frigi un bit-blit in DC-ul view-ului.

mesajflaviu
Membru++
Membru++
Posts: 687
Joined: 10 Sep 2008, 21:40
Judet: Cluj

Re: Draw overlay

Post by mesajflaviu » 08 Nov 2012, 10:59

Sant atat de aproape de a rezolva problema cu solutia 2, cat e Chuck Norris de Felix Baumgartner ... :biggrin:
Image

Scot afara ScrollWindow(...) din CTestDrawView::OnScrollBy(...), da' atunci trebuie sa invalidez imaginea CTestDrawView::OnHScroll(...) si CTestDrawView::OnVScroll(...), ca altfel n-am cum sa fac scroll ... si desenez in OnDraw cu double-buffering, am inteles bine ? Si asta presupune sa tin bitmap-ul intr-o variabila locala, poate si memory-device-context-ul ? Poate la acest capitol revin cu o intrebare ....

User avatar
Ovidiu Cucu
Fondator
Fondator
Posts: 3778
Joined: 11 Jul 2007, 16:10
Judet: Iaşi
Location: Iasi
Contact:

Re: Draw overlay

Post by Ovidiu Cucu » 08 Nov 2012, 12:02

O fi el Felix Baumgartner tare, insa se vede ca n-are scroll. :D
Btmap-ul sursa of course, il pui la pastrare ca doar n-o sa-l incarci de fecare data din fisier.
Celelalte nu, nici memory DC-urile.

Post Reply