Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • World
  • Users
  • Groups
Skins
  • Light
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Code Project
  1. Home
  2. General Programming
  3. C / C++ / MFC
  4. CPaintDC resource

CPaintDC resource

Scheduled Pinned Locked Moved C / C++ / MFC
graphicsquestionannouncementlearning
10 Posts 3 Posters 1 Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • L Offline
    L Offline
    LighthouseJ
    wrote on last edited by
    #1

    I have an OnPaint function and it's being called over and over and after a while, it throws a resource exception by simply saying:

    A required resource was unavailable.

    I have no idea what that means beyond what it says but it's happening sometime in the OnPaint function after it's run a couple thousand times. I only get the "CPaintDC dc(this);" at the top of the try block (to catch exceptions) and then I draw or not draw with if statements later. Am I allocating the drawing context without deallocating it, do I need to release the 'dc' variable or something to the system? Under the CPaintDC constructor, it says this as a remark:

    An exception (of type CResourceException) is thrown if the Windows GetDC call fails. A device context may not be available if Windows has already allocated all of its available device contexts. Your application competes for the five common display contexts available at any given time under Windows.

    Is that affecting me? If so, how I do rectify this?

    C 1 Reply Last reply
    0
    • L LighthouseJ

      I have an OnPaint function and it's being called over and over and after a while, it throws a resource exception by simply saying:

      A required resource was unavailable.

      I have no idea what that means beyond what it says but it's happening sometime in the OnPaint function after it's run a couple thousand times. I only get the "CPaintDC dc(this);" at the top of the try block (to catch exceptions) and then I draw or not draw with if statements later. Am I allocating the drawing context without deallocating it, do I need to release the 'dc' variable or something to the system? Under the CPaintDC constructor, it says this as a remark:

      An exception (of type CResourceException) is thrown if the Windows GetDC call fails. A device context may not be available if Windows has already allocated all of its available device contexts. Your application competes for the five common display contexts available at any given time under Windows.

      Is that affecting me? If so, how I do rectify this?

      C Offline
      C Offline
      Christian Graus
      wrote on last edited by
      #2

      It sounds to me like your paint handler is leaking resources. Could you post the code ? Do you clean up the brushes/bitmaps/DCs etc that you use ? Christian Graus - Microsoft MVP - C++

      L 1 Reply Last reply
      0
      • C Christian Graus

        It sounds to me like your paint handler is leaking resources. Could you post the code ? Do you clean up the brushes/bitmaps/DCs etc that you use ? Christian Graus - Microsoft MVP - C++

        L Offline
        L Offline
        LighthouseJ
        wrote on last edited by
        #3

        The code is complex, but here's the short of it: try {   CPaintDC dc(this);   if ((thread == NULL) && (files != NULL)) {     dc.Rectangle(x, y, x + 300, y + nTextHeight + 4);     COLORREF OldColor = dc.SetTextColor (RGB(192, 192, 192));     dc.SelectObject (new CBrush(RGB(192, 192, 192)));     sMsg.Format("%s, %s", obj->GetName(), obj->GetStringFilesize());     dc.TextOut(x + 2, y + 2, (LPCTSTR) sMsg);     dc.SetTextColor(OldColor);     dc.SelectObject (new CBrush (RGB(255, 255, 255)));   }   <2 more sections like the above exist with different if statement tests> } catch (CResourceException * e) {   e->Delete();   thread->SuspendThread();   char * lpszMessage = new char[128];   e->GetErrorMessage(lpszMessage, 128, NULL);   MessageBox(lpszMessage, "Critical Error", MB_ICONSTOP);   delete[] lpszMessage;   thread->ResumeThread(); } That's the gist (and most complex) part of it. I have 3 blocks like the if statement above, the first two are rarely used, but the third is heavily used when a particular thread is running. The heavily used if statement is similar in layout to the above but it draws a text element and pie, both correspond to a progress display of the thread the code mentions. I was handling the CBrush's by new'ing and delete'ing them manually but it threw runtime errors when delete'ing the CBrush's, it said a "pure virtual function call" or something like that. I don't do any clean up, I just get the dc from CPaintDC and then draw, that's it. I figured I didn't need to deallocate the drawing context because I was using it in this method, instead of using a handle to a drawing context with GetDC/ReleaseDC.

        C P 2 Replies Last reply
        0
        • L LighthouseJ

          The code is complex, but here's the short of it: try {   CPaintDC dc(this);   if ((thread == NULL) && (files != NULL)) {     dc.Rectangle(x, y, x + 300, y + nTextHeight + 4);     COLORREF OldColor = dc.SetTextColor (RGB(192, 192, 192));     dc.SelectObject (new CBrush(RGB(192, 192, 192)));     sMsg.Format("%s, %s", obj->GetName(), obj->GetStringFilesize());     dc.TextOut(x + 2, y + 2, (LPCTSTR) sMsg);     dc.SetTextColor(OldColor);     dc.SelectObject (new CBrush (RGB(255, 255, 255)));   }   <2 more sections like the above exist with different if statement tests> } catch (CResourceException * e) {   e->Delete();   thread->SuspendThread();   char * lpszMessage = new char[128];   e->GetErrorMessage(lpszMessage, 128, NULL);   MessageBox(lpszMessage, "Critical Error", MB_ICONSTOP);   delete[] lpszMessage;   thread->ResumeThread(); } That's the gist (and most complex) part of it. I have 3 blocks like the if statement above, the first two are rarely used, but the third is heavily used when a particular thread is running. The heavily used if statement is similar in layout to the above but it draws a text element and pie, both correspond to a progress display of the thread the code mentions. I was handling the CBrush's by new'ing and delete'ing them manually but it threw runtime errors when delete'ing the CBrush's, it said a "pure virtual function call" or something like that. I don't do any clean up, I just get the dc from CPaintDC and then draw, that's it. I figured I didn't need to deallocate the drawing context because I was using it in this method, instead of using a handle to a drawing context with GetDC/ReleaseDC.

          C Offline
          C Offline
          Christian Graus
          wrote on last edited by
          #4

          LighthouseJ wrote:

          dc.SelectObject (new CBrush(RGB(192, 192, 192)));

          This is a resource leak. you need to create a brush as a variable, and when you call selectobject, you need to grab the brush it returns. Then you need to restore the original brush, and destroy the brush you created.

          LighthouseJ wrote:

          dc.SelectObject (new CBrush (RGB(255, 255, 255)));

          Ditto. I assume this is supposed to restore the original brush color, but you need to actually restore the original brush. Christian Graus - Microsoft MVP - C++

          L 1 Reply Last reply
          0
          • C Christian Graus

            LighthouseJ wrote:

            dc.SelectObject (new CBrush(RGB(192, 192, 192)));

            This is a resource leak. you need to create a brush as a variable, and when you call selectobject, you need to grab the brush it returns. Then you need to restore the original brush, and destroy the brush you created.

            LighthouseJ wrote:

            dc.SelectObject (new CBrush (RGB(255, 255, 255)));

            Ditto. I assume this is supposed to restore the original brush color, but you need to actually restore the original brush. Christian Graus - Microsoft MVP - C++

            L Offline
            L Offline
            LighthouseJ
            wrote on last edited by
            #5

            I actually did that originally but I got the aforementioned error because I was trying to free memory from another threads heap. I changed it like below and no error shows up so I guess it's cleared up but I have to clean up the code more because it was opened up to try and fix this with other methods. CBrush * grey = new CBrush (RGB(192, 192, 192)); CBrush * black = new CBrush (RGB(255, 255, 255)); dc.SelectObject (grey); < drawing done here > dc.SelectObject(black); delete grey; delete black;

            C 1 Reply Last reply
            0
            • L LighthouseJ

              I actually did that originally but I got the aforementioned error because I was trying to free memory from another threads heap. I changed it like below and no error shows up so I guess it's cleared up but I have to clean up the code more because it was opened up to try and fix this with other methods. CBrush * grey = new CBrush (RGB(192, 192, 192)); CBrush * black = new CBrush (RGB(255, 255, 255)); dc.SelectObject (grey); < drawing done here > dc.SelectObject(black); delete grey; delete black;

              C Offline
              C Offline
              Christian Graus
              wrote on last edited by
              #6

              LighthouseJ wrote:

              I actually did that originally but I got the aforementioned error because I was trying to free memory from another threads heap.

              Well, it's the way it needs to be done, you need to work out those threading issues, I guess..

              LighthouseJ wrote:

              CBrush * grey = new CBrush (RGB(192, 192, 192)); CBrush * black = new CBrush (RGB(255, 255, 255)); dc.SelectObject (grey); < drawing done here > dc.SelectObject(black); delete grey; delete black;

              This is wrong. CBrush * grey = new CBrush (RGB(192, 192, 192)); CBrush * black = dc.SelectObject (grey); < drawing done here > dc.SelectObject(black); delete grey; You need to grab the brush that SelectObject returns, and put it back when you're done. Christian Graus - Microsoft MVP - C++

              L 1 Reply Last reply
              0
              • C Christian Graus

                LighthouseJ wrote:

                I actually did that originally but I got the aforementioned error because I was trying to free memory from another threads heap.

                Well, it's the way it needs to be done, you need to work out those threading issues, I guess..

                LighthouseJ wrote:

                CBrush * grey = new CBrush (RGB(192, 192, 192)); CBrush * black = new CBrush (RGB(255, 255, 255)); dc.SelectObject (grey); < drawing done here > dc.SelectObject(black); delete grey; delete black;

                This is wrong. CBrush * grey = new CBrush (RGB(192, 192, 192)); CBrush * black = dc.SelectObject (grey); < drawing done here > dc.SelectObject(black); delete grey; You need to grab the brush that SelectObject returns, and put it back when you're done. Christian Graus - Microsoft MVP - C++

                L Offline
                L Offline
                LighthouseJ
                wrote on last edited by
                #7

                I was trying to capture the outgoing brush but when I delete it, I got the error saying the memory I was deallocating wasn't mine. So, I just don't delete the black brush? Isn't that leaking memory?

                C 1 Reply Last reply
                0
                • L LighthouseJ

                  I was trying to capture the outgoing brush but when I delete it, I got the error saying the memory I was deallocating wasn't mine. So, I just don't delete the black brush? Isn't that leaking memory?

                  C Offline
                  C Offline
                  Christian Graus
                  wrote on last edited by
                  #8

                  LighthouseJ wrote:

                  I was trying to capture the outgoing brush but when I delete it, I got the error saying the memory I was deallocating wasn't mine.

                  Correct. You can't delete it, you need to select it back into the DC in order to avoid a leak.

                  LighthouseJ wrote:

                  So, I just don't delete the black brush? Isn't that leaking memory?

                  No, because you don't create a black brush, and because the brush in question is left in the control of the DC, as it was at the start. Christian Graus - Microsoft MVP - C++

                  1 Reply Last reply
                  0
                  • L LighthouseJ

                    The code is complex, but here's the short of it: try {   CPaintDC dc(this);   if ((thread == NULL) && (files != NULL)) {     dc.Rectangle(x, y, x + 300, y + nTextHeight + 4);     COLORREF OldColor = dc.SetTextColor (RGB(192, 192, 192));     dc.SelectObject (new CBrush(RGB(192, 192, 192)));     sMsg.Format("%s, %s", obj->GetName(), obj->GetStringFilesize());     dc.TextOut(x + 2, y + 2, (LPCTSTR) sMsg);     dc.SetTextColor(OldColor);     dc.SelectObject (new CBrush (RGB(255, 255, 255)));   }   <2 more sections like the above exist with different if statement tests> } catch (CResourceException * e) {   e->Delete();   thread->SuspendThread();   char * lpszMessage = new char[128];   e->GetErrorMessage(lpszMessage, 128, NULL);   MessageBox(lpszMessage, "Critical Error", MB_ICONSTOP);   delete[] lpszMessage;   thread->ResumeThread(); } That's the gist (and most complex) part of it. I have 3 blocks like the if statement above, the first two are rarely used, but the third is heavily used when a particular thread is running. The heavily used if statement is similar in layout to the above but it draws a text element and pie, both correspond to a progress display of the thread the code mentions. I was handling the CBrush's by new'ing and delete'ing them manually but it threw runtime errors when delete'ing the CBrush's, it said a "pure virtual function call" or something like that. I don't do any clean up, I just get the dc from CPaintDC and then draw, that's it. I figured I didn't need to deallocate the drawing context because I was using it in this method, instead of using a handle to a drawing context with GetDC/ReleaseDC.

                    P Offline
                    P Offline
                    PJ Arends
                    wrote on last edited by
                    #9

                    Have a look at CDC::SaveDC() ( There is also an excellent article by Joe Newcomer on this site about SaveDC(), look it up ) and also why not just use local GDI objects that go out of scope when you are done with them? saves having to mess around with new and delete.


                    "You're obviously a superstar." - Christian Graus about me - 12 Feb '03 "Obviously ???  You're definitely a superstar!!!" - mYkel - 21 Jun '04 "There's not enough blatant self-congratulatory backslapping in the world today..." - HumblePie - 21 Jun '05 Within you lies the power for good - Use it!

                    L 1 Reply Last reply
                    0
                    • P PJ Arends

                      Have a look at CDC::SaveDC() ( There is also an excellent article by Joe Newcomer on this site about SaveDC(), look it up ) and also why not just use local GDI objects that go out of scope when you are done with them? saves having to mess around with new and delete.


                      "You're obviously a superstar." - Christian Graus about me - 12 Feb '03 "Obviously ???  You're definitely a superstar!!!" - mYkel - 21 Jun '04 "There's not enough blatant self-congratulatory backslapping in the world today..." - HumblePie - 21 Jun '05 Within you lies the power for good - Use it!

                      L Offline
                      L Offline
                      LighthouseJ
                      wrote on last edited by
                      #10

                      I'll read that tonight. I haven't optimized the program for space and efficiency yet but one thing I did was to put the grey brush into the child view to be created once on construction, then used repeatedly, and deleted on deconstruction. I also have to figure out a better flow to my program but that's on my shoulders. I'm trying to optimize drawing because it's definitely the slowest part of my program.

                      1 Reply Last reply
                      0
                      Reply
                      • Reply as topic
                      Log in to reply
                      • Oldest to Newest
                      • Newest to Oldest
                      • Most Votes


                      • Login

                      • Don't have an account? Register

                      • Login or register to search.
                      • First post
                        Last post
                      0
                      • Categories
                      • Recent
                      • Tags
                      • Popular
                      • World
                      • Users
                      • Groups