How to preselect "pages" option in the print dialog (MFC)

Václav Jedlička
Václav Jedlička used Ask the Experts™
on
I am trying to customize a print dialog in a MFC app.
I want the "pages" option to be preselected.

In CMyView::OnPreparePrinting(CPrintInfo* pInfo)
I added this at the end of the function:
      pInfo->SetMinPage(10);
      pInfo->SetMaxPage(20);
      pInfo->m_pPD->m_pd.nFromPage = 10;
      pInfo->m_pPD->m_pd.nToPage = 20;
      pInfo->m_pPD->m_nFlags |= PD_PAGENUMS;
      return DoPreparePrinting(pInfo);

When the print dialog comes up, the "all" option is preselected.
Comment
Watch Question

Do more with

Expert Office
EXPERT OFFICE® is a registered trademark of EXPERTS EXCHANGE®
Hi

unfortunately the MFC printing classes are a bit confuzing, the m_nFlags you set is not the correct member (in fact this is a flag in CWnd), you need to set the flag of the used PRINTDLG member like this instead:
pInfo->m_pPD->m_pd.Flags |= PD_PAGENUMS;

Open in new window

Hope this helps,

ZOPPO

Author

Commented:
Thanks!
Vaclav

Author

Commented:
Unfortunately there is still a problem. If the range of pages is just one page, the "pages" option does not get preselected:

      pInfo->SetMinPage(10);
      pInfo->SetMaxPage(10);
      pInfo->m_pPD->m_pd.nFromPage = 10;
      pInfo->m_pPD->m_pd.nToPage = 10;
      pInfo->m_pPD->m_pd.Flags |= PD_PAGENUMS;
      return DoPreparePrinting(pInfo);

It prints correctly page 10, but the print dialog has option "all" selected
Introduction to R

R is considered the predominant language for data scientist and statisticians. Learn how to use R for your own data science projects.

Hm - does this really matter a lot? I mean: why offer two options at all if there's only one page, regardless what options the user can select only that single page can be printed. IMO it would would make more sense to remove the page-selection completeley ...

Beside this: it might be complicated (and probably only possible with huge effort) to change this behavior, this dialog is a common dialog which is created and handled by Windows, to change behavior of this dialog with is not provided by its common implementation is quite hard.

Author

Commented:
There are many pages there. This code is for printing just the current page.
ok, sorry, I missunderstood this because the code you posted indicates there's only one page - the SetMinPage/SetMaxPage functions set the limits of the possible page-range, they don't set a pre-set page-range.

Unfortunateley I found MFC internally pre-sets the limits as default, regardsless of what's set in the appropriate members of PRINTDLG (nFromPage and nToPage are always set to nMinPage and nMaxPage in CView::DoPreparePrinting).

So I think the easiest way to acchieve what you want is to implement your own functionality which displays the dialog as done there, i.e. somehow like this (this is not an original copy of CView::DoPreparePrinting, to make it better readable I cleaned it up a bit, and I added two parameters for the pre-selected page-range ... if you want to know what it does in detail please compare it with the original CView::DoPreparePrinting in the MFC source in viewprnt.cpp somewhere in your Visual Studio path):
BOOL CMyView::MyDoPreparePrinting( CPrintInfo* pInfo, WORD nFrom, WORD nTo )
{
	CPrintDialog* pPD = nullptr == pInfo ? nullptr : pInfo->m_pPD;

	if ( nullptr == pPD )
	{
		ASSERT( 0 );
		return FALSE;
	}

	PRINTDLG& pd = pPD->m_pd;

	pd.nMaxPage = max( pd.nMinPage, pd.nMaxPage );
	
	CWinApp* pApp = AfxGetApp();

	if ( pInfo->m_bPreview || pInfo->m_bDirect || ( pInfo->m_bDocObject && !( pInfo->m_dwFlags & PRINTFLAG_PROMPTUSER ) ) )
	{
		if (pd.hDC == NULL)
		{
			if ( !pApp->GetPrinterDeviceDefaults( &pd ) )
			{
				if ( !pInfo->m_bDocObject || ( pInfo->m_dwFlags & PRINTFLAG_MAYBOTHERUSER ) )
				{
					if ( pApp->DoPrintDialog( pPD ) != IDOK )
					{
						return FALSE;
					}
				}
			}

			if ( pd.hDC == NULL )
			{
				if ( pPD->CreatePrinterDC() == NULL )
				{
					return FALSE;
				}
			}
		}

		pd.nFromPage = nFrom;
		pd.nToPage = nTo;
	}
	else
	{
		pd.nFromPage = nFrom;
		pd.nToPage = nTo;

		if ( IDOK != pApp->DoPrintDialog( pPD ) )
		{
			return FALSE;
		}
	}

	if ( nullptr == pd.hDC )
	{
		ASSERT( 0 );
		return FALSE;
	}

	pInfo->m_nNumPreviewPages = pApp->m_nNumPreviewPages;
	ENSURE( pInfo->m_strPageDesc.LoadString( AFX_IDS_PREVIEWPAGEDESC ) );

	return TRUE;
}

BOOL
CMyView::OnPreparePrinting( CPrintInfo* pInfo )
{
	pInfo->SetMinPage( 1 );
	pInfo->SetMaxPage( 100 );

	// we need to pass the wanted page-range since there are cases where they are not set in MyDoPreparePrinting, i.e. when opening a print-preview
	return MyDoPreparePrinting( pInfo, 10, 10 );
}

Open in new window

Hope this helps,

ZOPPO

Author

Commented:
Thank you very much!
Vaclav
You're welcome, I'm glad I could help ...

Have a nice weekend,

best regards,

ZOPPO

Do more with

Expert Office
Submit tech questions to Ask the Experts™ at any time to receive solutions, advice, and new ideas from leading industry professionals.

Start 7-Day Free Trial