From: "Bill" don't want more on 12 Apr 2010 06:11 I'm doing a program that needs to capture bitmaps off a window of another program. I'm doing okay except I have an intermittent failure. I admit I'm not testing for all the possible MFC error returns at this early stage, but even I did I'm not sure how I'd deal with this error. My piece of code looks like this. CDC m_memoryDc; CBitmap m_bitmap; void CMyDlg::GrabRect(CWnd *pWnd, CRect rc) { CDC * pSourceDc = pWnd->GetDC(); Sleep(50); // !!!!! need this or the crash happens almost right away m_bitmap.Detach(); m_bitmap.CreateCompatibleBitmap(pSourceDc, rc.Width(), rc.Height()); <-- error here m_memoryDc.Detach(); BOOL ret = m_memoryDc.CreateCompatibleDC(pSourceDc); m_memoryDc.SelectObject(&m_bitmap); <-- error here m_memoryDc.BitBlt(0, 0, rc.Width(), rc.Height(), pSourceDc, rc.left, rc.top, SRCCOPY); } I'm trying to capture a bit of window into m_bitmap. I'll later use the m_memoryDC to access the pixels of the bitmap. I need the Sleep function call. If I set to 50 ms, then I will get an error after a few hundred calls to this function. If I set it to 1 msec, I will get an error after a few calls only. If I set it longer, like 200 msec, I can run a longer time, but since it's slower, I don't know if it will run forever without a crash or just takes longer to crash. Sometimes the error occurs at CreateCompatibleBitmap. pSourceDC is NULL so the GetDC call failed I guess. But I don't know if I can check the reason because there is no error code returned. Sometimes the error occurs at SelectObject. In this case pSourceDC looks valid (0x00c0fe70) and the m_hDC and m_hAttribDC both have the same value (0x70015a85) but ret is NULL and two handles of m_memoryDC are both NULL. I'm not sure what to try next. Am I not releasing some resource and running out of memory or soemthing? Is there a need for a delay after the calls for the object to be valid? Doesn't seem right, but if so, is there a way to check if they are valid myself so I'm not wasting time when they are already valid? Actually, is there any way to manipulate bitmaps without going through the seemingly extra step of using a CDC? Thanks...
From: Joseph M. Newcomer on 12 Apr 2010 14:44 See below... On Mon, 12 Apr 2010 18:11:36 +0800, "Bill" <<don't want more spam>> wrote: >I'm doing a program that needs to capture bitmaps off a window of another >program. I'm doing okay except I have an intermittent failure. I admit I'm >not testing for all the possible MFC error returns at this early stage, but >even I did I'm not sure how I'd deal with this error. > >My piece of code looks like this. > >CDC m_memoryDc; >CBitmap m_bitmap; > >void CMyDlg::GrabRect(CWnd *pWnd, CRect rc) >{ > CDC * pSourceDc = pWnd->GetDC(); > Sleep(50); // !!!!! need this or the crash happens almost right away **** Any program that requires a Sleep to work correctly is inherently wrong to start with! **** > m_bitmap.Detach(); *** Note that this leaks bitmaps; you must first DeleteObject to kill the bitmap, or you start accumulating bitmaps and will run out of GDI resources. Detach() does not destroy a bitmap, it just breaks the association between a CBitmap object and the bitmap! **** > m_bitmap.CreateCompatibleBitmap(pSourceDc, rc.Width(), rc.Height()); <-- >error here **** I'm sure there an "error", whatever that means! But you have not said what the error is, so we are left to use psychic vibrations to determine the cause. ***** > m_memoryDc.Detach(); > BOOL ret = m_memoryDc.CreateCompatibleDC(pSourceDc); > m_memoryDc.SelectObject(&m_bitmap); <-- error here > m_memoryDc.BitBlt(0, 0, rc.Width(), rc.Height(), pSourceDc, rc.left, >rc.top, SRCCOPY); >} > >I'm trying to capture a bit of window into m_bitmap. I'll later use the >m_memoryDC to access the pixels of the bitmap. > >I need the Sleep function call. If I set to 50 ms, then I will get an error >after a few hundred calls to this function. If I set it to 1 msec, I will >get an error after a few calls only. If I set it longer, like 200 msec, I >can run a longer time, but since it's slower, I don't know if it will run >forever without a crash or just takes longer to crash. **** The word "crash" is a nonsense term that conveys no meaning. Do you mean "I had an assertion failure" (which is not a crash, by the way), or "I had an access fault", or what? **** > >Sometimes the error occurs at CreateCompatibleBitmap. pSourceDC is NULL so >the GetDC call failed I guess. But I don't know if I can check the reason >because there is no error code returned. **** Well, then it would help if you checked the return values and did not continue execution if there is a problem. **** > >Sometimes the error occurs at SelectObject. In this case pSourceDC looks >valid (0x00c0fe70) and the m_hDC and m_hAttribDC both have the same value >(0x70015a85) but ret is NULL and two handles of m_memoryDC are both NULL. **** You need to check at each stage that things are working right! ***** > >I'm not sure what to try next. Am I not releasing some resource and running >out of memory or soemthing? Is there a need for a delay after the calls for >the object to be valid? Doesn't seem right, but if so, is there a way to >check if they are valid myself so I'm not wasting time when they are already >valid? *** Well, the Detach() is a Really Bad Idea, since you don't actually delete the bitmap. ***** > >Actually, is there any way to manipulate bitmaps without going through the >seemingly extra step of using a CDC? **** No. Not to do what you want. Note also that "capturing the bitmap" means you will capture the rectangular area of the screen that defines where the window is; if there is something laying on top of it at the moment, you will get the pixels that are on the screen, not necessarily the pixels of the window. joe **** > >Thanks... > Joseph M. Newcomer [MVP] email: newcomer(a)flounder.com Web: http://www.flounder.com MVP Tips: http://www.flounder.com/mvp_tips.htm
From: "Bill Brehm" don't want on 12 Apr 2010 21:33 "Any program that requires a Sleep to work correctly is inherently wrong to start with!" 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? "I'm sure there an "error", whatever that means! But you have not said what the error is, so we are left to use psychic vibrations to determine the cause." 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. 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. "you must first DeleteObject to kill the bitmap" 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 word "crash" is a nonsense term" Yes, it was ASSERTs in the MFC code or sometimes also access violations. I traced backwards to find the cause and found the NULL pointers / handles. "Well, then it would help if you checked the return values and did not continue execution if there is a problem." I agree but then my goal will be to recover from the error. How to recover when the error is not understood. I'm pretty sure you will disagree with my way of working, but I tend to go for the functionality first then come back and fill in the error checking and recovery to a level that depends on who the user will be. If for myself only, I do less of it and if for others I do more. "Note also that "capturing the bitmap" means you will capture the rectangular area of the screen that defines where the window is" Yes, I'm aware of that. It caught me by surprise in an earlier project but thinking about it, it's quite logical. At first I thought there was some image of each window in memory somewhere and Windows displays it and the program maintains it. But then I learned that the program paints or draws to the screen directly when Windows asks it to. On this project I discovered that when the workstation times out and locks itself, there is also nothing there to capture. Thanks. "Joseph M. Newcomer" <newcomer(a)flounder.com> wrote in message news:u4q6s5hvlckon72ngk3sc2ul709e2jbcdq(a)4ax.com... > See below... > On Mon, 12 Apr 2010 18:11:36 +0800, "Bill" <<don't want more spam>> wrote: > >>I'm doing a program that needs to capture bitmaps off a window of another >>program. I'm doing okay except I have an intermittent failure. I admit I'm >>not testing for all the possible MFC error returns at this early stage, >>but >>even I did I'm not sure how I'd deal with this error. >> >>My piece of code looks like this. >> >>CDC m_memoryDc; >>CBitmap m_bitmap; >> >>void CMyDlg::GrabRect(CWnd *pWnd, CRect rc) >>{ >> CDC * pSourceDc = pWnd->GetDC(); >> Sleep(50); // !!!!! need this or the crash happens almost right away > **** > Any program that requires a Sleep to work correctly is inherently wrong to > start with! > **** >> m_bitmap.Detach(); > *** > Note that this leaks bitmaps; you must first DeleteObject to kill the > bitmap, or you start > accumulating bitmaps and will run out of GDI resources. Detach() does not > destroy a > bitmap, it just breaks the association between a CBitmap object and the > bitmap! > **** >> m_bitmap.CreateCompatibleBitmap(pSourceDc, rc.Width(), rc.Height()); <-- >>error here > **** > I'm sure there an "error", whatever that means! But you have not said > what the error is, > so we are left to use psychic vibrations to determine the cause. > ***** >> m_memoryDc.Detach(); >> BOOL ret = m_memoryDc.CreateCompatibleDC(pSourceDc); >> m_memoryDc.SelectObject(&m_bitmap); <-- error here >> m_memoryDc.BitBlt(0, 0, rc.Width(), rc.Height(), pSourceDc, rc.left, >>rc.top, SRCCOPY); >>} >> >>I'm trying to capture a bit of window into m_bitmap. I'll later use the >>m_memoryDC to access the pixels of the bitmap. >> >>I need the Sleep function call. If I set to 50 ms, then I will get an >>error >>after a few hundred calls to this function. If I set it to 1 msec, I will >>get an error after a few calls only. If I set it longer, like 200 msec, I >>can run a longer time, but since it's slower, I don't know if it will run >>forever without a crash or just takes longer to crash. > **** > The word "crash" is a nonsense term that conveys no meaning. Do you mean > "I had an > assertion failure" (which is not a crash, by the way), or "I had an access > fault", or > what? > **** >> >>Sometimes the error occurs at CreateCompatibleBitmap. pSourceDC is NULL so >>the GetDC call failed I guess. But I don't know if I can check the reason >>because there is no error code returned. > **** > Well, then it would help if you checked the return values and did not > continue execution > if there is a problem. > **** >> >>Sometimes the error occurs at SelectObject. In this case pSourceDC looks >>valid (0x00c0fe70) and the m_hDC and m_hAttribDC both have the same value >>(0x70015a85) but ret is NULL and two handles of m_memoryDC are both NULL. > **** > You need to check at each stage that things are working right! > ***** >> >>I'm not sure what to try next. Am I not releasing some resource and >>running >>out of memory or soemthing? Is there a need for a delay after the calls >>for >>the object to be valid? Doesn't seem right, but if so, is there a way to >>check if they are valid myself so I'm not wasting time when they are >>already >>valid? > *** > Well, the Detach() is a Really Bad Idea, since you don't actually delete > the bitmap. > ***** >> >>Actually, is there any way to manipulate bitmaps without going through the >>seemingly extra step of using a CDC? > **** > No. Not to do what you want. > > Note also that "capturing the bitmap" means you will capture the > rectangular area of the > screen that defines where the window is; if there is something laying on > top of it at the > moment, you will get the pixels that are on the screen, not necessarily > the pixels of the > window. > joe > > **** >> >>Thanks... >> > Joseph M. Newcomer [MVP] > email: newcomer(a)flounder.com > Web: http://www.flounder.com > MVP Tips: http://www.flounder.com/mvp_tips.htm
From: Oliver Regenfelder on 13 Apr 2010 13:22 Hello, Bill Brehm wrote: > disagree with my > way of working, but I tend to go for the functionality first then come back > and fill in the error checking and recovery to a level that depends on who > the user will be. In my experience this is the style of work where error checking never happens. First it is postponed and once things work everybody goes on. The first time error checking is included then is when the customer complains. > At first I thought there was some > image of each window in memory somewhere and Windows displays it and the > program maintains it. But then I learned that the program paints or draws to > the screen directly when Windows asks it to. I think now you have to be more specific what 'Windows' you mean: XP, Vista, Seven? Best regards, Oliver
From: John H. on 13 Apr 2010 13:40 On Apr 12, 8:33 pm, "Bill Brehm" <don't want spam> wrote: > "Well, then it would help if you checked the return values and did not > continue execution if there is a problem." > > I agree but then my goal will be to recover from the error. How to recover > when the error is not understood. I'm pretty sure you will disagree with my > way of working, but I tend to go for the functionality first then come back > and fill in the error checking and recovery to a level that depends on who > the user will be. If for myself only, I do less of it and if for others I do > more. Error recovery isn't the only consideration here. From a "go for the functionality" point of view, checking the error codes can still be useful, because it can offer insight into what is going wrong with your code, i.e. can help you determine what you are doing wrong.
|
Next
|
Last
Pages: 1 2 3 Prev: CMFCRibbonStatusBar always visibile Next: Marshalling C# Strings to VC++ 6.0 |