CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 1 of 1

Threaded View

  1. #1
    Join Date
    Feb 2000
    Location
    Indore, India
    Posts
    1,046

    Windows SDK GDI: How do I drag an image?

    Q: How do I drag an image?

    A: Dragging an image is a multistage process where one has to first erase the image previously drawn then move the coordinates of the image to a new position and finally redraw the image at the new position. Apart from that, one has to handle the mouse messages 'WM_LBUTTONDOWN', 'WM_MOUSEMOVE' and 'WM_LBUTTONUP'. Here are the basic steps to have the effect of dragging an image using mouse.
    • Data members are to be defined, which are to be used in view class, like the image as a 'CBitmap' object point of insertion of the image and pointer to the cursor point.
      Code:
      public:
        CBitmap bmImage;
        CPoint ptImage, *pCursor;
      I have chosen the cursor point variable as a pointer since I can set it to 'NULL' when the image is not being moved.


    • Initialise the variables in view constructor.
      Code:
      ptImage = CPoint(0, 0);
      bmImage.LoadBitmap(IDB_BITMAP);
      pCursor = NULL;

    • Delete the 'CBitmap' object in view destructor. Furthermore, delete pointer to cursor, if it is not 'NULL'.
      Code:
      bmImage.DeleteObject();
      if (pCursor)
        delete pCursor;

    • Paint the image in 'OnDraw()' member function of view.
      Code:
      CDC MemDC;
      if (MemDC.CreateCompatibleDC(pDC))
      {
        CBitmap* pBM = MemDC.SelectObject(&bmImage);
        BITMAP objBM;
        bmImage.GetBitmap(&objBM);
        pDC->BitBlt(ptImage.x, ptImage.y, objBM.bmWidth, objBM.bmHeight, &MemDC, 0, 0, SRCCOPY);
        MemDC.SelectObject(pBM);
        MemDC.DeleteDC();
      }
      Now we have to identify a click inside the image and make movements when cursor is dragged while pressed.


    • In 'OnLButtonDown()' function (of 'WM_LBUTTONDOWN' message handler) check whether the mouse click is within the image and note the cursor position if it is.
      Code:
      BITMAP objBM;
      bmImage.GetBitmap(&objBM);
      CRect rectImage(ptImage, CSize(objBM.bmWidth, objBM.bmHeight));
      if (rectImage.PtInRect(point))
      {
        pCursor = new CPoint;
        *pCursor = point;
      }

    • Check in 'OnMouseMove()' function (of 'WM_MOUSEMOVE' message) whether the image is being dragged (pointer to cursor not 'NULL') and update its position by calling a forced repaint.
      Code:
      if (pCursor)
      {
        BITMAP objBM;
        bmImage.GetBitmap(&objBM);
        CRect rectPrev(ptImage, CSize(objBM.bmWidth, objBM.bmHeight));
        ptImage.x += point.x - pCursor->x;
        ptImage.y += point.y - pCursor->y;
        CRect rectImage(ptImage, CSize(objBM.bmWidth, objBM.bmHeight));
        *pCursor = point;
        InvalidateRect(rectPrev);
        InvalidateRect(rectImage);
        UpdateWindow();
      }
      Both the 'InvalidateRect()' calls can be combined to a single 'Invalidate()' without bothering to evaluate the rectangles to be invalidated. But this will give a flickering effect each time you move the image since the whole client area will be invalidated.


    • And finally, clean up the pointer to cursor position in 'OnLButtonUp()' function (of 'WM_LBUTTONUP' message).
      Code:
      if (pCursor)
      {
        delete pCursor;
        pCursor = NULL;
      }
      This will give a smooth effect of dragging when the bitmap image is small.

      One can also store the background image before a bitmap is displayed and reinsert the background image when the image is moved. Though result is smoother in this case, it needs more involved coding.



    Last edited by Andreas Masur; November 4th, 2006 at 01:46 PM.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured