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 » 08 Nov 2012, 15:45

Nu vreau sa abuzez de rabdarea voastra, dar ceva nu merge cum trebuie: overlay-ul ramane stabil si fara flicker, dar lasa "dare" pe view ... alta problema, nu pot incarca bitmap-ul cu zoom in memorie.
Am creat o metoda:

Code: Select all

void CTestDrawView::InitializeBitmap()
{
	if(NULL != m_Bitmap.GetSafeHandle())
	{
		m_Bitmap.DeleteObject();
	}
	CTestDrawDoc* pDoc = GetDocument();
	CSize sizeDoc = pDoc->GetBitmapSize();
	CSize sizeLog = pDoc->GetBitmapSize(m_fZoomFactor);

	CDC MemDC;
	CPaintDC dc(this);
	MemDC.CreateCompatibleDC(&dc);
	CBitmap* pOldBitmap = MemDC.SelectObject(&pDoc->GetBitmap());
	dc.StretchBlt(0, 0, sizeLog.cx, sizeLog.cy, 
		&MemDC, 0, 0, sizeDoc.cx, sizeDoc.cy, SRCCOPY);
	MemDC.SelectObject(pOldBitmap);
	m_Bitmap.CreateCompatibleBitmap(&dc, sizeLog.cx, sizeLog.cy);
}
in care incerc sa pun in m_Bitmap bitmap-ul din document, dar intins cu StretchBlt, ca sa am zoom .... nu merge, ecranul ramane negru. Pentru ca daca nu fac aici zoom-ul, in OnDraw, cu pDC->BitBlt nu mai pot ....

Metoda CTestDrawView::OnDraw arata simplu:

Code: Select all

void CTestDrawView::OnDraw(CDC* pDC)
{
	CTestDrawDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);
	// TODO: add draw code for native data here
	CRect rectClient;
	GetClientRect(&rectClient);
///*//// Draw the bitmap ////////////////////////////////////////////////////////////////
	CSize sizeDoc = pDoc->GetBitmapSize();
	CDC MemDC;
	MemDC.CreateCompatibleDC(pDC);
	CBitmap* pOldBitmap = MemDC.SelectObject(&m_Bitmap);
//	CBitmap* pOldBitmap = MemDC.SelectObject(&pDoc->GetBitmap());
	DrawOverlay(&MemDC);
	CRect rect(rectClient);
	rect += GetScrollPosition();
	pDC->BitBlt(rect.left, rect.top, rect.Width(), rect.Height(), 
		&MemDC, rect.left, rect.top, SRCCOPY);
	MemDC.SelectObject(pOldBitmap);
///*/////////////////////////////////////////////////////////////////////////////////////
dar overlay-ul lasa o urme ("dare") pe bitmap ... de ce ?

In OnDraw, pot incarca in MemDC bitmap-ul direct din clasa document, cum am comentat linia de mai sus:

Code: Select all

	CBitmap* pOldBitmap = MemDC.SelectObject(&pDoc->GetBitmap());
in acest mod bitmap-ul se afiseaza corect, dar nu mai pot avea zoom ... si in acest caz overlay-ul lasa urme ("dare") pe ecran ...

Ma mai gandesc la ceva: nu stiu daca e bine sa incarc un bitmap marit in memorie, caci la fisiere bitmap mari s-ar putea sa am probleme ... dar atunci cum sa fac zoom in OnDraw, cu BitBlt ?

Pentru exemplificare a ceea ce am spus mai sus, atasez aici "opera de arta". Orice sugestie ar fi super-bine-venita.
Attachments
TestDraw9.zip
(200.75 KiB) Downloaded 363 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 » 08 Nov 2012, 20:16

mesajflaviu wrote:[...]
In OnDraw, pot incarca in MemDC bitmap-ul direct din clasa document, cum am comentat linia de mai sus:

Code: Select all

	CBitmap* pOldBitmap = MemDC.SelectObject(&pDoc->GetBitmap());
in acest mod bitmap-ul se afiseaza corect, dar nu mai pot avea zoom ... si in acest caz overlay-ul lasa urme ("dare") pe ecran ...
Daca vrei poti, insa nu-i bine. Un memory DC este un DC in care se fapt desenezi intr-un... bitmap. Daca selectezi bitmapul sursa intr-un DC iar apoi desenezi in el, normal ca te alegi cu dare si mazgaleli.
mesajflaviu wrote: Ma mai gandesc la ceva: nu stiu daca e bine sa incarc un bitmap marit in memorie, caci la fisiere bitmap mari s-ar putea sa am probleme ... dar atunci cum sa fac zoom in OnDraw, cu BitBlt ?
Eu zic sa faci asa: socotesti in asa fel incat DC-ul final, ala pe care in cele din urma il bit-blituiesti in DC-ul view-ului, sa fie unul cu dimensiunile zonei client. E un pic de jonglat cu cateva DC-uri intermediare, insa nu-i un capat de lume... ;)

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 » 09 Nov 2012, 11:48

In principiu, ai putea face asa:
  1. un memory DC (sa-i zicem DC1) in care selectezi bitmapul sursa (cel incarcat din fisier, resurse, etc).
  2. un memory DC pentru desenare (DC2) in care selectzi un bitmap compatibil de dimensiunile zonei client a view-ului (nu cat ditamai bitmapul zoomat).
  3. faci stretch-blit din DC1 in DC2; coordonatele si dimensiunele sursei si destinatiei le calculezi in functie de dmensiunile sursei, scroll, zoom si in fine dimensiunea zonei client.
  4. desenezi in DC2 ce "overlay" fix vrea muschii tai: texte, linii, mutzunaki, etc.
  5. faci bit-blit din DC2 in DC-ul view-ului.
In fine, spun astea ca un "architect" care n-a incercat inca, deci nu-i sigur 100% cum merge si daca n-ar mai trebui schimbat pe ici pe colo si anume in punctele esentiale. :)

Folosesti peste tot doar MM_TEXT iar originea viewport-ului o tii pe zero. Asta implica sa nu folosesti mai nimic din implementarea default din CScrollView si decat sa te apuci sa dai cu barda prin toate functiile virtuale, cu riscul de a mai avea si surprize neplacute "in spate", zi eu, mai bine derivezi direct din CView.
In plus, dupa cum spuneam mai demult, scroll-ul default de la CScrollView este limitat la 32768 (provenit de la faptul ca WM_HSCROLL si WM_VSCROLL tine pozitia pe 16 biti), limita destul de usor de atins daca faci zoom-uri bengoase pe bitmapuri mari. Rescriind scroll-ul la mana poti trece peste asta deoarece functii prcum SetScrollInfo, SetScrollPos, SetScrollRange, GetScrollInfo, GetScrollPos, si GetScrollRange le tin totusi pe 32 biti (vezi si remarcile din MSDN).

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 » 09 Nov 2012, 12:24

Am vrut sa spun insa am uitat. Poti arunca un ochi cum a facut scroll Chris Maunder in gridul sau: MFC Grid control (derived from CWnd).
Nu-i ceea ce vrem noi insa e bun ca material didactic, de exemplu (daca imi aduc bine aminte) sa vezi cum a trecut de hopul cu limitarile lui WM_HSCROLL/WM_VSCROLL.

BTW. Pe asta, cand eram tanar si nelinistit, am invatat ceva MFC... :D

[ later edit ]
Voi incerca sa pun un asemenea image view-er cu "overlay" la rubrica Proiecte Open-Source.
Insa acesta nefiind pentru mine cel mai arde-frige-n-are-gura-ca-sa-strige dintre deadline-uri, s-ar putea sa mai dureze.
Asa ca, ar fi bine ca intre timp sa incerci si tu o rezolvare... ;)

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

Re: Draw overlay

Post by mesajflaviu » 09 Nov 2012, 12:59

La asta lucrez acum, mai am sa intind bitmap-ul in DC2 in functie de zoom si scroll ... nu-mi vine sa cred ce stabil e overlay-ul !
Last edited by mesajflaviu on 09 Nov 2012, 13:29, edited 1 time in total.

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 » 09 Nov 2012, 13:15

De ce n-ar fi stabil? Doar de aia s-a inventat "femeia cu sarpele care uite ca n-o musca" si minunea-minunilor... Double Buffering. :D

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

Re: Draw overlay

Post by mesajflaviu » 09 Nov 2012, 16:38

Nu merge bine:

Code: Select all

void CTestDrawView::OnDraw(CDC* pDC)
{
	CTestDrawDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);
///*//// Draw the bitmap ////////////////////////////////////////////////////////////////
	CPoint ptScroll = GetScrollPosition();
	CDC SourceDC, DrawDC;
	DrawDC.CreateCompatibleDC(pDC);
	SourceDC.CreateCompatibleDC(pDC);
	CBitmap* pOldBitmap = SourceDC.SelectObject(&pDoc->GetBitmap());
	CBitmap* pOldBitmapDraw = DrawDC.SelectObject(&m_Bitmap);
	DrawDC.StretchBlt(0, 0, rectClient.Width(), rectClient.Height(), 
		&SourceDC, ptScroll.x, ptScroll.y, rectClient.Width(), rectClient.Height(), SRCCOPY);
	DrawOverlay(&DrawDC);
	pDC->BitBlt(0, 0, rectClient.Width(), rectClient.Height(), &DrawDC, 0, 0, SRCCOPY);
	SourceDC.SelectObject(pOldBitmap);
	DrawDC.SelectObject(pOldBitmapDraw);
///*/////////////////////////////////////////////////////////////////////////////////////
}
in care m_Bitmap il initializez in OnSize:

Code: Select all

void CTestDrawView::OnSize(UINT nType, int cx, int cy) 
{
	CScrollView::OnSize(nType, cx, cy);

	// TODO: Add your message handler code here
/*//////////////////////////////////////////////////
	CTestDrawDoc* pDoc = GetDocument();
	CSize sizeDoc = pDoc->GetBitmapSize();
	if(sizeDoc.cx < cx)cx = sizeDoc.cx;
	if(sizeDoc.cy < cy)cy = sizeDoc.cy;
///*//////////////////////////////////////////////////
	if(NULL != m_Bitmap.GetSafeHandle())m_Bitmap.DeleteObject();
	CClientDC dc(this);
	m_Bitmap.CreateCompatibleBitmap(&dc, cx, cy);
	Invalidate();
}
nu pot pune in DC2 (la mine DrawDC) rectangle-ul corect, nu mai vorbesc de zoom ... ce nu am facut bine ?
Attachments
TestDraw9.zip
(202.19 KiB) Downloaded 366 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 » 09 Nov 2012, 21:23

Cand ai de facut chestii din astea, este bine sa lasi putin computerul si sa iei un creion si-o hartie cu patratele. Se vede ca n-ai facut asa. ;)

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

Re: Draw overlay

Post by mesajflaviu » 11 Nov 2012, 13:59

Linia

Code: Select all

pDC->BitBlt(0, 0, rectClient.Width(), rectClient.Height(), &DrawDC, 0, 0, SRCCOPY);
e clara, pun in DC view-ului DrawDC, care ar trebui sa fie pregatit la dimensiunea ecranului, cu informatia (portiunea de bitmap) corespunzatoare. Revin ...

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

Re: Draw overlay

Post by mesajflaviu » 11 Nov 2012, 14:37

Inainte de asta, in DrawDC pun m_Bitmap, care are dimensiunea clientului:

Code: Select all

CBitmap* pOldBitmapDraw = DrawDC.SelectObject(&m_Bitmap);
In SourceDC, pun bitmap-ul original:

Code: Select all

CBitmap* pOldBitmap = SourceDC.SelectObject(&pDoc->GetBitmap());
tot ce trebuie sa mai fac, este sa pozitionez/intind in DrawDC, SourceDC:

Code: Select all

	DrawDC.StretchBlt(0, 0, rectClient.Width(), rectClient.Height(), 
		&SourceDC, ptScroll.x, ptScroll.y, rectClient.Width(), rectClient.Height(), SRCCOPY);
aici e cuiul lui Pepelea ...
Am luat cazul cel mai simplu, cand zoom-ul e 1 (100%).
Din SourceDC am incercat sa iau portiunea din bitmap-ul original:
ptScroll.x, ptScroll.y, rectClient.Width(), rectClient.Height(), adica left-ul si top-ul rectangle-ului in functie de scroll si latimea/inaltimea de dimensiunea clientului ... acest rectangle il pun pe rectangle-ul destinatie, 0, 0, rectClient.Width(), rectClient.Height() al DrawDC-ului ... si nu cred ca e buna aceasta logica, fiindca aici nu are loc socoteala in care as avea zoom ... hmm ... trebuie sa mai sap, si mai revin ...

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 » 11 Nov 2012, 16:54

In primul rand incearca sa aduni la un loc tot ce tine de desenare (DC-uri cu bitmapurile aferente), in functia de desenare.
Nu castigi nimic daca pui "la pastrare" un DC sau un bitmap care oricum trebuie refacut frecvent, apoi sa le distrugi si re-creezi prin WM_SIZE sau darcu mai stie pe unde.

Spuneai mai devreme ca-ti place acel CMemDC. De ce nu-l folosesti?
Te scuteste in primul rand de grija eliberarii obiectelor GDI, a memory leaks si a altor minuni de genul asta. RAI(I) curat! ;)
Vezi ca are doi costructori:
  1. CMemDC(CDC* pDC, int nWidth, int nHeight) ii plasezi DC-ul cu care trebuie sa fie compatibil si dimensiunile, apoi isi creaza si selecteaza el singur bitmapul pe care trebuie sa deseneze.
  2. CMemDC(CDC* pDC, CBitmap* pBitmap) - ii dai DC-ul cu care trebuie sa fie compatibil si un bitmap deja existent; ideal pentru tinut bitmapul sursa pentru a fi bit-blituit in alt DC.
Iar pe destructor, are el grija sa nu lase mizerie la locul de munca.

Poate n-am spus destul de clar mai devreme: "coordonatele si dimensiunele sursei si destinatiei le calculezi in functie de dmensiunile sursei, scroll, zoom si in fine dimensiunea zonei client". In StretchBlt din codul tau nu vad nicaieri variabile care sa tina de dimensiunile sursei si zoom.
Pui dimensiunile destinatiei pe dimensiunile zonei client (faci stretch pe zona client a view-ului) ceea ce nu-i corect. Destinatia trebuie sa fie de dimensiuni proportionale cu sursa (in functie de zoom). Am spus doar sa folosesti un DC destinatie cu dimensiunile zonei client. Nu-i nimic daca dimensiunile destinatiei din StretchBlt depasesc sau nu dimensiunile DC-ului destinatie. Oricum sistemul o sa ignore ce da pe dinafara.

In fine ar fi fost mai clar ce-am vrut sa sugerez, daca ti-as fi aratat foaia mea cu patratele despre care am vorbit serios. Din pacate mi s-a stricat scanerul, si nu vreau sa pierd acum timp cu desenat scheme pe computer.
Am facut deja o clasa care rezolva problema si cred ca din cod ti-ar fi destul de usor sa te prinzi ce am facut. Daca nu, putem discuta dupa aceea si eventual sa facem si niste desene ca sa fie totul mult mai clar. Mai am de completat cate ceva si voi pune acusi o aplicatie demo.

Pana atunci, in avanpremiera, o poza pentru impresia artistica :)
Overlay Image and Text.jpg
Overlay Image and Text.jpg (52.22 KiB) Viewed 9644 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 » 11 Nov 2012, 18:39

Iaca si sursele cu proiectul demo!
Image_scroll_zoom_demo.zip
(49.43 KiB) Downloaded 351 times
Iata si cate ceva despre ele, pe scurt:
CImageView, derivata din CScrollView este o clasa abstracta care face cam tot ce trebuie: umplere background, afisare imagine, zoom si scroll, mai putin sa deseneze overlay-urile care normal, trebuie sa poata fi customizate in functie de aplicatie.
Deci, cam tot ce ai de facut e sa derivezi din CImageView (vezi ca exemplu CDemoView) si sa suprascrii functia virtuala DrawOverlay apoi sa mapezi comenzile si metodele publice necesare.

La fel, am facut si o clasa abstracta CImageDoc derivata din CDocument, care contine bitmap-ul sursa si ofera metode legate de acesta.
E bine s-o folosesti si pe aceasta ca si clasa de baza pentru ca iti permite, daca de exemplu vrei sa extinzi aplicatia sa suporte si altceva decat BMP-uri, poti face asta suprascriind oaresce functii virtuale in loc sa dai cu barda in cod deja scris.

Pun aici o lista cu metode publice si metode virtuale, cu o descriere scurta la fiecare:
  • CImageView::SetBackPatternBrush - seteaza pentru background un brush bazat pe un bitmap
  • CImageView::SetBackSolidBrush - seteaza pentru background un brush bazat pe o culoare
  • CImageView::SetHandCursor - seteaza cursorul "hand", cel folosit in momentul in care userul incepe sa mute imaginea cu mouse-ul.
  • CImageView::SetHandDragCursor - seteaza cursorul "hand drag", cel folosit in momentul cand userul muta imaginea cu mouse-ul
  • CImageView::ZoomIn - incrementeaza zoom-ul
  • CImageView::ZoomOut - decrementeaza zoom-ul
  • CImageView::ZoomToOriginalSize - afiseaza imaginea la dimensiunea originala (zoom 1.0)
  • CImageView::ZoomToWindowWidth - face fit la latimea view-ului.
  • CImageView::ZoomToWindow - face fit in zona client a view-ului.
  • CImageView::ZoomToRectangle - (virtual) de suprascris in caz ca se doreste altfel de zoom la selecta cu mouse-ul
  • CImageView::DrawBackgound - (virtual) de suprascris in caz ca se doreste un alt mod de umplere a background-ului.
  • CImageView::DrawImage - (virtual) de suprascris in caz ca se doreste un alt mod de desenare a imaginii
  • CImageView::DrawOverlay - (pure virtual) obligatoriu de suprascris, pentru desenarea "overlay", in functie de aplicatie.
  • CImageDoc::GetImage - intoarce o referinta la bitmapul sursa.
  • CImageDoc::IsValidImage - intoarce TRUE daca imaginea (bitmapul) continuta este valida.
  • CImageDoc::GetImageSize - intoarce dimensiunile imaginii sursa.
  • CImageDoc::LoadFromFile - (virtual) incarca imaginea dintr-un fisier BMP. O poti suprascrie in clasa derivata daca de exemplu vrei sa schimbi LoadImage cu ceva mai bengos, sa zicem din GDI+.
Note:
  1. Am suprascris CScrollView::OnScrollBy eliminand apelul la ScrollWindow si invalidand zona client. In rest, am pastrat codul din clasa de baza.
  2. Am suprascris CScrollView::OnPrepareDC pentru a forta mapping mode pe MM_TEXT si viewport origin la (0, 0), nescesare in implementarea data.
  3. Vezi cum am facut calculele in CImageView::DrawImage.
  4. CImageView::ZoomToRectangle face zoom bazandu-se pe latura de sus a selectiei. Asta pentru ca unui user ii vine mai usor sa ia o latura a dreptunghiului ca reper, decat centrul sau (cum am vazut in alte implementari). Daca vrei sa schimbi asta, no problem, o suprascrii in clasa derivata.
  5. CImageView::OnMouseWheel face scroll asa cum este implementat by default in clasa de baza, CScrollView. Am adaugat zoom daca userul tine "Ctrl" apasat. Vrei altfel? No problem, mapeaza WM_MOUSEWHEEL in clasa derivata.
  6. Ar mai fi unele mici ajustari de facut, pentru ca nu am tinut nicaieri cont de scrollbars. De asemenea se mai poate imbunatati performanta setind clip region pentru DC-ul intermediar si probabil se mai pot face si alte imbunatatiri. Intentionat nu le-am facut inca pentru a lasa codul mai simplu deci mai usor de inteles. Oricum, din ce am testat pana acum se misca suficient de fast.
  7. Am "stresat" putin aplicatia demo punand deasupra imaginii un mic desen animat. :D


Te rog sa-mi spui orice nelamuriri, pareri, observatii, critici!
BTW. Chiar mi-a placut sa "pierd" putin timpul prin thread-ul asta si sa trecem prin solutii mai bune si mai rele. Cred ca oricine interesat poate sa le revada, sa invete cate ceva sau sa prinda cate o idee.

Bineinteles, problema ramane deschisa si de ce nu... poate vine cineva cu o solutie mai buna, mai simpla, mai rapida.

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

Re: Draw overlay

Post by mesajflaviu » 12 Nov 2012, 15:32

Arta si precizie. Acum merge bine. Si prima solutie e super OK, atata doar ca daca aplicatia e minimizata, si apoi restaurata, prima data se vede fereastra layer, si pe urma fereastra aplicatiei ... si n-am gasit nici un mesaj pe care sa-l "handluiesc" sa scap de acest comportament ... insa solutia 2 e perfecta ! Cine are acelasi lucru de facut (inclusiv double-buffering), are de invatat daca urmareste acest thread, cu siguranta ...

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

Re: Draw overlay

Post by mesajflaviu » 21 Jan 2013, 11:11

Revin la acest post cu o problema: dezvoltand un pic proiectul de test cu acest excelent mod de desenare, (un CPreviewView extins, zoom la punct fix) am dat peste o comportare ciudata. Am pus pe bitmap niste obiecte fixe: linii, dreptunghiuri, elipse. Insa la zoom nu prea mare (3X ... 5X), aceste obiecte fixe nu raman chiar fixe la scroll, au un o mica oscilatie ... mentionez ca aceste obiecte le desenez pe device context-ul offline, pentru a nu avea flicker:

Code: Select all

	DrawImage(&DrawDC, pDC);
	GetDocument()->Draw(&DrawDC, GetScrollPosition(), m_fZoomFactor);
	DrawOverlay(&DrawDC);
iar desenarea obiectelor :

Code: Select all

void CDrawObj::Draw(CDC* pDC, CPoint ptScroll, float fZoom)
{
	ASSERT_VALID(this);

	LOGBRUSH logBrush;
	logBrush.lbStyle = BS_HOLLOW;
	CBrush brush;
	brush.CreateBrushIndirect(&logBrush);
	CPen pen;
	pen.CreatePen(PS_SOLID, (int)((float)m_nBorder * fZoom), m_crBorder);
	CPen* pOldPen = pDC->SelectObject(&pen);
	CBrush* pOldBrush = pDC->SelectObject(&brush);
	int nPrevBkMode = pDC->SetBkMode(TRANSPARENT);

	CPoint ptStart(0, 0);
	CPoint ptEnd(0, 0);

	int x = (int)((float)m_ptStart.x * fZoom);
	int y = (int)((float)m_ptStart.y * fZoom);
	ptStart = CPoint(x, y);
	x = (int)((float)m_ptEnd.x * fZoom);
	y = (int)((float)m_ptEnd.y * fZoom);
	ptEnd = CPoint(x, y);

	ptStart -= ptScroll;
	ptEnd -= ptScroll;

	switch(m_nType)
	{
	case SHAPE_LINE:
		pDC->MoveTo(ptStart);
		pDC->LineTo(ptEnd);
		break;
	case SHAPE_ELIPSE:
		pDC->Ellipse(CRect(ptStart, ptEnd));
		break;
	default:
		pDC->Rectangle(CRect(ptStart, ptEnd));
		break;
	}
	pDC->SelectObject(pOldPen);
	pDC->SelectObject(pOldBrush);
	pDC->SetBkMode(nPrevBkMode);
}
Se poate vedea cel mai bine aceasta oscilatie a obiectelor fixe in aplicatia test atasata, cu bitmap-ul creat in resurse (Ctrl+New). Obiectele fixe se pot genera din meniul Edit, Generate objects. Nu am folosit CImageView din exemplul lui Ovidiu, nu pentru ca n-ar fi fost mai elegant, dar pentru o aplicatie test e mai simplu sa implementez offline drawing direct in CMyView.

Ce am observat eu: ca la zoom-uri mari, exista situatii cand desi user-ul actioneaza scroll-ul, sursa bitmap-ului pentru desenarea offline ramane aceeasi (in acest caz si destinatia bitmap-ului ramane aceeasi), caz in care am incercat sa nu desenez aceste obiecte fixe, degeaba, aveam aceeasi oscilatie a acestor obiecte ...
Intrebarea mea este, cum s-ar putea desena aceste obiecte fixe pe bitmap, in interiorul DC-ului offline, sincron cu bitmap-ul ? Am mai incercat sa folosesc CDC::DPtoLP pentru a converti pozitia m_ptStart si m_ptEnd a obiectelor in logical point, dar e totuna.
Attachments
TestDraw10.zip
(249.28 KiB) Downloaded 346 times
Last edited by mesajflaviu on 23 Jan 2013, 15:36, edited 2 times in total.

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

Re: Draw overlay

Post by mesajflaviu » 21 Jan 2013, 14:48

Am incercat sa desenez obiectele fixe in CDC offline setand viewport-ul original:

Code: Select all

	DrawDC.SetViewportOrg(ptPrevViewportOrg);
	GetDocument()->Draw(&DrawDC, m_fZoomFactor);
	DrawDC.SetViewportOrg(CPoint(0, 0));
	DrawOverlay(&DrawDC);
acelasi rezultat ...
am modificat scroll-ul pe 32 de biti, inspirat de aici, la fel, obiectele nu sant stabile pe bitmap ... mai sap ...

Post Reply