Page 1 of 4

Print preview in explore

Posted: 09 Jul 2014, 14:19
by mesajflaviu
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).

Re: Print preview in explore

Posted: 09 Jul 2014, 14:33
by mesajflaviu
Atasez si versiunea demo, care are grid-ul in view.

Re: Print preview in explore

Posted: 09 Jul 2014, 15:29
by mesajflaviu
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 ...

Re: Print preview in explore

Posted: 11 Jul 2014, 15:00
by mesajflaviu
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 ...

Re: Print preview in explore

Posted: 13 Jul 2014, 19:17
by Ovidiu Cucu

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 ]

Re: Print preview in explore

Posted: 13 Jul 2014, 20:22
by Ovidiu Cucu
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 444 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.

Re: Print preview in explore

Posted: 14 Jul 2014, 09:57
by mesajflaviu
Interesanta abordare ... ma uit un pic sa vad ce si cum ...

Re: Print preview in explore

Posted: 14 Jul 2014, 10:48
by Ovidiu Cucu
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.

Re: Print preview in explore

Posted: 14 Jul 2014, 10:50
by mesajflaviu
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 ?

Re: Print preview in explore

Posted: 14 Jul 2014, 10:56
by Ovidiu Cucu
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...

Re: Print preview in explore

Posted: 14 Jul 2014, 19:51
by Ovidiu Cucu
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.

Re: Print preview in explore

Posted: 17 Jul 2014, 14:26
by mesajflaviu
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) ...

Re: Print preview in explore

Posted: 18 Jul 2014, 13:17
by mesajflaviu
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 ...

Re: Print preview in explore

Posted: 22 Jul 2014, 15:22
by mesajflaviu
Exista vreo posibilitate de a obtine CPrintInfo in constructorul clasei CMyView ?

Re: Print preview in explore

Posted: 23 Jul 2014, 10:11
by mesajflaviu
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