-
November 1st, 2006, 02:08 AM
#1
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
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|