Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

How to substitute CPrintDialogEx for CPrintDialog?

275 views
Skip to first unread message

Gaute

unread,
Mar 27, 2008, 5:19:43 PM3/27/08
to
Before Vista the CPageSetupDialog had a button for printer selection:
http://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=278409

I looked at Notepad in Vista and I think it uses the newer CPrintDialogEx
that let us switch printer without printing by using the Apply button in the
Print dialog.

I want to do the same in my application but it seems very hard to make MFC
use the newer CPrintDialogEx with the Apply button. I found this 4,5 year
old thread discussing this:
http://www.themssforum.com/MFC/substitute-CPrintDialogEx/

Is there a solution now? (I can use the latest MFC version if it helps)

Best regards from Gaute


Dan Bloomquist

unread,
Mar 27, 2008, 6:03:15 PM3/27/08
to

Like the link says, the MFC printing loop operates with the old dialog.
I have a global, BOOL DoPreparePrinting( CPrintInfo* pInfo ) that I can
call from from the view member. In pInfo->m_lpUserData I have a
CPrintDialogEx created on the heap. In this call I take care of
associating the data between the the new dialog and the old.

I'll post below. Where the dialog is run you can handle an 'apply -
cancel' and grab the new printer name.

Best, Dan.


BOOL DoPreparePrinting( CPrintInfo* pInfo )
{
ASSERT(pInfo != NULL);
ASSERT(pInfo->m_pPD != NULL);

if (pInfo->m_pPD->m_pd.nMinPage > pInfo->m_pPD->m_pd.nMaxPage)
pInfo->m_pPD->m_pd.nMaxPage = pInfo->m_pPD->m_pd.nMinPage;

CWinApp* pApp = AfxGetApp();

pInfo->m_pPD->m_pd.nFromPage = (WORD)pInfo->GetMinPage( );
pInfo->m_pPD->m_pd.nToPage = (WORD)pInfo->GetMaxPage( );

CPrintInfoEx* pExInfo= static_cast< CPrintInfoEx* >( pInfo->m_lpUserData );
ASSERT_VALID( pExInfo->pPrintDialog );

CPRINTDIALOGEX& dlg= *pExInfo->pPrintDialog;

dlg.m_hWndOwner= *AfxGetMainWnd( );
dlg.m_pdex.Flags|= PD_ALLPAGES | PD_HIDEPRINTTOFILE | PD_RETURNDC;
dlg.m_pdex.nCopies= 1;
dlg.m_pdex.nMinPage= (WORD)pInfo->GetMinPage( );
dlg.m_pdex.nMaxPage= (WORD)pInfo->GetMaxPage( );
dlg.m_pdex.lpPageRanges= &pExInfo->printRange.front( );
dlg.m_pdex.Flags&= ~( PD_NOPAGENUMS /*| PD_NOPAGENUMS*/ );
dlg.m_pdex.nMaxPageRanges= pExInfo->printRange.size( );

if( ! pInfo->m_bPreview )
{
INT_PTR response= dlg.DoModal( );
if( response != S_OK || dlg.m_pdex.dwResultAction != PD_RESULT_PRINT )
return FALSE; // do not print
}
else if( pInfo->m_pPD->m_pd.hDC == NULL )
{
// call CreatePrinterDC if DC was not created by above
HDC hDC= dlg.CreatePrinterDC( );
if( hDC == NULL )
return FALSE;
pInfo->m_pPD->m_pd.hDC= hDC;
}

ASSERT( dlg.m_pdex.hDC );
if( ! dlg.m_pdex.hDC )
return FALSE;

pInfo->m_pPD->m_pd.hDC= dlg.m_pdex.hDC;
pInfo->m_pPD->m_pd.nFromPage= (int)dlg.m_pdex.nMinPage;
pInfo->m_pPD->m_pd.nToPage= (int)dlg.m_pdex.nMaxPage;

pInfo->m_nNumPreviewPages = pApp->m_nNumPreviewPages;
VERIFY( pInfo->m_strPageDesc.LoadString(AFX_IDS_PREVIEWPAGEDESC ) );
return TRUE;
}

Gaute

unread,
Mar 28, 2008, 6:13:57 AM3/28/08
to
Thank you - this can be a good start.
Where and what do you assign to pInfo->m_lpUserData?

Best regards from Gaute


Dan Bloomquist

unread,
Mar 28, 2008, 12:31:06 PM3/28/08
to
Gaute wrote:
> Thank you - this can be a good start.
> Where and what do you assign to pInfo->m_lpUserData?

This is your member, anything you would like.

struct YourPrintStruct
{
//Your stuff
...
CPrintDialogEx* pPrintDialog;
//This is for the print range object for CPrintDialogEx
std::vector< PRINTPAGERANGE > printRange;

YourPrintStruct( )
...
,pPrintDialog( NULL )
{
printRange.resize( 64 );
}
~YourPrintStruct( )
{
if( pPrintDialog )
delete pPrintDialog;
}
};

And somewhere before you call that ::DoPreparePrinting:

YourPrintStruct* pInfoEx= new YourPrintStruct;
//check and set other stuff
pInfoEx->pPrintDialog=
new CPrintDialogEx( PD_HIDEPRINTTOFILE, this );

//if you have some other printer
SomeSetPrinterCall( ...
&pInfoEx->pPrintDialog->m_pdex.hDevMode,
&pInfoEx->pPrintDialog->m_pdex.hDevNames )

pInfo->m_lpUserData= pInfoEx;

...
It ends up becoming accessible through my print object. In
OnEndPrinting, delete it.

YourPrintStruct* pExInfo= pReport->GetPreviewExInfo( );
//or just cast pInfo->m_lpUserData
//Finish using it
delete pExInfo;

Best, Dan.

Gaute

unread,
Mar 28, 2008, 3:06:09 PM3/28/08
to
Thank you!


Dan Bloomquist

unread,
Mar 28, 2008, 3:41:49 PM3/28/08
to
Gaute wrote:
> Thank you!
>
>
Hay, your welcome! If you start using some of the MS printer examples,
note that some of there calls do:

Function( ..., hDevNames, hDevMode );

Drove me nuts because the problem is not obvious. Make them all conform.

Function( ..., hDevMode, hDevNames );

Best, Dan.

0 new messages