OnPaint si OnDraw

Intrebari legate de programarea cu biblioteci precum MFC, ATL, WTL si GDI+.
User avatar
Zeros
Membru
Membru
Posts: 54
Joined: 12 Jul 2007, 12:34
Location: Waslooy

OnPaint si OnDraw

Post by Zeros » 02 Nov 2007, 12:18

Cer scuze pentru titlul anterior (Bug in MFC).
Acum invat si eu mfc si mai ales sa nu dau vina pe altii. :D

Pina la urma am facut asa si merge!!!

Code: Select all

void CXyzDlg::OnPaint() 
{
	if (IsIconic())
	{
		CPaintDC dc(this); // device context for painting

		SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);

		// Center icon in client rectangle
		int cxIcon = GetSystemMetrics(SM_CXICON);
		int cyIcon = GetSystemMetrics(SM_CYICON);
		CRect rect;
		GetClientRect(&rect);
		int x = (rect.Width() - cxIcon + 1) / 2;
		int y = (rect.Height() - cyIcon + 1) / 2;

		// Draw the icon
		dc.DrawIcon(x, y, m_hIcon);
	}
	else
	{
		// CDialog::OnPaint();
		CPaintDC dc(this);
      		dc.Rectangle(10,10,100,50);
	}
}
Mai am totusi o intrebare.
Am facut si o aplicatie 'multiple documents' si am cautat OnPaint dar n-am gasit. In schimb am reusit sa desenez dreptunghiul in OnDraw

Code: Select all

void CZzzView::OnDraw(CDC* pDC)
{
	CZzzDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);
	// TODO: add draw code for native data here

	pDC->Rectangle(10,10,100,50);
}
De ce la CXyzDlg e OnPaint iar la CZzzView e OnDraw?
Sper sa nu fie chiar asa de stupida intrebarea si mai pun una: la ce foloseste CZzzDoc* pDoc = GetDocument();?


V-am pupat! :-)

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

Re: OnPaint si OnDraw

Post by Ovidiu Cucu » 02 Nov 2007, 13:00

Scuzele au fost acceptate... :D

Sa le luam pe rand:
#1.
OnPaint picteaza iar OnDraw deseneaza... :D (well, a fost doar o gluma, forget it! ;))

OnPaint este functia handler pentru mesajul WM_PAINT pe care probabil ti-a mapat-o AppWizard-ul sau poti sa o mapez si singur "cu mana" sau cu ClassWizard la VS6.0 sau din property list la VS2005.
In cod arata cam asa:

Code: Select all

// MYDIALOG.H
class CMyDialog : public CDialog
{
// ...
   afx_msg void OnPaint();
// ...
};

// MYDIALOG.CPP
BEGIN_MESSAGE_MAP(CMyDialog, CDialog)
   //...
   ON_WM_PAINT()
//...
void CMyDialog::OnPaint() 
{
   // ...drawing code here... 
}
Toate peste toate cand dialogul primeste WM_PAINT se apeleaza CMyDialog::OnPaint in care poti sa desenezi ce vrea muschii tai.

La CView, functia OnDraw este o functie virtuala care se apeleaza din handlerul lui WM_PAINT. Daca arunci un ochi in implementarea din MFC a lui CView vei gasi ceva de genul

Code: Select all

// AFXWIN.H
class CView : public CWnd
{
// ...
   virtual void OnDraw(CDC* pDC) = 0;
// ...
   afx_msg void OnPaint();
// ...
};

Code: Select all

// VIEWCORE.CPP

BEGIN_MESSAGE_MAP(CView, CWnd)
   // ...
   ON_WM_PAINT()
   //...

void CView::OnPaint()
{
   // standard paint routine
   CPaintDC dc(this);
   OnPrepareDC(&dc);
   OnDraw(&dc);
}

void CView::OnDraw(CDC*)
{
}
Bineinteles, poti mapa tu direct WM_PAINT in clasa derivata dar "fenta" cu OnDraw te ajuta putin, de exemplu ca-ti da de-a gata acel pointer la DC (device context).


#2.

Code: Select all

CZzzDoc* pDoc = GetDocument();

iti intoarce un pointer la clasa document a aplicatiei tale.

User avatar
Zeros
Membru
Membru
Posts: 54
Joined: 12 Jul 2007, 12:34
Location: Waslooy

Re: OnPaint si OnDraw

Post by Zeros » 02 Nov 2007, 13:06

Ovidiu Cucu wrote: #2.

Code: Select all

CZzzDoc* pDoc = GetDocument();

iti intoarce un pointer la clasa document a aplicatiei tale.
Bine, bine, dar la ce-mi foloseste?
V-am pupat! :-)

User avatar
Hannibal
Membru
Membru
Posts: 104
Joined: 30 Jul 2007, 15:18
Location: Bucuresti
Contact:

Re: OnPaint si OnDraw

Post by Hannibal » 02 Nov 2007, 13:16

Zeros wrote:
Ovidiu Cucu wrote: #2.

Code: Select all

CZzzDoc* pDoc = GetDocument();

iti intoarce un pointer la clasa document a aplicatiei tale.
Bine, bine, dar la ce-mi foloseste?
Cred ca e cea mai tare intrebare de MFC. :biggrin: ( no offence intended).
To help put the document/view creation process in perspective, consider a running program: a document, the frame window used to contain the view, and the view associated with the document.
*A document keeps a list of the views of that document and a pointer to the document template that created the document.
*A view keeps a pointer to its document and is a child of its parent frame window.
*A document frame window keeps a pointer to its current active view.
*A document template keeps a list of its open documents.
*The application keeps a list of its document templates.
*Windows keeps track of all open windows so it can send messages to them.
Multa lume foloseste modelul dar nu prea intelege de ce. E unul din plusurile (pentru unii si in acelasi timp minusurile majore pentru altii ) ale MFC-ului. Pentru explicatii linkurile de mai jos:
- Documents, Views, and the Framework
- Document Templates and the Document/View Creation Process
- Model-view-controller ( pentru ca Document/View este o specializare a MVC-ului in care Document este CDocument si View+Controller se unifica intr-o singura clasa CView)

Si recomand calduros :
- Design patterns
For the End of the World spell, press control, alt, delete.

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

Re: OnPaint si OnDraw

Post by Ovidiu Cucu » 02 Nov 2007, 13:47

Well, eu am sa incerc s-o iau mai babeste si mai pe romaneste, pentru ca oricine deschide prima oara un manual de MFC si da de "Document-View Architecture" ca si de "MDI/SDI Frameworks" are primul impuls de a se lasa de meserie... :D

Deci...
Atunci cand MFC AppWizard-ul iti face "scheletul" pentru o aplicatie SDI sau MDI iti pune urmatoarele clase principale:
  • O clasa aplicatie derivata din CWinAPP. Asta contine in primul rand tot ce-i referitor la threadul principal al aplicatiei cat si alte chestii si setari generale legate de aplicatie.
  • O clasa main frame, derivata din CFrameWnd (pt. SDI) sau din CMDIFrameWnd (pt. MDI). Aceasta incapsuleaza fereastra principala a aplicatiei, cu meniu, cu status bar, cu toolbar etc.
  • La MDI apare in plus frame-ul copil (derivat din CMDIChildWnd).
  • O clasa view (derivata din CView, CScrollView, CEditView, etc...) care se ocupa de afisarea datelor si....
  • ... o clasa document, derivata din CDocument care ce mai poata sa faca altceva decat sa tina datele si sa faca operatiile legate de acestea, cum ar fi serializarea (incarcare/salvare).
N-am pus pe lista Document Templates pentru a nu "complica" deocamdata lucrurile. ;)

Daca respecti "arhitectura" de mai sus (ceea ce din pacate multi nu prea fac, rezultand o aplicatie de te doare capul :)), atunci tii datele in clasa document, pe care le "afisezi" in clasa view, in cazul tau concret, ceva de genul

Code: Select all

class CZzzDoc : public CDocument
{
// Attributes
public:
   int x1, y1, x2, y2;
// ...
};

void CZzzView::OnDraw(CDC* pDC)
{
   CZzzDoc* pDoc = GetDocument();
   ASSERT_VALID(pDoc);

   pDC->Rectangle(pDoc->x1,pDoc->y1,pDoc->x2,pDoc->y2);
   // ...
}
NOTA: E doar un exemplu bazat pe OP, asa ca ii rog pe gurus sa nu critice "design-ul"! :D

Dragos Cojocari
Membru++
Membru++
Posts: 789
Joined: 11 Jul 2007, 14:11

Re: OnPaint si OnDraw

Post by Dragos Cojocari » 02 Nov 2007, 13:50

Zeros wrote:Bine, bine, dar la ce-mi foloseste?
Sper ca am inteles intrebarea. In mod normal view-ul e o reprezentare grafica a documentului. Ca atare ca sa reprezinti documentul ai nevoie de documentul propriu zis.

Asta nu inseamna ca e obligatoriu. Daca tu vrei sa desenezi un patrat de 10x10 tot timpul, evident continutul documentului e irelevant.

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

Re: OnPaint si OnDraw

Post by Ovidiu Cucu » 02 Nov 2007, 13:58

Dragos Cojocari wrote:
Zeros wrote:Bine, bine, dar la ce-mi foloseste?
Asta nu inseamna ca e obligatoriu. Daca tu vrei sa desenezi un patrat de 10x10 tot timpul, evident continutul documentului e irelevant.
De acord, Dragos, dar stii si tu vorba aia "Cine (in MFC) fura azi un ou... maine va fura dupa scheme cool ca asta"... deja ma doare capul! :D ;)

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

Re: OnPaint si OnDraw

Post by Ovidiu Cucu » 02 Nov 2007, 14:15

Well, daca n-ai si n-ai si n-ai nevoie de docoment si desenezi numai patratzele batute-n cuie, atunci tot bunul Wizard te poate ajuta.
Numai ca trebuie sa-i spui din timp scotand bifa de la "Document/View architecture support".

User avatar
Silviu Ardelean
Senior
Senior
Posts: 1175
Joined: 12 Jul 2007, 09:22
Judet: Timiş
Location: Timisoara
Contact:

Re: OnPaint si OnDraw

Post by Silviu Ardelean » 02 Nov 2007, 14:34

Cred ca in momentul in care el va intelege cum e treaba asta cu document si reprezentare lucrurile vor parea mult mai simple...
Atunci va vedea cum, bazandu-se pe conceptul de serializare din document poate incarca/salva date din/in fisiere si le va putea reprezenta in view. Atunci va folosii cu adevarat si GetDocument() pentru a avea acces din view la datele din document.

P.S. Baieti, poate ati observat ca la articolul de serializare s-a schimbat numele. Voi reveni in cadrul acestei luni cu un articol despre serializare in arhitectura Doc/View. ;)

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

Re: OnPaint si OnDraw

Post by Ovidiu Cucu » 02 Nov 2007, 14:44

Silviu wrote: P.S. Baieti, poate ati observat ca la articolul de serializare s-a schimbat numele. Voi reveni in cadrul acestei luni cu un articol despre serializare in arhitectura Doc/View. ;)
Fain! Ar fi timpul sa descalcim putin itele pe aici. ;)



Revenind putin la tabelul cu "MFC Doc/View: How to obtain a pointer to various objects" (pe care l-am dat in link-ul de mai sus).
Am observat ca exista patratele goale, asa ca o sa-l rog pe Andreas sa le completeze.
De exemplu la randul 4 - coloana 4:

Code: Select all

SDI: ((CFrameWnd*)AfxGetMainWnd())->GetActiveView()->GetDocument();
MDI: ((CMDIFrameWnd*)AfxGetMainWnd())->MDIGetActive()->GetActiveView()->GetDocument();
:D :D ;)

User avatar
Silviu Ardelean
Senior
Senior
Posts: 1175
Joined: 12 Jul 2007, 09:22
Judet: Timiş
Location: Timisoara
Contact:

Re: OnPaint si OnDraw

Post by Silviu Ardelean » 02 Nov 2007, 15:05

Ovidiu Cucu wrote:Fain! Ar fi timpul sa descalcim putin itele pe aici. ;)
Voi incerca sa ma tzin de promisiune si pana la sfarsitul lunii sa fie gata treaba (desi voi fi putzin plecat in concediu).
De asemenea, voi incerca sa fac putzina lumina si in privinta arhitecturii doc/view cat si legatura dintre cele doua entintati. ;)

Dragos Cojocari
Membru++
Membru++
Posts: 789
Joined: 11 Jul 2007, 14:11

Re: OnPaint si OnDraw

Post by Dragos Cojocari » 02 Nov 2007, 15:26

Silviu wrote:Voi incerca sa ma tzin de promisiune si pana la sfarsitul lunii sa fie gata treaba (desi voi fi putzin plecat in concediu).
De asemenea, voi incerca sa fac putzina lumina si in privinta arhitecturii doc/view cat si legatura dintre cele doua entintati. ;)
:thumbsup:

User avatar
Zeros
Membru
Membru
Posts: 54
Joined: 12 Jul 2007, 12:34
Location: Waslooy

Re: OnPaint si OnDraw

Post by Zeros » 03 Nov 2007, 10:57

Hannibal wrote:
Cred ca e cea mai tare intrebare de MFC. :biggrin: ( no offence intended).
Asa cum spunea Ovidiu atunci cind deschizi un manual iti vine de multe ori sa-ti iei cimpii. :(
Intrebind e mult mai usor.
Mersi mult la toata lumea!

pifcnt
Junior
Junior
Posts: 1
Joined: 16 Dec 2008, 18:49
Judet: Bucureşti

Re: OnPaint si OnDraw

Post by pifcnt » 16 Dec 2008, 19:17

Da realizez ca sunt cu ani intarziere...dar poate se mai uita cineva pe forumul acesta.

Diferentza intre OnPaint si OnDraw este ca in OnPaint poti sa apelezi legal GetUpdateRgn
sau GetUpdateRect(mai degraba) pentru a obtine regiunea/rectangle-ul care trebuie redesenat.In OnDraw acest lucru nu mai este posibil, asta pentru ca MFC-ul apeleaza constructorul lui CPaintDC care face BeginPaint, care face indisponibila informatia data de GetUpdateRect.

Asa, ca o observatie, implementarea din CView::OnPaint() Nu prea e corecta pentru ca
la http://msdn.microsoft.com/en-us/library ... S.85).aspx
se spune:
A window may receive internal paint messages as a result of calling RedrawWindow with the RDW_INTERNALPAINT flag set. In this case, the window may not have an update region. An application should call the GetUpdateRect function to determine whether the window has an update region. If GetUpdateRect returns zero, the application should not call the BeginPaint and EndPaint functions.
Dupa cum se vede si din sample-ul dat intr-un post anterior, mfc-ul nici macar nu se deranjeaza sa apeleze GetUpdateRect, ce sa mai vorbim de verificat ce intoarce...

User avatar
Silviu Ardelean
Senior
Senior
Posts: 1175
Joined: 12 Jul 2007, 09:22
Judet: Timiş
Location: Timisoara
Contact:

Re: OnPaint si OnDraw

Post by Silviu Ardelean » 16 Dec 2008, 23:23

pifcnt wrote:Da realizez ca sunt cu ani intarziere...dar poate se mai uita cineva pe forumul acesta.
Scuza-ma, as dorii sa ma luminezi si pe mine ce ai vrut sa zici cu ani intarziere...
Multumesc, anticipat.

Post Reply