From: Joseph M. Newcomer on
Which does require that at some point you have to explicitly release the DC. Generally, I
find that the DC is transient, so I rarely do this. I want it to go away when I leave
scope.
joe
On Fri, 28 Jul 2006 10:55:49 -0700, "David Ching" <dc(a)remove-this.dcsoft.com> wrote:

>
>"Joseph M. Newcomer" <newcomer(a)flounder.com> wrote in message
>news:odikc257ni90u0me7vbo41hdntsqa3p7bf(a)4ax.com...
>> CDC dc;
>> dc.Attach(handle_of_dc)
>>
>> when the CDC leaves scope, the DC will be released.
>> joe
>>
>
>Or:
>
>CDC *pDC = CDC::FromHandle (handle_of_dc);
>
>-- David
>
Joseph M. Newcomer [MVP]
email: newcomer(a)flounder.com
Web: http://www.flounder.com
MVP Tips: http://www.flounder.com/mvp_tips.htm
From: David Ching on
"Joseph M. Newcomer" <newcomer(a)flounder.com> wrote in message
news:e27oc2lke5f10l1qn88hhjfuo7uoc9ccr5(a)4ax.com...
> Which does require that at some point you have to explicitly release the
> DC. Generally, I
> find that the DC is transient, so I rarely do this. I want it to go away
> when I leave
> scope.

Hmm, the doc says:

"The pointer may be temporary and should not be stored beyond immediate use.
Returns a pointer to a CDC object when given a handle to a device context.
If a CDC object is not attached to the handle, a temporary CDC object is
created and attached."

I've never manually released any pointers returned from the FromHandle()
methods for GDI objects, and the doc seems to imply that it is an error to
do so.

-- David





From: Joseph M. Newcomer on
It is indeed temporary, however, "immediate use" is subject to interpretation. For
example, suppose I did

CDC * CMyView::GetPrinterDC() ;

then the temporary CDC * pointer is returned, and I still have to release the DC at some
later point. So the "lifetime" of the CDC * object exceeds a local scope (the
GetPrinterDC call)

When you bind an object to a temporary object, when the temporary object is freed, the
original kernel object is not touched. So if you have a

CWnd * f = CWnd::GetFocus()

it can return a temporary CWnd pointer. The HWND has a potential existence beyond the
lifetime of the CWnd * object, and therefore destroying the window will be an error. But
the same applies if you do

CBitmap * bmp = CBitMap::FromHandle(h);

where h is a bitmap handle. When the temporary CBitmap* object is freed, the HBITMAP is
not disturbed. If you planned to free the HBITMAP also, it didn't happen. OTOH, if you
do

CBitmap bmp;
bmp.Attach(h);

then when the variable bmp leaves scope, the associated HBITMAP is deleted. So the
question is, who has responsibility for the lifetime of the kernel object? If you do,
then you must delete it, because it won't be deleted when a temporary object is freed
during the OnIdle processing (the temporary object is seen as a proxy for the kernel
object, which must remain untouched).

In this case, when the DC is explicitly created and attached, someone has to know when to
delete it. This adds a burden to the programmer, who then must worry about other possible
aliases that may have been generated and which might still be in use, which is why it
isn't really a good idea to use FromHandle. Unfortunately, this isn't done with smart
pointers, which would have their own problems for long-lived objects (e.g., a window DC or
an HWND which otherwise would have no other CWnd * objects)

You don't delete the CDC * object, you delete the DC itself, which is what I was referring
to.

See the example shown under CPrintDialog::GetPrinterDC, which explicitly illustrates the
need to delete the DC.
joe

On Sun, 30 Jul 2006 20:53:24 GMT, "David Ching" <dc(a)remove-this.dcsoft.com> wrote:

>"Joseph M. Newcomer" <newcomer(a)flounder.com> wrote in message
>news:e27oc2lke5f10l1qn88hhjfuo7uoc9ccr5(a)4ax.com...
>> Which does require that at some point you have to explicitly release the
>> DC. Generally, I
>> find that the DC is transient, so I rarely do this. I want it to go away
>> when I leave
>> scope.
>
>Hmm, the doc says:
>
>"The pointer may be temporary and should not be stored beyond immediate use.
>Returns a pointer to a CDC object when given a handle to a device context.
>If a CDC object is not attached to the handle, a temporary CDC object is
>created and attached."
>
>I've never manually released any pointers returned from the FromHandle()
>methods for GDI objects, and the doc seems to imply that it is an error to
>do so.
>
>-- David
>
>
>
>
Joseph M. Newcomer [MVP]
email: newcomer(a)flounder.com
Web: http://www.flounder.com
MVP Tips: http://www.flounder.com/mvp_tips.htm
From: David Ching on

"Joseph M. Newcomer" <newcomer(a)flounder.com> wrote in message
news:k79qc2p15f7ensl4262jvbig0e89r8gref(a)4ax.com...
> So the
> question is, who has responsibility for the lifetime of the kernel object?
> If you do,
> then you must delete it, because it won't be deleted when a temporary
> object is freed
> during the OnIdle processing (the temporary object is seen as a proxy for
> the kernel
> object, which must remain untouched).
>
> See the example shown under CPrintDialog::GetPrinterDC, which explicitly
> illustrates the
> need to delete the DC.

You're right about not using FromHandle() if you are responsible for
deleting the underlying GDI object. The CPrintDialog::GetPrinterDC() doc
doesn't say one way or the other if the returned HDC needs to be deleted. I
couldn't find any example in the MSDN that came with either VC6 or VC2003.

-- David


From: Joseph M. Newcomer on
My example came in the VS.NET 2003 MSDN

CPrintDialog::GetPrinterDC

Retrieves a handle to the printer device context.

HDC GetPrinterDC( ) const;

Return Value
A handle to the printer device context if successful; otherwise NULL.

Remarks
If the bPrintSetupOnly parameter of the CPrintDialog constructor was FALSE (indicating
that the Print dialog box is displayed), then GetPrinterDC returns a handle to the printer
device context. You must call the Windows DeleteDC function to delete the device context
when you are done using it.

Example

CPrintDialog dlg(FALSE);
if (dlg.DoModal() == IDOK)
{
// Get a handle to the printer device context (DC).
HDC hdc = dlg.GetPrinterDC();
ASSERT(hdc);

// Do something with the HDC...

// Clean up.
CDC::FromHandle(hdc)->DeleteDC();
}

On Sun, 30 Jul 2006 23:38:06 GMT, "David Ching" <dc(a)remove-this.dcsoft.com> wrote:

>
>"Joseph M. Newcomer" <newcomer(a)flounder.com> wrote in message
>news:k79qc2p15f7ensl4262jvbig0e89r8gref(a)4ax.com...
>> So the
>> question is, who has responsibility for the lifetime of the kernel object?
>> If you do,
>> then you must delete it, because it won't be deleted when a temporary
>> object is freed
>> during the OnIdle processing (the temporary object is seen as a proxy for
>> the kernel
>> object, which must remain untouched).
>>
>> See the example shown under CPrintDialog::GetPrinterDC, which explicitly
>> illustrates the
>> need to delete the DC.
>
>You're right about not using FromHandle() if you are responsible for
>deleting the underlying GDI object. The CPrintDialog::GetPrinterDC() doc
>doesn't say one way or the other if the returned HDC needs to be deleted. I
>couldn't find any example in the MSDN that came with either VC6 or VC2003.
>
>-- David
>
Joseph M. Newcomer [MVP]
email: newcomer(a)flounder.com
Web: http://www.flounder.com
MVP Tips: http://www.flounder.com/mvp_tips.htm