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
CODE PROJECT For Those Who Code
  • Home
  • Articles
  • FAQ
Community
  1. Home
  2. General Programming
  3. C / C++ / MFC
  4. [win32]Draw on a background bitmap

[win32]Draw on a background bitmap

Scheduled Pinned Locked Moved C / C++ / MFC
questiongraphicshelp
17 Posts 5 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.
  • M Offline
    M Offline
    Member 2965471
    wrote on last edited by
    #1

    Hi, this is the code:

    case WM_MOUSEMOVE:
    pt.x = LOWORD(lParam);
    pt.y = HIWORD(lParam);
    InvalidateRect(hWnd,NULL,TRUE);
    break;

    case WM_PAINT:
    hdc = BeginPaint(hWnd, &ps);

    memDC = CreateCompatibleDC(hdc);

    SelectObject(memDC,hbmp);

    GetObject(bmp, sizeof(bm), &bm);

    GetClientRect(hWnd,&rcc);

    StretchBlt(hdc,
    0,0, rcc.right,rcc.bottom,
    memDC,
    0,0,bm.bmWidth, bm.bmHeight,
    SRCCOPY);

    //onMouseMove
    MoveToEx(hdc, pt.x , 0 , NULL);
    LineTo(hdc, pt.x, rcc.bottom);
    MoveToEx(hdc, 0, pt.y, NULL);
    LineTo(hdc, rcc.right, pt.y);

    how can i draw lines on mouse move without repainting the background bitmap? There's a way to "fix" the bitmap on background and repaint only lines?

    L M B 3 Replies Last reply
    0
    • M Member 2965471

      Hi, this is the code:

      case WM_MOUSEMOVE:
      pt.x = LOWORD(lParam);
      pt.y = HIWORD(lParam);
      InvalidateRect(hWnd,NULL,TRUE);
      break;

      case WM_PAINT:
      hdc = BeginPaint(hWnd, &ps);

      memDC = CreateCompatibleDC(hdc);

      SelectObject(memDC,hbmp);

      GetObject(bmp, sizeof(bm), &bm);

      GetClientRect(hWnd,&rcc);

      StretchBlt(hdc,
      0,0, rcc.right,rcc.bottom,
      memDC,
      0,0,bm.bmWidth, bm.bmHeight,
      SRCCOPY);

      //onMouseMove
      MoveToEx(hdc, pt.x , 0 , NULL);
      LineTo(hdc, pt.x, rcc.bottom);
      MoveToEx(hdc, 0, pt.y, NULL);
      LineTo(hdc, rcc.right, pt.y);

      how can i draw lines on mouse move without repainting the background bitmap? There's a way to "fix" the bitmap on background and repaint only lines?

      L Offline
      L Offline
      Lost User
      wrote on last edited by
      #2

      InvalidateRect(hWnd,NULL,TRUE);

      The third parameter tells the system whether to erase the background on the next call to BeginPaint(); change it to FALSE to prevent the erase. You can also trap the WM_ERASEBKGND message and provide your own code to redraw the background however you like.

      The best things in life are not things.

      M 1 Reply Last reply
      0
      • L Lost User

        InvalidateRect(hWnd,NULL,TRUE);

        The third parameter tells the system whether to erase the background on the next call to BeginPaint(); change it to FALSE to prevent the erase. You can also trap the WM_ERASEBKGND message and provide your own code to redraw the background however you like.

        The best things in life are not things.

        M Offline
        M Offline
        Member 2965471
        wrote on last edited by
        #3

        thanks works, but why when i resize or maximize the window it doesn't work very well?

        D M 2 Replies Last reply
        0
        • M Member 2965471

          thanks works, but why when i resize or maximize the window it doesn't work very well?

          D Offline
          D Offline
          David Crow
          wrote on last edited by
          #4

          Member 2965471 wrote:

          ...it doesn't work very well?

          Is that supposed to be helpful?

          "One man's wage rise is another man's price increase." - Harold Wilson

          "Fireproof doesn't mean the fire will never come. It means when the fire comes that you will be able to withstand it." - Michael Simmons

          "Some people are making such thorough preparation for rainy days that they aren't enjoying today's sunshine." - William Feather

          M 1 Reply Last reply
          0
          • D David Crow

            Member 2965471 wrote:

            ...it doesn't work very well?

            Is that supposed to be helpful?

            "One man's wage rise is another man's price increase." - Harold Wilson

            "Fireproof doesn't mean the fire will never come. It means when the fire comes that you will be able to withstand it." - Michael Simmons

            "Some people are making such thorough preparation for rainy days that they aren't enjoying today's sunshine." - William Feather

            M Offline
            M Offline
            Member 2965471
            wrote on last edited by
            #5

            sorry...well when i increase the size of the window, the two lines partially disappear under the bitmap, while when i maximize the window the two lines do not appear and even the background image is distorted, may you help me please?

            D 1 Reply Last reply
            0
            • M Member 2965471

              thanks works, but why when i resize or maximize the window it doesn't work very well?

              M Offline
              M Offline
              Mark Salsbery
              wrote on last edited by
              #6

              Where are you calling InvalidateRect from? Don't do it in your WM_PAINT handler!

              Mark Salsbery Microsoft MVP - Visual C++ :java:

              M 1 Reply Last reply
              0
              • M Member 2965471

                sorry...well when i increase the size of the window, the two lines partially disappear under the bitmap, while when i maximize the window the two lines do not appear and even the background image is distorted, may you help me please?

                D Offline
                D Offline
                David Crow
                wrote on last edited by
                #7

                I think you should be drawing the bitmap on the temporary DC, then drawing the lines on top of that, and then BitBlt'ing the temporary DC onto the screen DC.

                "One man's wage rise is another man's price increase." - Harold Wilson

                "Fireproof doesn't mean the fire will never come. It means when the fire comes that you will be able to withstand it." - Michael Simmons

                "Some people are making such thorough preparation for rainy days that they aren't enjoying today's sunshine." - William Feather

                M 1 Reply Last reply
                0
                • D David Crow

                  I think you should be drawing the bitmap on the temporary DC, then drawing the lines on top of that, and then BitBlt'ing the temporary DC onto the screen DC.

                  "One man's wage rise is another man's price increase." - Harold Wilson

                  "Fireproof doesn't mean the fire will never come. It means when the fire comes that you will be able to withstand it." - Michael Simmons

                  "Some people are making such thorough preparation for rainy days that they aren't enjoying today's sunshine." - William Feather

                  M Offline
                  M Offline
                  Member 2965471
                  wrote on last edited by
                  #8

                  i've tried, when i maximize the window bitmap disappear and when i restoring the window the bitmap reappears, it seems that the coordinates are different when the window is maximize, it may be true?

                  D 1 Reply Last reply
                  0
                  • M Member 2965471

                    no no of course, i call it from WM_MOUSEMOVE.

                    M Offline
                    M Offline
                    Mark Salsbery
                    wrote on last edited by
                    #9

                    You're joking, right?

                    Mark Salsbery Microsoft MVP - Visual C++ :java:

                    M 1 Reply Last reply
                    0
                    • M Mark Salsbery

                      Where are you calling InvalidateRect from? Don't do it in your WM_PAINT handler!

                      Mark Salsbery Microsoft MVP - Visual C++ :java:

                      M Offline
                      M Offline
                      Member 2965471
                      wrote on last edited by
                      #10

                      no no of course, i call it from WM_MOUSEMOVE.

                      M 1 Reply Last reply
                      0
                      • M Mark Salsbery

                        You're joking, right?

                        Mark Salsbery Microsoft MVP - Visual C++ :java:

                        M Offline
                        M Offline
                        Member 2965471
                        wrote on last edited by
                        #11

                        i don't understand, why? i post my code in the first msg...

                        M 1 Reply Last reply
                        0
                        • M Member 2965471

                          i don't understand, why? i post my code in the first msg...

                          M Offline
                          M Offline
                          Mark Salsbery
                          wrote on last edited by
                          #12

                          Well it's not as bad as the recursion you'd get from calling it in response to WM_PAINT, but it certainly doesn't need to be called on every WM_MOUSEMOVE message. Maybe call it from WM_SIZE handling code instead...

                          Mark Salsbery Microsoft MVP - Visual C++ :java:

                          M 1 Reply Last reply
                          0
                          • M Mark Salsbery

                            Well it's not as bad as the recursion you'd get from calling it in response to WM_PAINT, but it certainly doesn't need to be called on every WM_MOUSEMOVE message. Maybe call it from WM_SIZE handling code instead...

                            Mark Salsbery Microsoft MVP - Visual C++ :java:

                            M Offline
                            M Offline
                            Member 2965471
                            wrote on last edited by
                            #13

                            I need to call it on mouse move because i need to draw two lines converging at the mouse cursor position.

                            M 1 Reply Last reply
                            0
                            • M Member 2965471

                              I need to call it on mouse move because i need to draw two lines converging at the mouse cursor position.

                              M Offline
                              M Offline
                              Mark Salsbery
                              wrote on last edited by
                              #14

                              Ok then I would double-buffer as mentioned by DavidCrow and use Invalidate();UpdateWindow() combination.

                              Mark Salsbery Microsoft MVP - Visual C++ :java:

                              1 Reply Last reply
                              0
                              • M Member 2965471

                                Hi, this is the code:

                                case WM_MOUSEMOVE:
                                pt.x = LOWORD(lParam);
                                pt.y = HIWORD(lParam);
                                InvalidateRect(hWnd,NULL,TRUE);
                                break;

                                case WM_PAINT:
                                hdc = BeginPaint(hWnd, &ps);

                                memDC = CreateCompatibleDC(hdc);

                                SelectObject(memDC,hbmp);

                                GetObject(bmp, sizeof(bm), &bm);

                                GetClientRect(hWnd,&rcc);

                                StretchBlt(hdc,
                                0,0, rcc.right,rcc.bottom,
                                memDC,
                                0,0,bm.bmWidth, bm.bmHeight,
                                SRCCOPY);

                                //onMouseMove
                                MoveToEx(hdc, pt.x , 0 , NULL);
                                LineTo(hdc, pt.x, rcc.bottom);
                                MoveToEx(hdc, 0, pt.y, NULL);
                                LineTo(hdc, rcc.right, pt.y);

                                how can i draw lines on mouse move without repainting the background bitmap? There's a way to "fix" the bitmap on background and repaint only lines?

                                M Offline
                                M Offline
                                Mark Salsbery
                                wrote on last edited by
                                #15

                                Since this is fun and I haven't touched C++ in years, here's a double-buffered version... Note I moved stuff out of the WM_PAINT handler that didn't need to be done every paint. For example, the offscreen buffer is only (re)created when the window size changes, the client rect is only updated when the window size changes, and the bitmap and its associated memoryDC are only loaded/created once (in WM_CREATE handler in the sample code). Flicker free! :)

                                POINT pt;
                                BITMAP Bitmap;
                                HANDLE hBitmap = 0;
                                HDC hBitmapMemoryDC = 0;
                                RECT ClientRect;
                                HBITMAP hOffScreenBitmap = 0;
                                HDC hOffScreenMemoryDC = 0;

                                LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
                                {
                                PAINTSTRUCT ps;
                                HDC hdc;

                                switch (message)
                                {
                                case WM\_CREATE:
                                    hBitmap = ::LoadImage(hInst, MAKEINTRESOURCE(IDB\_BITMAP1), IMAGE\_BITMAP, 0, 0, LR\_CREATEDIBSECTION);
                                    ::GetObject(hBitmap, sizeof(Bitmap), &Bitmap);
                                    hBitmapMemoryDC = ::CreateCompatibleDC(0);
                                    ::SelectObject(hBitmapMemoryDC, hBitmap);
                                    break;
                                case WM\_PAINT:
                                    hdc = BeginPaint(hWnd, &ps);
                                    // blt the bitmap to the offscreen buffer
                                    ::StretchBlt(hOffScreenMemoryDC, 0, 0, ClientRect.right, ClientRect.bottom, hBitmapMemoryDC, 0, 0, Bitmap.bmWidth, Bitmap.bmHeight, SRCCOPY);
                                    // draw crosshairs on the offscreen buffer
                                    ::MoveToEx(hOffScreenMemoryDC, pt.x , 0 , NULL); 
                                    ::LineTo(hOffScreenMemoryDC, pt.x, ClientRect.bottom); 
                                    ::MoveToEx(hOffScreenMemoryDC, 0, pt.y, NULL); 
                                    ::LineTo(hOffScreenMemoryDC, ClientRect.right, pt.y); 
                                    // blt the offscreen buffer to the screen
                                    ::BitBlt(hdc, 0, 0, ClientRect.right, ClientRect.bottom, hOffScreenMemoryDC, 0, 0, SRCCOPY);
                                    EndPaint(hWnd, &ps);
                                    break;
                                case WM\_MOUSEMOVE:
                                    pt.x = LOWORD(lParam);
                                    pt.y = HIWORD(lParam);
                                    ::InvalidateRect(hWnd,NULL,FALSE); // changed to FALSE since we draw the entire client area
                                    ::UpdateWindow(hWnd);
                                    break;	
                                case WM\_ERASEBKGND:
                                    // We draw the background in WM\_PAINT - don't do it here!
                                    return 1;
                                case WM\_SIZE:
                                    ClientRect.left = 0;
                                    ClientRect.top = 0;
                                    ClientRect.right = LOWORD(lParam);
                                    ClientRect.bottom = HIWORD(lParam);
                                    // (Re)Create the offscreen buffer
                                    if (hOffScreenBitmap != 0)
                                        ::DeleteObject(hOffScreenBitmap);
                                    if (hOffScreenMemoryDC != 0)
                                        ::Delete
                                
                                1 Reply Last reply
                                0
                                • M Member 2965471

                                  i've tried, when i maximize the window bitmap disappear and when i restoring the window the bitmap reappears, it seems that the coordinates are different when the window is maximize, it may be true?

                                  D Offline
                                  D Offline
                                  David Crow
                                  wrote on last edited by
                                  #16

                                  Member 2965471 wrote:

                                  it seems that the coordinates are different when the window is maximize, it may be true?

                                  That depends on if you are using screen or client coordinates. With the former, the coordinates will always change. With the latter, top and left will always be 0.

                                  "One man's wage rise is another man's price increase." - Harold Wilson

                                  "Fireproof doesn't mean the fire will never come. It means when the fire comes that you will be able to withstand it." - Michael Simmons

                                  "Some people are making such thorough preparation for rainy days that they aren't enjoying today's sunshine." - William Feather

                                  1 Reply Last reply
                                  0
                                  • M Member 2965471

                                    Hi, this is the code:

                                    case WM_MOUSEMOVE:
                                    pt.x = LOWORD(lParam);
                                    pt.y = HIWORD(lParam);
                                    InvalidateRect(hWnd,NULL,TRUE);
                                    break;

                                    case WM_PAINT:
                                    hdc = BeginPaint(hWnd, &ps);

                                    memDC = CreateCompatibleDC(hdc);

                                    SelectObject(memDC,hbmp);

                                    GetObject(bmp, sizeof(bm), &bm);

                                    GetClientRect(hWnd,&rcc);

                                    StretchBlt(hdc,
                                    0,0, rcc.right,rcc.bottom,
                                    memDC,
                                    0,0,bm.bmWidth, bm.bmHeight,
                                    SRCCOPY);

                                    //onMouseMove
                                    MoveToEx(hdc, pt.x , 0 , NULL);
                                    LineTo(hdc, pt.x, rcc.bottom);
                                    MoveToEx(hdc, 0, pt.y, NULL);
                                    LineTo(hdc, rcc.right, pt.y);

                                    how can i draw lines on mouse move without repainting the background bitmap? There's a way to "fix" the bitmap on background and repaint only lines?

                                    B Offline
                                    B Offline
                                    bob16972
                                    wrote on last edited by
                                    #17

                                    It almost sounds like your asking how to rubberband a line. If not, ignore my comments but if you are looking to have the bitmap drawn in your WM_PAINT handler and you want to stretch a line from some starting point to where the mouse cursor is, this is normally referred to as "rubberbanding". Here's an old post of mine describing how to rubberband a line (btw, the idea is basically the same for a rectangle). Rubberbanding Lines[^] NOTE: One you commit to the line being at some location permanently, you would need to keep track of that object and also draw it in your WM_PAINT handler but only after you no longer want to rubberband it. I reference the book by Ivor Horton which is truly a must have if your going to pursue a drawing project as he basically builds one in the second half of the book. Also, this is all using MFC but the concepts can be easily adjusted to WIN32.

                                    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