From: Doug Harrison [MVP] on
On Tue, 13 Apr 2010 09:33:55 +0800, "Bill Brehm" <don't want spam> wrote:

>Yes, I agree. I put it in as a test and to make some progress until I could
>figure out what is going wrong. I dislike timer delays because unless you
>guess perfectly, you are either wasting time or still facing the problem
>that the delay is supposed to be hiding. That's why I asked if the pointer
>that is return cannot be used immediately, how can I tell when it is safe to
>use it?

The pointer can be used immediately unless there is some race condition
with code you're not showing. Actually, I don't know how reliable it is to
call GetDC on a window belonging to another process. It can be dicey even
between threads within the same process.

>I also don't know what the error is. That's why I'm here looking for the
>help of experts with lots of experience. What I know is what I mentioned
>about certain pointers or handles being NULL. Running out of GDI resources
>might be the cause and I will test for that. But it's seems unlikely to me
>that GDI resources would be depleted after fewer calls (not after a shorter
>time) with a 1 msec delay than with a 50 msec delay.

Sleep times are at best approximate. It might be more useful to count the
number of calls you're able to make before it fails, and you need to check
for errors so you know immediately when something fails.

>The help says typically
>that a function returns 0 if error and non zero if success. So 0 only tells
>me there was an error but not what the error was. It also doesn't tell me to
>call GetLastError so I assume it's not updated in this case.

FWIW, the help is only sometimes helpful. It's usually insufficient to read
only the MFC documentation concerning things that are documented by the SDK
as the primary source.

>Okay, thanks. I'll try this. I'd rather not Detach and recreate all the time
>if it's not necessary. But many MFC functions that return a pointer say that
>the pointer is temporary and should not be saved for future use. So I try
>getting a fresh one before I need to use it because I don't know such when a
>pointer will become "stale". Could you please shed some light on that? When
>do these temporary pointers become invalid? Is it a matter of memory being
>swapped out and into a new address? Or control switching out of my thread
>then coming back? Is the underlying bitmap or DC (in this example) stable
>but only the MFC object might not have a stable connection to it (meaning I
>should use the SDK level instead of MFC)?

The temporary MFC objects are deleted during idle-time processing, which is
part of the normal MFC message loop, though IIRC, it doesn't occur while a
dialog box is active. So as a rule of thumb, a temporary MFC object is
usable until the function that obtained it returns, or more correctly (and
dangerously), during the processing of the Windows message under which it
was obtained. The "Create" calls you're making create permanent objects,
which you can reuse to the extent that it makes any sense to reuse them.
The GetDC call may return a temporary object.

To add to what Joe said about the Detach vs. Delete, the CWnd::GetDC
documentation says:

"Unless the device context belongs to a window class, the ReleaseDC member
function must be called to release the context after painting."

That's something else you seem to be forgetting to do. You should call that
function, period. It's at worst unnecessary and harmless. You might want to
go to codeproject.com and look for classes that wrap all this in a more
modern way using the RAII technique. You can probably find one or two to
encapsulate everything you're doing in your function with a single
"SomeMemoryDcClass" variable. Or maybe your function should be a member of
that class named "Update" or something. The initialization and state of
objects of that class will be more complicated since the window you're
interested in belongs to another process and can potentially go away at any
time.

--
Doug Harrison
Visual C++ MVP
From: "Bill" don't want more on
Without actually counting in code, I know that the access fault occurs in
far fewer calls with the 1 msec delay than with the 50 msec delay. I know
because I am calling my grabrect() in an outer loop that calls it 320 times
and with 1 msec the code will fail in the first pass of the loop near the
beginning but with 50 msec it will succeed for several passes through the
loop before failing. But I no longer think it's directly related to the
delay - just indirectly related.

I now know that there are objects being created and not destroyed. I can see
memory usage going up in task manager each time I go through the loop. When
I close the program there are no warnings about leaked memory, so this
memory must be used for something that MFC debugger doesn't track for memory
leaks and the system takes care of destroying them when the program closes.

I believe that the call to GetDC fails when I run out of some kind of
resource. I mentioned before that I was getting both ASSERTS and access
violations. Lately it's only the access violation I'm getting. When it
happens, the window I am copying gets painted on top of my visual studio
window in the upper left corner of the screen. I'm using mouse_event() to
send mouse clicks to the other window so the repaint is probably due to a
mouse click and the incorrect location is probably due to the fact that the
other window is also out of proper resources to do it's painting. A theory
anyway.

I noticed the thing about ReleaseDC after my previous post and added it in.
The problem has not gone away. But I surely have other locations in my code
that GetDC without ReleaseDC, so I have to find and fix them all today
before I know if that solves the problem.

Per Joe's suggestion, I do DeleteObject on the bitmap now. I can't find a
function to DeleteObject for the memoryDC. Is there one or a way? Also, I
saw in DeleteObject help that I shouldn't delete an object that is selected
into a DC. But I can't find a function to unselect the bitmap object out of
the DC. Am I overlooking one or must I just select another object (maybe a
stock object) into the DC?

I'm not sure I have a good mental image of what is happening with bitmap and
DC classes and instances and objects and handles. Is it correct to imagine
this? Before MFC, these (SDK?) objects were referenced by handles. MFC added
a layer around these objects to allow C++ coding using them. So to use MFC,
there is an instance of the MFC class but still the original windows object.
Attach and detach make and break the connection between these two things via
pointers or lookup tables. Are the original windows objects "stable" in that
they can be referenced by their handle through the life of the program? Is
it only the MFC class instance that might be temporary in that it might be
destructed when it goes out of scope but the windows object referenced by
the handle is still there?

Windows XP for now. Eventually this might run on Windows 2003 server. MSVC++
6.0.


"Doug Harrison [MVP]" <dsh(a)mvps.org> wrote in message
news:ien9s59t0i10cdj9ueodftaa91146tbifl(a)4ax.com...
> On Tue, 13 Apr 2010 09:33:55 +0800, "Bill Brehm" <don't want spam> wrote:
>
>>Yes, I agree. I put it in as a test and to make some progress until I
>>could
>>figure out what is going wrong. I dislike timer delays because unless you
>>guess perfectly, you are either wasting time or still facing the problem
>>that the delay is supposed to be hiding. That's why I asked if the pointer
>>that is return cannot be used immediately, how can I tell when it is safe
>>to
>>use it?
>
> The pointer can be used immediately unless there is some race condition
> with code you're not showing. Actually, I don't know how reliable it is to
> call GetDC on a window belonging to another process. It can be dicey even
> between threads within the same process.
>
>>I also don't know what the error is. That's why I'm here looking for the
>>help of experts with lots of experience. What I know is what I mentioned
>>about certain pointers or handles being NULL. Running out of GDI resources
>>might be the cause and I will test for that. But it's seems unlikely to me
>>that GDI resources would be depleted after fewer calls (not after a
>>shorter
>>time) with a 1 msec delay than with a 50 msec delay.
>
> Sleep times are at best approximate. It might be more useful to count the
> number of calls you're able to make before it fails, and you need to check
> for errors so you know immediately when something fails.
>
>>The help says typically
>>that a function returns 0 if error and non zero if success. So 0 only
>>tells
>>me there was an error but not what the error was. It also doesn't tell me
>>to
>>call GetLastError so I assume it's not updated in this case.
>
> FWIW, the help is only sometimes helpful. It's usually insufficient to
> read
> only the MFC documentation concerning things that are documented by the
> SDK
> as the primary source.
>
>>Okay, thanks. I'll try this. I'd rather not Detach and recreate all the
>>time
>>if it's not necessary. But many MFC functions that return a pointer say
>>that
>>the pointer is temporary and should not be saved for future use. So I try
>>getting a fresh one before I need to use it because I don't know such when
>>a
>>pointer will become "stale". Could you please shed some light on that?
>>When
>>do these temporary pointers become invalid? Is it a matter of memory being
>>swapped out and into a new address? Or control switching out of my thread
>>then coming back? Is the underlying bitmap or DC (in this example) stable
>>but only the MFC object might not have a stable connection to it (meaning
>>I
>>should use the SDK level instead of MFC)?
>
> The temporary MFC objects are deleted during idle-time processing, which
> is
> part of the normal MFC message loop, though IIRC, it doesn't occur while a
> dialog box is active. So as a rule of thumb, a temporary MFC object is
> usable until the function that obtained it returns, or more correctly (and
> dangerously), during the processing of the Windows message under which it
> was obtained. The "Create" calls you're making create permanent objects,
> which you can reuse to the extent that it makes any sense to reuse them.
> The GetDC call may return a temporary object.
>
> To add to what Joe said about the Detach vs. Delete, the CWnd::GetDC
> documentation says:
>
> "Unless the device context belongs to a window class, the ReleaseDC
> member
> function must be called to release the context after painting."
>
> That's something else you seem to be forgetting to do. You should call
> that
> function, period. It's at worst unnecessary and harmless. You might want
> to
> go to codeproject.com and look for classes that wrap all this in a more
> modern way using the RAII technique. You can probably find one or two to
> encapsulate everything you're doing in your function with a single
> "SomeMemoryDcClass" variable. Or maybe your function should be a member of
> that class named "Update" or something. The initialization and state of
> objects of that class will be more complicated since the window you're
> interested in belongs to another process and can potentially go away at
> any
> time.
>
> --
> Doug Harrison
> Visual C++ MVP


From: Doug Harrison [MVP] on
On Wed, 14 Apr 2010 11:25:40 +0800, "Bill" <<don't want more spam>> wrote:

>Per Joe's suggestion, I do DeleteObject on the bitmap now. I can't find a
>function to DeleteObject for the memoryDC. Is there one or a way?

There is the DeleteDC function. However, it should be called automatically
when the object is destroyed if you are using CDC and have called a Create
function.

>Also, I saw in DeleteObject help that I shouldn't delete an object that is selected
>into a DC. But I can't find a function to unselect the bitmap object out of
>the DC. Am I overlooking one or must I just select another object (maybe a
>stock object) into the DC?

Standard practice is to save the object that was returned by SelectObject
and select it back into the DC. You can also use SaveDC/RestoreDC, which is
simpler. You should wrap SaveDC/RestoreDC with a class that uses the RAII
technique, which helps with exception safety and clarity, as using such
classes will significantly shorten your code as it helps you make your
program more robust. That is, you should be able to write inside a
function:

DcSaver dcSaver(dc);

After this statement is executed, you can use the DC to your heart's
content. When the DcSaver goes out of scope and is destroyed, the DC will
be restored. If you're not familiar with this technique, let me know, and
I'll post an implementation of DcSaver. Again, codeproject.com may have an
implementation of this.

>I'm not sure I have a good mental image of what is happening with bitmap and
>DC classes and instances and objects and handles. Is it correct to imagine
>this? Before MFC, these (SDK?) objects were referenced by handles. MFC added
>a layer around these objects to allow C++ coding using them. So to use MFC,
>there is an instance of the MFC class but still the original windows object.
>Attach and detach make and break the connection between these two things via
>pointers or lookup tables. Are the original windows objects "stable" in that
>they can be referenced by their handle through the life of the program?

That depends on the Windows object and when it's destroyed. It is certainly
possible to have MFC objects that contain NULL handles, but it's harder to
encounter an MFC object that contains an invalid, non-NULL handle.
Observing that condition usually represents a bug in your code.

>Is it only the MFC class instance that might be temporary in that it might be
>destructed when it goes out of scope but the windows object referenced by
>the handle is still there?

Sure, that can happen. The destruction of a temporary MFC object will not
destroy the underlying Windows object, because the MFC object doesn't own
it. Indeed, the Windows object may have been destroyed by the time MFC gets
around to deleting the temporary MFC object that wraps it. That said,
ownership in MFC is often less than clear, and the documentation typically
doesn't help. This is when you use the source. Note also that these
temporary MFC objects are all referred to by pointers, so strictly
speaking, they aren't destroyed when they "go out of scope". They're
destroyed primarily during idle-time processing, when you drop back into
MFC's message loop.

--
Doug Harrison
Visual C++ MVP
From: "Bill" don't want more on
I put in ReleaseDC adn DeleteDc and DeleteObject and removed the Detach
calls and now it's working much better. I'll let it run overnight to check
and then move on to other functionality. Thanks all for the advice.


"Doug Harrison [MVP]" <dsh(a)mvps.org> wrote in message
news:vrgas5plq70psccm60n1j2j33f2liahupd(a)4ax.com...
> On Wed, 14 Apr 2010 11:25:40 +0800, "Bill" <<don't want more spam>> wrote:
>
>>Per Joe's suggestion, I do DeleteObject on the bitmap now. I can't find a
>>function to DeleteObject for the memoryDC. Is there one or a way?
>
> There is the DeleteDC function. However, it should be called automatically
> when the object is destroyed if you are using CDC and have called a Create
> function.
>
>>Also, I saw in DeleteObject help that I shouldn't delete an object that is
>>selected
>>into a DC. But I can't find a function to unselect the bitmap object out
>>of
>>the DC. Am I overlooking one or must I just select another object (maybe a
>>stock object) into the DC?
>
> Standard practice is to save the object that was returned by SelectObject
> and select it back into the DC. You can also use SaveDC/RestoreDC, which
> is
> simpler. You should wrap SaveDC/RestoreDC with a class that uses the RAII
> technique, which helps with exception safety and clarity, as using such
> classes will significantly shorten your code as it helps you make your
> program more robust. That is, you should be able to write inside a
> function:
>
> DcSaver dcSaver(dc);
>
> After this statement is executed, you can use the DC to your heart's
> content. When the DcSaver goes out of scope and is destroyed, the DC will
> be restored. If you're not familiar with this technique, let me know, and
> I'll post an implementation of DcSaver. Again, codeproject.com may have an
> implementation of this.
>
>>I'm not sure I have a good mental image of what is happening with bitmap
>>and
>>DC classes and instances and objects and handles. Is it correct to imagine
>>this? Before MFC, these (SDK?) objects were referenced by handles. MFC
>>added
>>a layer around these objects to allow C++ coding using them. So to use
>>MFC,
>>there is an instance of the MFC class but still the original windows
>>object.
>>Attach and detach make and break the connection between these two things
>>via
>>pointers or lookup tables. Are the original windows objects "stable" in
>>that
>>they can be referenced by their handle through the life of the program?
>
> That depends on the Windows object and when it's destroyed. It is
> certainly
> possible to have MFC objects that contain NULL handles, but it's harder to
> encounter an MFC object that contains an invalid, non-NULL handle.
> Observing that condition usually represents a bug in your code.
>
>>Is it only the MFC class instance that might be temporary in that it might
>>be
>>destructed when it goes out of scope but the windows object referenced by
>>the handle is still there?
>
> Sure, that can happen. The destruction of a temporary MFC object will not
> destroy the underlying Windows object, because the MFC object doesn't own
> it. Indeed, the Windows object may have been destroyed by the time MFC
> gets
> around to deleting the temporary MFC object that wraps it. That said,
> ownership in MFC is often less than clear, and the documentation typically
> doesn't help. This is when you use the source. Note also that these
> temporary MFC objects are all referred to by pointers, so strictly
> speaking, they aren't destroyed when they "go out of scope". They're
> destroyed primarily during idle-time processing, when you drop back into
> MFC's message loop.
>
> --
> Doug Harrison
> Visual C++ MVP


From: Joseph M. Newcomer on
See below...
On Tue, 13 Apr 2010 23:47:54 -0500, "Doug Harrison [MVP]" <dsh(a)mvps.org> wrote:

>On Wed, 14 Apr 2010 11:25:40 +0800, "Bill" <<don't want more spam>> wrote:
>
>>Per Joe's suggestion, I do DeleteObject on the bitmap now. I can't find a
>>function to DeleteObject for the memoryDC. Is there one or a way?
>
>There is the DeleteDC function. However, it should be called automatically
>when the object is destroyed if you are using CDC and have called a Create
>function.
>
>>Also, I saw in DeleteObject help that I shouldn't delete an object that is selected
>>into a DC. But I can't find a function to unselect the bitmap object out of
>>the DC. Am I overlooking one or must I just select another object (maybe a
>>stock object) into the DC?
>
>Standard practice is to save the object that was returned by SelectObject
>and select it back into the DC. You can also use SaveDC/RestoreDC, which is
>simpler. You should wrap SaveDC/RestoreDC with a class that uses the RAII
>technique, which helps with exception safety and clarity, as using such
>classes will significantly shorten your code as it helps you make your
>program more robust. That is, you should be able to write inside a
>function:
>
>DcSaver dcSaver(dc);
>
>After this statement is executed, you can use the DC to your heart's
>content. When the DcSaver goes out of scope and is destroyed, the DC will
>be restored. If you're not familiar with this technique, let me know, and
>I'll post an implementation of DcSaver. Again, codeproject.com may have an
>implementation of this.
>
****
I have an RAII version of SaveDC on my MVP Tips site.

Also, I am not at all sure why a GetDC is being done; it should be

CClientDC dc(wnd);

where wnd is the CWnd * pointer in hand; the DC will be released when the variable goes
out of scope.
****
>>I'm not sure I have a good mental image of what is happening with bitmap and
>>DC classes and instances and objects and handles. Is it correct to imagine
>>this? Before MFC, these (SDK?) objects were referenced by handles. MFC added
>>a layer around these objects to allow C++ coding using them. So to use MFC,
>>there is an instance of the MFC class but still the original windows object.
>>Attach and detach make and break the connection between these two things via
>>pointers or lookup tables. Are the original windows objects "stable" in that
>>they can be referenced by their handle through the life of the program?
>
>That depends on the Windows object and when it's destroyed. It is certainly
>possible to have MFC objects that contain NULL handles, but it's harder to
>encounter an MFC object that contains an invalid, non-NULL handle.
>Observing that condition usually represents a bug in your code.
>
>>Is it only the MFC class instance that might be temporary in that it might be
>>destructed when it goes out of scope but the windows object referenced by
>>the handle is still there?
>
>Sure, that can happen. The destruction of a temporary MFC object will not
>destroy the underlying Windows object, because the MFC object doesn't own
>it. Indeed, the Windows object may have been destroyed by the time MFC gets
>around to deleting the temporary MFC object that wraps it. That said,
>ownership in MFC is often less than clear, and the documentation typically
>doesn't help. This is when you use the source. Note also that these
>temporary MFC objects are all referred to by pointers, so strictly
>speaking, they aren't destroyed when they "go out of scope". They're
>destroyed primarily during idle-time processing, when you drop back into
>MFC's message loop.
****
The default CWinApp::OnIdle handler goes through the handle map, locates all temporary
handles, and deletes the MFC object without deleting the underlying kernel object which is
wrapped by the temporary object. So after returning to the default message pump, the
pointeres to temporary MFC objects are destroy.

In this case, he is creating a bitmap which is in the class, so it can have a lifetime
beyond this subroutine.
joe
****
Joseph M. Newcomer [MVP]
email: newcomer(a)flounder.com
Web: http://www.flounder.com
MVP Tips: http://www.flounder.com/mvp_tips.htm