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.
  • 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