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. Performance issue when drawing on MFC

Performance issue when drawing on MFC

Scheduled Pinned Locked Moved C / C++ / MFC
c++graphicshelpquestionperformance
5 Posts 3 Posters 0 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.
  • U Offline
    U Offline
    User 1619799
    wrote on last edited by
    #1

    Hello all & Thanks for reading this, -I would have a question on you: -I have created a small application on MFC/C++ that draw different geometric shapes on screen using the mouse (like Paint). These shapes can be moved and rotated, so, I had to keep all these created shapes in a vector and draw all of them in OnDraw(). -My problem is, when I create many shapes (more than 50-60) and I try to move/rotate one of the shapes, these movements/rotations become very-very slow. -Could you give me some tips in order to make my application faster when moving/rotating?

    OnDraw(CDC* pDC)
    {

    for (int i = 0; i < numberObjects; i++)
    objects\[i\]->DrawShape(pDC);
    

    }

    Many thanks!

    R L 2 Replies Last reply
    0
    • U User 1619799

      Hello all & Thanks for reading this, -I would have a question on you: -I have created a small application on MFC/C++ that draw different geometric shapes on screen using the mouse (like Paint). These shapes can be moved and rotated, so, I had to keep all these created shapes in a vector and draw all of them in OnDraw(). -My problem is, when I create many shapes (more than 50-60) and I try to move/rotate one of the shapes, these movements/rotations become very-very slow. -Could you give me some tips in order to make my application faster when moving/rotating?

      OnDraw(CDC* pDC)
      {

      for (int i = 0; i < numberObjects; i++)
      objects\[i\]->DrawShape(pDC);
      

      }

      Many thanks!

      R Offline
      R Offline
      Rick York
      wrote on last edited by
      #2

      I would suggest drawing to a memory DC. There is a class here called CMemDC by Keith Rule that can handle that and something similar to it was built into MFC and is also called CMemDC, unfortunately. That might or might not help but I would start there.

      1 Reply Last reply
      0
      • U User 1619799

        Hello all & Thanks for reading this, -I would have a question on you: -I have created a small application on MFC/C++ that draw different geometric shapes on screen using the mouse (like Paint). These shapes can be moved and rotated, so, I had to keep all these created shapes in a vector and draw all of them in OnDraw(). -My problem is, when I create many shapes (more than 50-60) and I try to move/rotate one of the shapes, these movements/rotations become very-very slow. -Could you give me some tips in order to make my application faster when moving/rotating?

        OnDraw(CDC* pDC)
        {

        for (int i = 0; i < numberObjects; i++)
        objects\[i\]->DrawShape(pDC);
        

        }

        Many thanks!

        L Offline
        L Offline
        leon de boer
        wrote on last edited by
        #3

        You are basically building a version of windows within windows :-) Buffering won't really help you that much, the problem is you are redrawing 50 shapes when you move one shape (look at your code you do 1..numberObjects) and most of the time you don't need to redraw them. What you need to do is calculate what shapes overlap where your shape to move is now, and what shapes overlap the move shape in it's new position. Then you only need to draw those limited shapes. Much of the time you only needed to redraw probably 1-3 shapes but you are drawing everything. You can then get even smarter like windows and do only redraw partial areas. Do you see the next step from above in those cases you do have to redraw from above often you don't have to redraw the entire thing just a limited area. So you are minimizing the redrawing. If you aren't going to have thousands I can give a quick hack which is to put each shape on it's own child window. That child window has frames off and have no background color and simply draws that shape just like your code does on the one parent window. Do you get what will happen the window is transparent except the area you draw on, in the old days we called them sprites. To move the shape just issue a window MoveWindow command to that child window handle and it will move and do minimum overlapping window redraws for you for free ..... because that is what windows does with a window move :-) I will give you the other thing about that trick the selection of the shapes is a lot easier probably than you current code because windows will sort all the overlapping for you. That all said the often better way to do this is to simply XOR draw a rectangle representing the object and move just the XOR box with the mouse. When you get to where you want it you do the release and only then redraw everything. I assume you know the trick with XOR drawing if not Combining GDI and GDI+ to Draw Rubber Band Rectangles[^]

        In vino veritas

        U 1 Reply Last reply
        0
        • L leon de boer

          You are basically building a version of windows within windows :-) Buffering won't really help you that much, the problem is you are redrawing 50 shapes when you move one shape (look at your code you do 1..numberObjects) and most of the time you don't need to redraw them. What you need to do is calculate what shapes overlap where your shape to move is now, and what shapes overlap the move shape in it's new position. Then you only need to draw those limited shapes. Much of the time you only needed to redraw probably 1-3 shapes but you are drawing everything. You can then get even smarter like windows and do only redraw partial areas. Do you see the next step from above in those cases you do have to redraw from above often you don't have to redraw the entire thing just a limited area. So you are minimizing the redrawing. If you aren't going to have thousands I can give a quick hack which is to put each shape on it's own child window. That child window has frames off and have no background color and simply draws that shape just like your code does on the one parent window. Do you get what will happen the window is transparent except the area you draw on, in the old days we called them sprites. To move the shape just issue a window MoveWindow command to that child window handle and it will move and do minimum overlapping window redraws for you for free ..... because that is what windows does with a window move :-) I will give you the other thing about that trick the selection of the shapes is a lot easier probably than you current code because windows will sort all the overlapping for you. That all said the often better way to do this is to simply XOR draw a rectangle representing the object and move just the XOR box with the mouse. When you get to where you want it you do the release and only then redraw everything. I assume you know the trick with XOR drawing if not Combining GDI and GDI+ to Draw Rubber Band Rectangles[^]

          In vino veritas

          U Offline
          U Offline
          User 1619799
          wrote on last edited by
          #4

          Nice tips @Leon, many thanks for your help!

          L 1 Reply Last reply
          0
          • U User 1619799

            Nice tips @Leon, many thanks for your help!

            L Offline
            L Offline
            leon de boer
            wrote on last edited by
            #5

            No worries and since you came back can I offer you a piece of code that can very quickly reject all the trivial shape areas that do not require drawing when moving in your current code. You need to set the "dragging" flag to TRUE when you are moving a shape and set it back to FALSE when done dragging. I don't have the structures so you need to feed in x1,y1,x2,y2 into the two /* xxxxx */. So for each Area x1,y1 needs to be top left corner, x2,y2 lower right corner of the on screen minimum box around the shape. It puts an extra very fast test on redrawing a shape if the flag is set and I will leave you to work out what it does but it is commented :-)

            BOOL CanAreasOverlap (int Area1_x1, int Area1_y1, int Area1_x2, int Area1_y2, int Area2_x1, int Area2_y1, int Area2_x2, int Area2_y2){
            if (Area1_x1 > Area2_x2) return (FALSE); // Area 1 completely to the right of Area 2 and can't overlap
            if (Area1_x2 < Area2_x1) return (FALSE); // Area 1 completely to the left of Area 2 and can't overlap
            if (Area1_y1 > Area2_y2) return (FALSE); // Area 1 completely below Area 2 and can't overlap
            if (Area1_y2 < Area2_y1) return (FALSE); // Area 1 completely above Area2 and can't overlap
            return (TRUE); // The two square areas overlap to some degree
            }

            /* Set the dragging flag to TRUE when moving a shape */
            BOOL dragging = FALSE;
            OnDraw(CDC* pDC){

            for (int i = 0; i < numberObjects; i++){
                 if ((!dragging) || CanAreasOverlap(/\* Moving shape is area 1\*/, /\*objects\[i\] shape is area 2\*/)) { 
                    objects\[i\]->DrawShape(pDC);
                }
            }
            

            }

            When you drag a shape and go to redraw

            In vino veritas

            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