From: Doug Harrison [MVP] on 13 Apr 2010 17:16 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 13 Apr 2010 23:25 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 14 Apr 2010 00:47 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 14 Apr 2010 05:55 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 14 Apr 2010 11:25 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
First
|
Prev
|
Next
|
Last
Pages: 1 2 3 Prev: CMFCRibbonStatusBar always visibile Next: Marshalling C# Strings to VC++ 6.0 |