ble
asked on
CPrintDialog and landscape gives problem
In VC++ 5.0 I use the following code in order to set the printer in landscape mode:
CPrintDialog PrintDialog(FALSE);
//set landscape mode
AfxGetApp()->GetPrinterDev iceDefault s(&PrintDi alog.m_pd) ;
DEVMODE FAR *lpDevMode = (DEVMODE FAR *) ::GlobalLock(PrintDialog.m _pd.hDevMo de);
lpDevMode->dmOrientation = DMORIENT_LANDSCAPE;
::GlobalUnlock(PrintDialog .m_pd.hDev Mode);
if (PrintDialog.DoModal() == IDCANCEL)
return;
After this I do the printing, and everything seems to work fine until I close the application. Then a debug assertion error in winutil.cpp (procedure AfxGlobalFree) occurs.
By commenting out parts I found that the problem lies in the GetPrinterDeviceDefaults. If this is not used there is no problem. I suppose something must be freed, cleared or something like that. Who can help me?
CPrintDialog PrintDialog(FALSE);
//set landscape mode
AfxGetApp()->GetPrinterDev
DEVMODE FAR *lpDevMode = (DEVMODE FAR *) ::GlobalLock(PrintDialog.m
lpDevMode->dmOrientation = DMORIENT_LANDSCAPE;
::GlobalUnlock(PrintDialog
if (PrintDialog.DoModal() == IDCANCEL)
return;
After this I do the printing, and everything seems to work fine until I close the application. Then a debug assertion error in winutil.cpp (procedure AfxGlobalFree) occurs.
By commenting out parts I found that the problem lies in the GetPrinterDeviceDefaults. If this is not used there is no problem. I suppose something must be freed, cleared or something like that. Who can help me?
If you set the hDevMode and/or hDevName members of the PRINTDLG structure to NULL, then the OS will allocate memory for these structures using GlobalAlloc() and return the handles to the memory in the hDevMode and/or hDevName members. It is your responsability to free this memory when it is no monger needed (When done setting up printing.)
ASKER
Yes, but how do I free the memory? I have tried GlobalFree, but that does not help (or I freed the wrong stuff?)
You should use GlobalFree(). Can you post the code? The memory must not be locked when you call GlobalFree().
ASKER
Here is the code:
CPrintDialog PrintDialog(FALSE);
//set landscape mode
AfxGetApp()->GetPrinterDev iceDefault s(&PrintDi alog.m_pd) ;
DEVMODE FAR *lpDevMode = (DEVMODE FAR *) ::GlobalLock(PrintDialog.m _pd.hDevMo de);
lpDevMode->dmOrientation = DMORIENT_LANDSCAPE;
::GlobalUnlock(PrintDialog .m_pd.hDev Mode);
if (PrintDialog.DoModal() == IDCANCEL)
return;
CDC DC;
DC.Attach(PrintDialog.GetP rinterDC() );
//set the document info
DOCINFO di;
CString strTitle;
memset (&di,0,sizeof(DOCINFO));
strTitle.LoadString (AFX_IDS_APP_TITLE);
di.cbSize = sizeof(DOCINFO);
di.lpszDocName = strTitle;
strTitle.Empty();
//start the actual printing
DC.StartDoc (&di);
DC.StartPage ();
DC.TextOut (Xoff,0, _T(PatInfo));
<etc>
DC.EndPage();
DC.EndDoc();
//cleanup
DC.Detach();
DC.DeleteDC();
GlobalFree(PrintDialog.m_p d.hDevMode );
GlobalFree(PrintDialog.m_p d.hDevName s);
CPrintDialog PrintDialog(FALSE);
//set landscape mode
AfxGetApp()->GetPrinterDev
DEVMODE FAR *lpDevMode = (DEVMODE FAR *) ::GlobalLock(PrintDialog.m
lpDevMode->dmOrientation = DMORIENT_LANDSCAPE;
::GlobalUnlock(PrintDialog
if (PrintDialog.DoModal() == IDCANCEL)
return;
CDC DC;
DC.Attach(PrintDialog.GetP
//set the document info
DOCINFO di;
CString strTitle;
memset (&di,0,sizeof(DOCINFO));
strTitle.LoadString (AFX_IDS_APP_TITLE);
di.cbSize = sizeof(DOCINFO);
di.lpszDocName = strTitle;
strTitle.Empty();
//start the actual printing
DC.StartDoc (&di);
DC.StartPage ();
DC.TextOut (Xoff,0, _T(PatInfo));
<etc>
DC.EndPage();
DC.EndDoc();
//cleanup
DC.Detach();
DC.DeleteDC();
GlobalFree(PrintDialog.m_p
GlobalFree(PrintDialog.m_p
I don't see a problem with the two GlobalFree()s. What do they return? (Should return NULL).
Are you setting the document name correctly? I don't think so. It looks like you convert strTitle to a LPCTSTR when you do
di.lpszDocName = strTitle;
That pointer may be invalidated the next time the CString is changed. The next line empties the CString, which may invlidate the pointer (although since it was already empty, it might not in this case, but it still isn't a good practice.)
Are you setting the document name correctly? I don't think so. It looks like you convert strTitle to a LPCTSTR when you do
di.lpszDocName = strTitle;
That pointer may be invalidated the next time the CString is changed. The next line empties the CString, which may invlidate the pointer (although since it was already empty, it might not in this case, but it still isn't a good practice.)
ASKER
The GlobalFree's return NULL.
The problem can not be in the document name (but you are right, something is wrong there). Everything works fine if I don't set the printer in landscape mode. If I comment out the following lines there is no problem.
/* //set landscape mode
AfxGetApp()->GetPrinterDev iceDefault s(&PrintDi alog.m_pd) ;
DEVMODE FAR *lpDevMode = (DEVMODE FAR *) ::GlobalLock(PrintDialog.m _pd.hDevMo de);
lpDevMode->dmOrientation = DMORIENT_LANDSCAPE;
::GlobalUnlock(PrintDialog .m_pd.hDev Mode); */
The problem can not be in the document name (but you are right, something is wrong there). Everything works fine if I don't set the printer in landscape mode. If I comment out the following lines there is no problem.
/* //set landscape mode
AfxGetApp()->GetPrinterDev
DEVMODE FAR *lpDevMode = (DEVMODE FAR *) ::GlobalLock(PrintDialog.m
lpDevMode->dmOrientation = DMORIENT_LANDSCAPE;
::GlobalUnlock(PrintDialog
This is beyond my knowledge of MFC, but what _might_ be happening is that those two handles are initialized by the CPrintDialog. Then you overwrite the handles when you call GetPrinterDeviceDefaults() . So the handles are lost and the memory associated with them can never be deleted. You may be able to verify this by looking at the CPrintDialog constructor. If this is the case, then you need to GlobalFree() the handles before getting the printer defaults.
ASKER
Sorry nietod, but I hope someone else can help me. Thansk for helping so far.
Did you confrm that the handles were not initialized before GetPrinterDeviceDefaults() ?
ASKER
How should the handles be initialized? Must there be someting done between
CPrintDialog PrintDialog(FALSE);
and
AfxGetApp()->GetPrinterDev iceDefault s(&PrintDi alog.m_pd) ;
?
B.T.W. If I press Cancel in the Dialog, no problem occurs, only if I press OK.
CPrintDialog PrintDialog(FALSE);
and
AfxGetApp()->GetPrinterDev
?
B.T.W. If I press Cancel in the Dialog, no problem occurs, only if I press OK.
I meant did the CPrintDialog object initialize the handles. Thus when you do GetPrinterDeviceDefaults() you may be loosing the initialized handles.
ASKER
I don't know if CPrintDialog initializes the handles. How can one tell?
What should then be done to print in landscape mode if I can not call GetPrinterDeviceDefaults?
What should then be done to print in landscape mode if I can not call GetPrinterDeviceDefaults?
ASKER
I found the following code elsewhere:
PrintDialog.m_pd.hDevMode = ::GlobalAlloc( GHND, sizeof(DEVMODE) );
DEVMODE * devMode = (DEVMODE *) ::GlobalLock( PrintDialog.m_pd.hDevMode );
devMode->dmSize = sizeof(DEVMODE);
devMode->dmOrientation = DMORIENT_LANDSCAPE;
devMode->dmFields = DM_ORIENTATION;
::GlobalUnlock( devMode );
This works fine.
PrintDialog.m_pd.hDevMode = ::GlobalAlloc( GHND, sizeof(DEVMODE) );
DEVMODE * devMode = (DEVMODE *) ::GlobalLock( PrintDialog.m_pd.hDevMode );
devMode->dmSize = sizeof(DEVMODE);
devMode->dmOrientation = DMORIENT_LANDSCAPE;
devMode->dmFields = DM_ORIENTATION;
::GlobalUnlock( devMode );
This works fine.
>> I don't know if CPrintDialog initializes the
>> handles. How can one tell?
If the handles are NULL, they are not initialized. If they are not NULL, they probably are initialized. In that case, just step throught the constructor to make sure that it really is initializing them.
>> found the following code elsewhere:
That code allocates the memory rather than making GetPrinterDevicedefaults() do it. Where is that code being placed in relation to GetPrinter...()? Before it, I assume.
>> handles. How can one tell?
If the handles are NULL, they are not initialized. If they are not NULL, they probably are initialized. In that case, just step throught the constructor to make sure that it really is initializing them.
>> found the following code elsewhere:
That code allocates the memory rather than making GetPrinterDevicedefaults()
ASKER
No, GetPrinter.. isn't used anymore.
I see. That is more like the way it is done in non-MFC.
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.