Problem in using Fromhandle Function
-
Hi, i am saving a HDC in one fuction of a class by using the following code
MyClass::MyFunction() { CDC dc; AfxGetApp()->CreatePrinterDC(dc); m_Hdc = dc.GetSafeHdc( ); dc.Detach(); }
Now in some other classes i am Creating a CDC class objcet using this HDC.CDC *pDC = CDC::FromHandle(MyClasss::getMyHDC());
But some time it is causing my application to crash. But if i replace FromHandle() by Attach() and detach() the application is working fine. So, i just want to know whether it is safe to use FromHandle() or not. If not should i replace all my FromHandle() by Attach and detach. Thanks Ashwani -
Hi, i am saving a HDC in one fuction of a class by using the following code
MyClass::MyFunction() { CDC dc; AfxGetApp()->CreatePrinterDC(dc); m_Hdc = dc.GetSafeHdc( ); dc.Detach(); }
Now in some other classes i am Creating a CDC class objcet using this HDC.CDC *pDC = CDC::FromHandle(MyClasss::getMyHDC());
But some time it is causing my application to crash. But if i replace FromHandle() by Attach() and detach() the application is working fine. So, i just want to know whether it is safe to use FromHandle() or not. If not should i replace all my FromHandle() by Attach and detach. Thanks Ashwaniashtwin wrote:
CDC *pDC = CDC::FromHandle(MyClasss::getMyHDC());
Are you storing the pDC beyond a function call, CDC::FromHandle returns a temporary CDC object if HDC is not already attached. CDC::DeleteTempMap will delete the temporary CDC objects in idle processing. so if you using the object beyond a function call and there by alowing the idle processing to delete the object, application can crash if you access the temp object. CDC::FromHandle() is less error-prone in the sense you do not have to remember to "detach". but remember it is used only in immediate processing. In your MyClass::MyFunction(), you are Detaching the CDC, so it is sure that FromHandle creates temp map object, and possibly you are storing beyond a function call. I suggest you to Keep attached the Printer DC with a member variable CDC and use it everywhere or use attach detach you should match the two calls then, or use FromHandle but with in a function call. If the frequency of the call is high reduce the number of attach - detach.
modified on Friday, March 14, 2008 8:50 AM
-
ashtwin wrote:
CDC *pDC = CDC::FromHandle(MyClasss::getMyHDC());
Are you storing the pDC beyond a function call, CDC::FromHandle returns a temporary CDC object if HDC is not already attached. CDC::DeleteTempMap will delete the temporary CDC objects in idle processing. so if you using the object beyond a function call and there by alowing the idle processing to delete the object, application can crash if you access the temp object. CDC::FromHandle() is less error-prone in the sense you do not have to remember to "detach". but remember it is used only in immediate processing. In your MyClass::MyFunction(), you are Detaching the CDC, so it is sure that FromHandle creates temp map object, and possibly you are storing beyond a function call. I suggest you to Keep attached the Printer DC with a member variable CDC and use it everywhere or use attach detach you should match the two calls then, or use FromHandle but with in a function call. If the frequency of the call is high reduce the number of attach - detach.
modified on Friday, March 14, 2008 8:50 AM
Hi, Currently i am using the pDC within the same fuction call though i am calling a seperate function to create it which is returning this pDC to the parent function and again from the parent function i am calling a seperate function which has pDC as one of its parameter.
CDC* dc = myPrintObj.createDCForPrint(printRect); doPrintWfReport(dc, printJob);
The Funtion where i am getting the CDC object is as followsCDC* PrintJob::PrintJobToPrinterType::createDCForPrint(const NcWfPrintJob& client, const CRect& printRect) { REQUIRE(!printRect.IsRectEmpty()); DOCINFO DI; ZeroMemory(&DI, sizeof(DOCINFO)); DI.cbSize = sizeof(DOCINFO); DI.lpszDocName = NcCommonResources().getWFReportDocName(); CDC* pDC = CDC::FromHandle(client.getPrintInfo().hDC); pDC->SetMapMode(MM_HIMETRIC); pDC->StartDoc(&DI); pDC->StartPage(); return pDC; }
In the current design it is not possible for me to have a CDC object as a member varaible. Is it OK to use FromHandlePermanent() instead of FromHandle(). Thanks -
Hi, Currently i am using the pDC within the same fuction call though i am calling a seperate function to create it which is returning this pDC to the parent function and again from the parent function i am calling a seperate function which has pDC as one of its parameter.
CDC* dc = myPrintObj.createDCForPrint(printRect); doPrintWfReport(dc, printJob);
The Funtion where i am getting the CDC object is as followsCDC* PrintJob::PrintJobToPrinterType::createDCForPrint(const NcWfPrintJob& client, const CRect& printRect) { REQUIRE(!printRect.IsRectEmpty()); DOCINFO DI; ZeroMemory(&DI, sizeof(DOCINFO)); DI.cbSize = sizeof(DOCINFO); DI.lpszDocName = NcCommonResources().getWFReportDocName(); CDC* pDC = CDC::FromHandle(client.getPrintInfo().hDC); pDC->SetMapMode(MM_HIMETRIC); pDC->StartDoc(&DI); pDC->StartPage(); return pDC; }
In the current design it is not possible for me to have a CDC object as a member varaible. Is it OK to use FromHandlePermanent() instead of FromHandle(). ThanksDo you have FromHandlePermanent for CDC, i think it is for CWnd::FromHandlePermanent.
ashtwin wrote:
Currently i am using the pDC within the same fuction call
I assume this is your new change, and works without crash.
ashtwin wrote:
In the current design it is not possible for me to have a CDC object as a member varaible
why it is not possible, in createDCForPrint why don't you attach the printer DC to a member variable CDC::Attach and when you done printing you can call cleanup function like DeleteDCForPrint and detach and delete the DC stored in member variable. If you are using the DC within the function call as said above it is ok, make sure the idle processing which deletes the temp DC object not allowed to execute in between.
-
Do you have FromHandlePermanent for CDC, i think it is for CWnd::FromHandlePermanent.
ashtwin wrote:
Currently i am using the pDC within the same fuction call
I assume this is your new change, and works without crash.
ashtwin wrote:
In the current design it is not possible for me to have a CDC object as a member varaible
why it is not possible, in createDCForPrint why don't you attach the printer DC to a member variable CDC::Attach and when you done printing you can call cleanup function like DeleteDCForPrint and detach and delete the DC stored in member variable. If you are using the DC within the function call as said above it is ok, make sure the idle processing which deletes the temp DC object not allowed to execute in between.
-
Sorry, u r right CDC don't have FromHandlePermanent(). Now the question is whether we can return a temporary object pointer from a function or not? Thanks Ashwani
ashtwin wrote:
Now the question is whether we can return a temporary object pointer from a function or not?
That i answered repeatedly, if you are sure the idle processing is not allowed to execute that is used CDC within a function callstack which is running in the same thread as of the Message loop ad you are not doing windows message processing in between.
-
ashtwin wrote:
Now the question is whether we can return a temporary object pointer from a function or not?
That i answered repeatedly, if you are sure the idle processing is not allowed to execute that is used CDC within a function callstack which is running in the same thread as of the Message loop ad you are not doing windows message processing in between.
-
Ok, thanks. I think dc.StartDoc; is the culprit. Because after prompting Save as dialogue the system will become idle and temporary objects are getting deleted during this call only.
Then what about returning an object which is attached using CDC::Attach not CDC::FromHandle.
CDC *CreatePrinterDC()
{
....
CDC *pdcPrinter = new CDC;
pdcPrinter ->Attach(hdcPrinter);
....
return pdcPrinter;
}clean up
delete pdcPrinter;
in main function;
-
Then what about returning an object which is attached using CDC::Attach not CDC::FromHandle.
CDC *CreatePrinterDC()
{
....
CDC *pdcPrinter = new CDC;
pdcPrinter ->Attach(hdcPrinter);
....
return pdcPrinter;
}clean up
delete pdcPrinter;
in main function;