Print preview in explore

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

Print preview in explore

Post by mesajflaviu » 09 Jul 2014, 14:19

Intr-o aplicatie MFC de tip Windows Explorer (in stanga tree, in dreapta view) s-ar putea suprapune prin preview-ul in locul view-ului din dreapta, in momentul cand este selectat un item specific din tree ?
Ideea e ca in view-ul din dreapta am grid-ul lui Chris Maunder, iar in momentul cand selectez un item din tree, as vrea sa am print preview-ul gridului dar nu pe toata aplicatia, ci doar in view-ul din dreapta ... este posibil asa ceva ? Ma gandesc ca dezvoltarea unui CPreviewView nu e suficienta, fiindca framework-ul MFC ascunde aplicatia principala pana este activ print preview-ul standard ...

Atasez o aplicatie de test, orice idee, sugestie (cat de mica) este binevenita (numai sa stiu pe ce drum sa pornesc).
Attachments
TestExplore.zip
(93.08 KiB) Downloaded 266 times
Last edited by mesajflaviu on 09 Jul 2014, 14:54, edited 1 time in total.



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

Re: Print preview in explore

Post by mesajflaviu » 09 Jul 2014, 14:33

Atasez si versiunea demo, care are grid-ul in view.
Attachments
TestExplore.zip
(224.41 KiB) Downloaded 262 times
Last edited by mesajflaviu on 10 Jul 2014, 14:29, edited 2 times in total.

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

Re: Print preview in explore

Post by mesajflaviu » 09 Jul 2014, 15:29

Print preview-ul gridului e rezolvat in modul urmator:

Code: Select all

void CGridCtrl::PrintPreview()
{
	if(m_bPrintPreview)
	{
		AfxGetApp()->m_pMainWnd->SetFocus();
		return;
	}
	CString strWindowTitle;
	strWindowTitle.LoadString(AFX_IDS_APP_TITLE);

	CFrameWnd* pOldFrame=(CFrameWnd*)AfxGetThread()->m_pMainWnd;
	pOldFrame->ShowWindow(SW_HIDE);
	if(! m_pTemplate)
	{
		m_pTemplate = new CSingleDocTemplate(
			IDR_TESTEXTYPE,
			NULL,
			RUNTIME_CLASS(CFrameWnd),
			RUNTIME_CLASS(CViewPrintPreview));
		AfxGetApp()->AddDocTemplate(m_pTemplate);
	}

	CFrameWnd* pFrameWnd = m_pTemplate->CreateNewFrame(NULL, NULL);
	m_bPrintPreview = TRUE;

	m_pTemplate->InitialUpdateFrame(pFrameWnd, NULL, FALSE);

	CViewPrintPreview* pView = (CViewPrintPreview*)pFrameWnd->GetActiveView();
	pView->m_pCtrl = this;
	pView->m_pOldFrame = pOldFrame;

	AfxGetApp()->m_pMainWnd = pFrameWnd;
	pFrameWnd->SetWindowText(_T("Print Preview"));
	pFrameWnd->ShowWindow(SW_SHOWMAXIMIZED);
	pView->OnFilePrintPreview();
}
e interesanta rezolvarea, dar nu stiu cum s-ar aplica in cazul cand as vrea acest print preview in view-ul explorerului ...

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

Re: Print preview in explore

Post by mesajflaviu » 11 Jul 2014, 15:00

Sa derivez CRightView din CPreviewView nu e solutie, fiindca CPreviewView cere m_pOrigView, ma gandesc sa refac CPreviewView dar cu informatiile printerului default ... pana acum am reusit sa fac background-ul ca si cel din print preview :D ...
Attachments
TestExplore.zip
(222.15 KiB) Downloaded 288 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 » 13 Jul 2014, 19:17

Code: Select all

class CTestExploreView : public CListView
{
    // ...
    CGridCtrl* m_pGridCtrl;
    // ...
};
1. Avem o clasa derivata din CListView care tine in ea un CGridCtrl. Ori, minunatul grid cu care Chris Maunder a incantat generatii de MFC-isti, :) n-are nici in clin nici in maneca cu controlul Windows predefinit listvew (SysListView32), care este tinut de catre clasa CListView. Daca vreun coleg de-al tau ar incerca sa apeleze metode din CListCtrl (dupa un CListView::GetListCtrl), ar avea neplacuta surpriza ca in cel mai bun caz nu se va intampla nimic. Sa te tii atunci sughituri... :)
In consecinta, e mai corect si mai clar sa derivezi din CView.

2. E destul de peste mana sa faci CGridCtrl copil intre-un view apoi sa ai grija de el sa-l creezi, sa-l redimensionezi, sa ai grija sa nu flicare s.a.m.d. pana sa-l distrugi. Mai mult, e peste mana sa faci print preview.
Poti (si cred ca nu s-ar supara Chris pentru atata lucru) sa-i transformi controlul intr-un view.
Cum? Simplu, derivandu-l din CCtrlView.
Ceva de genul:

Code: Select all

class CGridCtrl : public CCtrlView
{
    // ...
};

CGridCtrl::CGridCtrl(int nRows, int nCols, int nFixedRows, int nFixedCols)
    : CCtrlView(GRIDCTRL_CLASSNAME, AFX_WS_DEFAULT_VIEW)
{
    // ...
}

BEGIN_MESSAGE_MAP(CGridCtrl, CCtrlView)

// in alte apeluri la metodele din clasa de baza, de inlocuit CWnd cu CCtrlView
// in rest, nimic de schimbat.
Mai departe, nu ai decat sa derivezi view-ul aplicatiei tale din CGridCtrl si-ai scapat de-o mie si una de giumbuslucuri.
Exemplu:

Code: Select all

#include "GridCtrl.h"
class CMyCoolView : public CGridCtrl
{
   // ...
   // CGridCtrl* m_pGridCtrl; // <-- get rid of this
   // ...
   // CGridCtrl* GetGridCtrl(){return m_pGridCtrl;} // <-- get rid of this, as well
   // ...and many others.
};

IMPLEMENT_DYNCREATE(CMyCoolView, CGridCtrl)

BEGIN_MESSAGE_MAP(CMyCoolView, CGridCtrl)
// ...

void CMyCoolView::OnInitialUpdate()
{
    CGridCtrl::OnInitialUpdate();

    SetRowCount(10);
    SetColumnCount(10);
    SetFixedRowCount(1);
    SetFixedColumnCount(1);
    SetItemText(1, 1, _T("Ali baba"));
    SetItemText(2, 1, _T("Test"));
    // etc.
}

// ...no need to resize, no need to avoid flicker, no need to handle print preview, etc.
[ to be continued ]

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 » 13 Jul 2014, 20:22

3. Nu-mi pare ok sa dai comanda de Print Preview dintr-un tree. Dintr-un butonel de toolbar sau dialogbar nu-i de-ajuns? Eventual poti sa-l pui intr-un toolbar sau dialog bar in frame-ul child ca sa fie mai la indemana.
In plus la ce-ti trebuie sa faci switch inapoi pe view-ul default daca view-ul de print preview are el insusi un buton pentru aceasta?

4. Print preview-ul din framwork-ul MFC este gandit si implementat in asa fel incat sa stea bine-mersi intr-un frame si nu intr-un pane dintr-un splitter.
Bineiteles, rescriind cod, ai putea sa schimbi asta insa eu cred ca n-are rost.

Daca nu ai si alte motive bine intemeiate eu zic sa renunti la ideea din OP si sa refaci putin design-ul.
Parerea mea. :)

Am atasat proiectul tau, putin modificat in acord cu cele spuse mai sus.
TestExplore.zip
(114.15 KiB) Downloaded 284 times
[later edit]
Am sters din workspace ViewPrintPreview.cpp si ViewPrintPreview.h. Stiu ca tu lucrezi cu VC6.0, asa ca pune-le te rog la loc, ca sa poti compila.

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

Re: Print preview in explore

Post by mesajflaviu » 14 Jul 2014, 09:57

Interesanta abordare ... ma uit un pic sa vad ce si cum ...

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 » 14 Jul 2014, 10:48

Mai kosher ar fi fost sa lasam CGridCtrl asa cum e si sa facem un CGridView derivat din CCtrlView dupa modelul claselor control si view din MFC (ex. CListCtrl si CListView). Insa nu stiu inca din ce motiv nu mi-a mers ieri. Cand o sa am ceva timp o sa incerc si-asa sa vad daca se poate.

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

Re: Print preview in explore

Post by mesajflaviu » 14 Jul 2014, 10:50

E destul de peste mana sa faci CGridCtrl copil intre-un view apoi sa ai grija de el sa-l creezi, sa-l redimensionezi, sa ai grija sa nu flicare s.a.m.d. pana sa-l distrugi. Mai mult, e peste mana sa faci print preview.
Poti (si cred ca nu s-ar supara Chris pentru atata lucru) sa-i transformi controlul intr-un view.
Cum? Simplu, derivandu-l din CCtrlView
E buna ideea, dar aici am o intrebare ... ce se intampla in cazul cand as vrea sa folosesc CGridCtrl-ul derivat din CCtrlView intr-un CFormView ? Pot face asta ? Cum ?

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 » 14 Jul 2014, 10:56

mesajflaviu wrote:
E destul de peste mana sa faci CGridCtrl copil intre-un view apoi sa ai grija de el sa-l creezi, sa-l redimensionezi, sa ai grija sa nu flicare s.a.m.d. pana sa-l distrugi. Mai mult, e peste mana sa faci print preview.
Poti (si cred ca nu s-ar supara Chris pentru atata lucru) sa-i transformi controlul intr-un view.
Cum? Simplu, derivandu-l din CCtrlView
E buna ideea, dar aici am o intrebare ... ce se intampla in cazul cand as vrea sa folosesc CGridCtrl-ul derivat din CCtrlView intr-un CFormView ? Pot face asta ? Cum ?
De asta spuneam mai devreme ca ar fi mai buna o solutie cu CGridCtrl derivat din CWnd si CGridView derivat din CCtrlView. Om vedea...

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 » 14 Jul 2014, 19:51

M-am uitat un pic cu mai atentie.
Ultima solutie nu e fezabila pentru ca, spre deosebire de clasele de controale din MFC (CListCtrl, CTreeCtrl, etc) care au numai metode (in general wrappere pentru mesaje), CGridCtrl are si date membru.
Deci, o fenta gen
CGridCtrl& CGridView::GetGridCtrl() const {return *(CGridCtrl*)this;}
similara cu cele din CListView, CTreeView s.a.m.d. nu mai este ok.

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

Re: Print preview in explore

Post by mesajflaviu » 17 Jul 2014, 14:26

Ma gandesc la ceva ... daca in constructorul clasei CView obtin imprimanta default si device contextul ei, poate as putea (in cazul cand totul e OK bineinteles) desena print preview-ul ... am incercat ceva de genul:

Code: Select all

CTestExploreView::CTestExploreView()
{
	char szPrinterName[MAX_PATH];
	memset(szPrinterName, 0, sizeof(szPrinterName));
	DWORD dwSize = MAX_PATH;
	GetDefaultPrinter(szPrinterName, &dwSize);

	HDC hDC = CreateDC(NULL, szPrinterName, NULL, NULL);
	ASSERT(hDC != NULL);
	m_PrinterDC.FromHandle(hDC);
	ASSERT(m_PrinterDC.GetSafeHdc() != NULL);
}
baiu e ca m_PrinterDC e invali, cu toate ca am o imprimanta default (in Win7) ...

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

Re: Print preview in explore

Post by mesajflaviu » 18 Jul 2014, 13:17

Da, am facut o greseala ... am incercat sa creez un DC din hDC, nu sa atasaz un hDC la m_PrinterDC:

Code: Select all

//m_PrinterDC.FromHandle(hDC); <-- wrong !!!!
m_PrinterDC.Attach(hDC);
ok, acuma avand DC printer-ului, incerc sa desenez ceva in view ... sa vad ce iese ...

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

Re: Print preview in explore

Post by mesajflaviu » 22 Jul 2014, 15:22

Exista vreo posibilitate de a obtine CPrintInfo in constructorul clasei CMyView ?

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

Re: Print preview in explore

Post by mesajflaviu » 23 Jul 2014, 10:11

Cred ca nu se poate obtine CPrintInfo decat in momentul printarii ...
CPrintInfo is a structure and does not have a base class.
The framework creates an object of CPrintInfo each time the Print or Print Preview command is chosen and destroys it when the command is completed

Post Reply