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

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.
Václav JedličkaAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

ZoppoCommented:
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

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
Václav JedličkaAuthor Commented:
Thanks!
Vaclav
Václav JedličkaAuthor 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
Active Protection takes the fight to cryptojacking

While there were several headline-grabbing ransomware attacks during in 2017, another big threat started appearing at the same time that didn’t get the same coverage – illicit cryptomining.

ZoppoCommented:
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.
Václav JedličkaAuthor Commented:
There are many pages there. This code is for printing just the current page.
ZoppoCommented:
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
Václav JedličkaAuthor Commented:
Thank you very much!
Vaclav
ZoppoCommented:
You're welcome, I'm glad I could help ...

Have a nice weekend,

best regards,

ZOPPO
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Microsoft Applications

From novice to tech pro — start learning today.