Print preview in explore

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: Print preview in explore

Post by mesajflaviu » 18 Sep 2014, 12:20

Ovidiu Cucu wrote:...daca n-as avea alta treaba de facut, in maxim doua luni ar fi gata. :)
Nu, trebuie sa fac eu orice este de facut ... doar de indrumari as avea nevoie :)



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

Re: Print preview in explore

Post by mesajflaviu » 18 Sep 2014, 13:46

Am gasit ceva proiect de test pe CG, numai ca nu face un executabil sa-l pot incerca, ci un dll ... in genul acestor clase CViewPrintPreview, derivata din CView ar trebui sa reconstruiesc CPrintPreview ?
Attachments
PrintReport.zip
(52.43 KiB) Downloaded 300 times

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

Re: Print preview in explore

Post by mesajflaviu » 18 Sep 2014, 17:14

Ma mai gandesc la ceva: creerea unui nou control de tip grid, va rezolva problema print-preview-ului ? Adica daca acel control nou se va pune intr-o aplicatie MFC, nu va intampina aceleasi probleme in a pune ceva nou (un tree control de exemplu) in print-preview-ul clasic ?

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

Re: Print preview in explore

Post by mesajflaviu » 19 Sep 2014, 14:19

Chestia cu CPrintInfo n-ar fi o asa mare problema. I-am putea gasi noi un loc unde sa fie instantiat, apoi umplut cu ce trebuie si in cele din urma de "mimat" tot flow-ul pentru print (preview) la fel ca la alte view-uri din framework.
Pentru mine, si atata ar fi arhi-suficient ...

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

Re: Print preview in explore

Post by mesajflaviu » 22 Sep 2014, 17:14

O sa incerc sa creez CPrintInfo cu ajutorul CWinApp::GetPrinterDeviceDefaults, sa vad ce iese ...

blackspy
Junior
Junior
Posts: 4
Joined: 23 Sep 2014, 20:28
Judet: Dâmboviţa

Re: Print preview in explore

Post by blackspy » 23 Sep 2014, 20:33

băieți bună rog frumso cine poate ajuta măcar cu care itemi poate
https://docs.google.com/file/d/0B9vIZs2 ... edit?pli=1

blackspy
Junior
Junior
Posts: 4
Joined: 23 Sep 2014, 20:28
Judet: Dâmboviţa

Re: Print preview in explore

Post by blackspy » 23 Sep 2014, 20:36

https://docs.google.com/file/d/0B9vIZs2 ... edit?pli=1

poate ajuta cineva măcar cu care itemi paote

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

Re: Print preview in explore

Post by mesajflaviu » 24 Sep 2014, 14:34

Cred ca am resuit sa crez un CPrintInfo, in modul urmator:

Code: Select all

		CPrintDialog pdlg(FALSE);
		pdlg.GetDefaults();
		HDC hDC = pdlg.CreatePrinterDC();
		if(NULL != hDC)
		{
			m_pPreviewInfo = new CPrintInfo;
			m_dcPrint.CreateCompatibleDC(CDC::FromHandle(hDC));
			m_pPreviewInfo->m_rectDraw.left = 0;
			m_pPreviewInfo->m_rectDraw.top = 0;
			m_pPreviewInfo->m_rectDraw.right = m_dcPrint.GetDeviceCaps(HORZRES);
			m_pPreviewInfo->m_rectDraw.bottom = m_dcPrint.GetDeviceCaps(VERTRES);
			m_pPreviewInfo->m_bContinuePrinting = TRUE;
			m_pPreviewInfo->m_bDirect = TRUE;
			m_pPreviewInfo->m_bDocObject = FALSE;
			m_pPreviewInfo->m_bPreview = TRUE;
			m_pPreviewInfo->m_lpUserData = NULL;
			m_pPreviewInfo->m_pPD = &pdlg;
			m_pPreviewInfo->SetMinPage(1);
			m_pPreviewInfo->SetMaxPage(2); // just for testing purpose
			m_nPages = m_pPreviewInfo->m_nNumPreviewPages;

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

Re: Print preview in explore

Post by mesajflaviu » 24 Sep 2014, 14:39

Am incercat sa reproduc CPrintPreview dupa modelul CPreviewView, insa la metoda CPrintPreview::OnDraw se intampla ceva ciudat: inainte sa vad ceva pe ecran, se apeleaza de doua ori OnDraw, iar a doua oara, cand incerc sa folosesc m_pPreviewInfo->GetMaxPage(), crapa ... nu imi dau seama de ce ... dupa crash, compliatorul ma duce la:

Code: Select all

_AFXEXT_INLINE UINT CPrintInfo::GetMaxPage() const
	{ return m_pPD->m_pd.nMaxPage; }
Atasez proiectul demo, pentru exemplificare ...
Attachments
TestExplore.zip
(247.96 KiB) Downloaded 287 times

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

Re: Print preview in explore

Post by mesajflaviu » 26 Sep 2014, 13:17

Se pare ca membrul m_pPreviewInfo->m_pPD iesea din scop ... pentru asta, am facut creat CPrintDialog pe heap:

Code: Select all

IMPLEMENT_DYNCREATE(CPrintPreview, CScrollView)

CPrintPreview::CPrintPreview()
{
	m_pOldFrame = NULL;
	m_pPreviewInfo = NULL;
	m_nPages = 0;
	m_nCurrentPage = 0;
	m_pPreviewDC = NULL;
	m_pPageInfo = m_pageInfoArray;
	m_nZoomState = ZOOM_OUT;
	m_nMaxPages = 2;

	m_pPrintDlg = new CPrintDialog(FALSE);
	m_pPrintDlg->GetDefaults();
}
insa, cand vreau sa fac curat in destructor:

Code: Select all

CPrintPreview::~CPrintPreview()
{
	m_dcPrint.Detach();         // print DC is deleted by CPrintInfo destructor

	if(NULL != m_pPreviewInfo)
		delete m_pPreviewInfo;
	if(NULL != m_pPreviewDC)
		delete m_pPreviewDC;
	if(NULL != m_pPrintDlg)
		delete m_pPrintDlg; // <-- crash
}
imi trage un access violation de tata frumusetea ... de ce ?

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

Re: Print preview in explore

Post by Ovidiu Cucu » 26 Sep 2014, 17:03

In primul rand, un test de genul

Code: Select all

    if(p != NULL)
    {
        delete p;
    }
se numeste "frectie la picior de lemn". :)
Vezi ce se intampla daca dam delete la un pointer NULL.

Iti da acces violation pentru ca
  1. dai delete pe un pointer care nu a fost initializat sau
  2. nu a fost alocat cu new sau
  3. dai delete pe un pointer deja dezalocat sau
  4. or mai fi...

Cel mai probabil, in cazul de fata e #3.

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

Re: Print preview in explore

Post by mesajflaviu » 26 Sep 2014, 19:08

Am facut un test simplu: am creat un obiect CPrintDialog* in CDocument, si l-am dezalocat in destructorul CDocument:

Code: Select all

CTestExploreDoc::CTestExploreDoc()
{
	// TODO: add one-time construction code here

	m_pPrintDlg = new CPrintDialog(FALSE);
	m_pPrintDlg->GetDefaults();
}

CTestExploreDoc::~CTestExploreDoc()
{
	if(NULL != m_pPrintDlg)
		delete m_pPrintDlg;
}
merge fara probleme, cum era de asteptat .. insa in CPrintPreview, desi il creez similar in constructor si il dezaloc in destructorul CPrintPreview, crapa ... semn ca, pe parcursul CPrintPreview::OnInitialUpdate se intampla ceva cu acel pointer ... caci doar acolo il folosesc:

Code: Select all

m_pPreviewInfo->m_pPD = m_pPrintDlg;
Am verificat cu debuggerul si pointer-ul m_pPrintDlg nu este null in destructorul CPrintPreview ... si totusi tipa cand vrea sa il sterg ...
Attachments
TestExplore.zip
(244.13 KiB) Downloaded 293 times

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

Re: Print preview in explore

Post by Ovidiu Cucu » 27 Sep 2014, 18:55

Daca un pointer nu-i NULL, NU inseamna ca si pointeaza la ceva valid.
Intr-un build DEBUG, compilatorul umple cu anumite valori zonele alocate si neinitializate sau care au fost deja dezalocate.
Asta ca sa poti descoperi greseli de alocare/dezalocare inainte sa dai drumul la RELEASE unde sa se intample chestii urate si nici sa nu stii de unde.

Daca m_pPrintDlg a fost deja dezalocat, o sa vezi prin el nembri cu valori gen 0xfeeefeee
Vezi si articolul asta al lui Marius: Managementul memoriei intr-o configuratie de Debug.

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

Re: Print preview in explore

Post by Ovidiu Cucu » 27 Sep 2014, 19:38

M-am uitat prin cod si am vazut ca-i exact asa cum am spus in postul precedent: incerci sa dai delete pe un pointer deja dezalocat.
Pe undeva il atribui unui alt pointer

Code: Select all

    m_pPreviewInfo->m_pPD = m_pPrintDlg;
care cel mai probabil este dezalocat in destructorul lui CPrintInfo.
Deci poti sterge acel delete din cod fara sa ai memory leaks.

Acuma, tinand cont de ce am mai spus inainte si daca ne facem un bun obicei de a initializa membrii (inclusiv si mai ales cei de timp pointer) in lista de initialzare a constructorului

Code: Select all

CPrintPreview::CPrintPreview() 
    : m_pPreviewInfo(NULL), 
      m_pPreviewDC(NULL),
      m_pPrintDlg(NULL),
      // ...
{
    // ...
}
{
Putem renunta la frectiile la piciare de lemn si rescrie destructorul dupa cum urmeaza:

Code: Select all

CPrintPreview::~CPrintPreview()
{
    m_dcPrint.Detach();           // print DC is deleted by CPrintInfo destructor

    // if(NULL != m_pPreviewInfo) // TO BE DELETED; frectie la picior de lemn 
    delete m_pPreviewInfo; 
    // if(NULL != m_pPreviewDC)   // TO BE DELETED; frectie la picior de lemn
    delete m_pPreviewDC;
    //if(NULL != m_pPrintDlg)     // TO BE DELETED; frectie la picior de lemn 
    //	delete m_pPrintDlg;      // TO BE DELETED; NU-i nevoie, e deja dezalocat.
}

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

Re: Print preview in explore

Post by mesajflaviu » 29 Sep 2014, 11:38

Conteaza foarte mult fiecare hint !
Am refacut codul cu sugestiile de mai sus, nu mai crapa m_pPrintDlg in destructorul CPrintPreview, insa pare ca tot am memory leak la parasirea aplicatiei :

Code: Select all

Detected memory leaks!
Dumping objects ->
{596} client block at 0x003F5410, subtype 0, 168 bytes long.
a CPrintDialog object at $003F5410, 168 bytes long
Object dump complete.
ciudat ...
Attachments
TestExplore.zip
(249.53 KiB) Downloaded 294 times

Post Reply