VC image drag and drop and animation examples

  • 2020-04-02 01:27:08
  • OfStack

Basic knowledge of
1. Use of PictureBox control
Load the bitmap file


1. Get the bitmap handle from the file path


//Gets the bitmap handle & NBSP;
void CMovePictureDlg::GetHandleFromPath(CString path)  
{  
    hBitmap= (HBITMAP)::LoadImage(AfxGetInstanceHandle(),path,IMAGE_BITMAP,0,0,LR_CREATEDIBSECTION|LR_LOADFROMFILE);//Create bitmap handle & NBSP;
} 

2. Create bitmap objects and obtain bitmap information through the bitmap handle

//Getting a bitmap object & NBSP;

void CMovePictureDlg::GetBitMap(HBITMAP hBitmap)  

{  

   m_BitMap.Attach(hBitmap);//Creates a bitmap object & NBSP; through a bitmap handle;

  
    //Getting image information & NBSP;

    BITMAPINFOHEADER bminfo;   

    m_BitMap.GetObject(sizeof(bminfo),&bminfo);   

  
//Get bitmap width and height & NBSP;

    m_nBmpWidth=bminfo.biWidth;  

    m_nBmpHeight=bminfo.biHeight;  

} 

Implementation steps:
1. Create a dialog project named MovePicture
2. Open the dialog box and drag in a PictureBox control, set the ID as: IDC_PICTUREBOX, set the type as: bitmap
3. Drag in two static text controls and two edit box controls. The static text control titles are: input momentum coefficient:, input resistance coefficient:, edit box ids are: IDC_EDITDV, IDC_EDITF, IDC_EDITDV, IDC_EDITDV, m_editDV, IDC_EDITF, m_editF
4. Implementation code
The header file

// MovePictureDlg.h : header file  
//  
#include "PictureBox.h"  

#if !defined(AFX_MOVEPICTUREDLG_H__6FFC1DDF_478C_43D6_B854_4D51E98D5E50__INCLUDED_) 
#define AFX_MOVEPICTUREDLG_H__6FFC1DDF_478C_43D6_B854_4D51E98D5E50__INCLUDED_ 

#if _MSC_VER > 1000  
#pragma once  
#endif // _MSC_VER > 1000  

/////////////////////////////////////////////////////////////////////////////  
// CMovePictureDlg dialog  

class CMovePictureDlg : public CDialog  
{  
// Construction  
public:  
    void GetBitMap(HBITMAP hBitmap);  
    void GetHandleFromPath(CString path);  
    void SetPicRect(int x,int y);  
    void SetSysPath();  
    CMovePictureDlg(CWnd* pParent = NULL);  // standard constructor  

// Dialog Data  
    //{{AFX_DATA(CMovePictureDlg)  
    enum { IDD = IDD_MOVEPICTURE_DIALOG };  
    CEdit   m_editF;  
    CEdit   m_editDV;  
    //}}AFX_DATA  

    // ClassWizard generated virtual function overrides  
    //{{AFX_VIRTUAL(CMovePictureDlg)  
    protected:  
    virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support  
    //}}AFX_VIRTUAL  

// Implementation  
protected:  
    HICON m_hIcon;  

    // Generated message map functions  
    //{{AFX_MSG(CMovePictureDlg)  
    virtual BOOL OnInitDialog();  
    afx_msg void OnSysCommand(UINT nID, LPARAM lParam);  
    afx_msg void OnPaint();  
    afx_msg HCURSOR OnQueryDragIcon();  
    afx_msg void OnLButtonDown(UINT nFlags, CPoint point);  
    afx_msg void OnMouseMove(UINT nFlags, CPoint point);  
    afx_msg void OnLButtonUp(UINT nFlags, CPoint point);  
    afx_msg void OnTimer(UINT nIDEvent);  
    afx_msg void OnDestroy();  
    //}}AFX_MSG  
    DECLARE_MESSAGE_MAP()  
private:  
    CString sysPath;//Save system path & NBSP;
    CString bmpPath;//Bitmap path & NBSP;

    HBITMAP hBitmap;//Bitmap handle & NBSP;
    CBitmap m_BitMap;//Bitmap object & NBSP;
    int m_nBmpWidth;//Bitmap width & NBSP;
    int m_nBmpHeight;//Bitmap height & NBSP;

    CPictureBox* pictureBox;//Picture control & NBSP;
    CRect picRect;//Control occupied area & NBSP;
    BOOL isSelect;//Determines whether the control is selected & NBSP;

    BOOL isDown;//Judge whether the mouse is pressed & NBSP;

    CPoint oldPoint;//Original mouse position & NBSP;

    CPoint startPoint;//Move the starting position & noon;

    SYSTEMTIME startTime;//Start time & NBSP;
    SYSTEMTIME endTime;//End time & NBSP;

    double vx;//Velocity in the x direction & NBSP;
    double vy;//Velocity in the y direction & NBSP;

    double f;//Resistance & have spent
    double dv;//Dynamic increment & NBSP;

    CRect clientRect;//Client area & NBSP;
};  

//{{AFX_INSERT_LOCATION}}  
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.  

#endif // !defined(AFX_MOVEPICTUREDLG_H__6FFC1DDF_478C_43D6_B854_4D51E98D5E50__INCLUDED_) 

Implementation file

// MovePictureDlg.cpp : implementation file  
//  

#include "stdafx.h"  
#include "MovePicture.h"  
#include "MovePictureDlg.h"  
#include <math.h>  

#ifdef _DEBUG  
#define new DEBUG_NEW  
#undef THIS_FILE  
static char THIS_FILE[] = __FILE__;  
#endif  

/////////////////////////////////////////////////////////////////////////////  
// CAboutDlg dialog used for App About  

//Calculate the time difference & noon; & have spent
inline   __int64   TimeDiff(SYSTEMTIME left,SYSTEMTIME right)   
{   
    CTime   tmLeft(left.wYear,left.wMonth,left.wDay,0,0,0);   
    CTime   tmRight(left.wYear,left.wMonth,left.wDay,0,0,0);   
    CTimeSpan   sp;   
    sp   =   tmLeft   -   tmRight;//If calculating the date is tricky, let the MFC do it & NBSP; & have spent
    long   lLMinllis   =   (left.wHour*3600   +   left.wMinute*60   +   left.wSecond)*1000   +   left.wMilliseconds;   
    long   lRMinllis   =   (right.wHour*3600   +   right.wMinute*60   +   right.wSecond)*1000   +   right.wMilliseconds;   

    return   (__int64)sp.GetDays()*86400000   +   (lLMinllis   -   lRMinllis);  
}  

class CAboutDlg : public CDialog  
{  
public:  
    CAboutDlg();  

// Dialog Data  
    //{{AFX_DATA(CAboutDlg)  
    enum { IDD = IDD_ABOUTBOX };  
    //}}AFX_DATA  

    // ClassWizard generated virtual function overrides  
    //{{AFX_VIRTUAL(CAboutDlg)  
    protected:  
    virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support  
    //}}AFX_VIRTUAL  

// Implementation  
protected:  
    //{{AFX_MSG(CAboutDlg)  
    //}}AFX_MSG  
    DECLARE_MESSAGE_MAP()  
};  

CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)  
{  
    //{{AFX_DATA_INIT(CAboutDlg)  
    //}}AFX_DATA_INIT  
}  

void CAboutDlg::DoDataExchange(CDataExchange* pDX)  
{  
    CDialog::DoDataExchange(pDX);  
    //{{AFX_DATA_MAP(CAboutDlg)  
    //}}AFX_DATA_MAP  
}  

BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)  
    //{{AFX_MSG_MAP(CAboutDlg)  
        // No message handlers  
    //}}AFX_MSG_MAP  
END_MESSAGE_MAP()  

/////////////////////////////////////////////////////////////////////////////  
// CMovePictureDlg dialog  

CMovePictureDlg::CMovePictureDlg(CWnd* pParent )  
    : CDialog(CMovePictureDlg::IDD, pParent)  
{  
    //{{AFX_DATA_INIT(CMovePictureDlg)  
    //}}AFX_DATA_INIT  
    // Note that LoadIcon does not require a subsequent DestroyIcon in Win32  
    m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);  

    isDown = FALSE;//Initializing the mouse pressed state & NBSP;
    isSelect = FALSE;//Initializing the checked state & NBSP;
    f = 0.05;//Initialization resistance & NBSP;
    dv = 5;//Initializing dynamic increment & NBSP;
}  

void CMovePictureDlg::DoDataExchange(CDataExchange* pDX)  
{  
    CDialog::DoDataExchange(pDX);  
    //{{AFX_DATA_MAP(CMovePictureDlg)  
    DDX_Control(pDX, IDC_EDITF, m_editF);  
    DDX_Control(pDX, IDC_EDITDV, m_editDV);  
    //}}AFX_DATA_MAP  
}  

BEGIN_MESSAGE_MAP(CMovePictureDlg, CDialog)  
    //{{AFX_MSG_MAP(CMovePictureDlg)  
    ON_WM_SYSCOMMAND()  
    ON_WM_PAINT()  
    ON_WM_QUERYDRAGICON()  
    ON_WM_LBUTTONDOWN()  
    ON_WM_MOUSEMOVE()  
    ON_WM_LBUTTONUP()  
    ON_WM_TIMER()  
    ON_WM_DESTROY()  
    //}}AFX_MSG_MAP  
END_MESSAGE_MAP()  

/////////////////////////////////////////////////////////////////////////////  
// CMovePictureDlg message handlers  

//Dialog initializing & NBSP;
BOOL CMovePictureDlg::OnInitDialog()  
{  
    CDialog::OnInitDialog();  

    // Add "About ... " menu item to system menu.  

    // IDM_ABOUTBOX must be in the system command range.  
    ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);  
    ASSERT(IDM_ABOUTBOX < 0xF000);  

    CMenu* pSysMenu = GetSystemMenu(FALSE);  
    if (pSysMenu != NULL)  
    {  
        CString strAboutMenu;  
        strAboutMenu.LoadString(IDS_ABOUTBOX);  
        if (!strAboutMenu.IsEmpty())  
        {  
            pSysMenu->AppendMenu(MF_SEPARATOR);  
            pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);  
        }  
    }  

    // Set the icon for this dialog.  The framework does this automatically  
    //  when the application's main window is not a dialog  
    SetIcon(m_hIcon, TRUE);         // Set big icon  
    SetIcon(m_hIcon, FALSE);        // Set small icon  

    // TODO: Add extra initialization here  

    pictureBox = (CPictureBox*)GetDlgItem(IDC_PICTUREBOX);//Get a picture frame pointer & NBSP;

    SetSysPath();//Set system path & NBSP;

    bmpPath = sysPath+"//image.bmp";// Set the bitmap path   

    GetHandleFromPath(bmpPath);//Create bitmap handle & NBSP;

    GetBitMap(hBitmap);//Getting a bitmap & NBSP;

    //Set the bitmap control area & PI;
    SetPicRect(0,0);  

    pictureBox->MoveWindow(picRect);//Set the control position & NBSP;

    //Sets the value of the text box & NBSP;
    CString strDV,strF;  
    strDV.Format("%f",dv);  
    strF.Format("%f",f);  

    m_editDV.SetWindowText(strDV);  
    m_editF.SetWindowText(strF);  
    return TRUE;  // return TRUE  unless you set the focus to a control  
}  

void CMovePictureDlg::OnSysCommand(UINT nID, LPARAM lParam)  
{  
    if ((nID & 0xFFF0) == IDM_ABOUTBOX)  
    {  
        CAboutDlg dlgAbout;  
        dlgAbout.DoModal();  
    }  
    else  
    {  
        CDialog::OnSysCommand(nID, lParam);  
    }  
}  

// If you add a minimize button to your dialog, you will need the code below  
//  to draw the icon.  For MFC applications using the document/view model,  
//  this is automatically done for you by the framework.  

//Redraw function & NBSP;
void CMovePictureDlg::OnPaint()   
{  
    if (IsIconic())  
    {  
        CPaintDC dc(this); // device context for painting  

        SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);  

        // Center icon in client rectangle  
        int cxIcon = GetSystemMetrics(SM_CXICON);  
        int cyIcon = GetSystemMetrics(SM_CYICON);  
        CRect rect;  
        GetClientRect(&rect);  
        int x = (rect.Width()  �  cxIcon + 1) / 2;  
        int y = (rect.Height()  �  cyIcon + 1) / 2;  

        // Draw the icon  
        dc.DrawIcon(x, y, m_hIcon);  
    }  
    else  
    {  

        this->GetClientRect(&clientRect);//Obtain client area size & NBSP;

        pictureBox->SetBitmap(hBitmap);//Display bitmap & NBSP;
        CDialog::OnPaint();  
    }  

}  

// The system calls this to obtain the cursor to display while the user drags  
//  the minimized window.  
HCURSOR CMovePictureDlg::OnQueryDragIcon()  
{  
    return (HCURSOR) m_hIcon;  
}  

//Press the left mouse button & NBSP;
void CMovePictureDlg::OnLButtonDown(UINT nFlags, CPoint point)   
{  
    // TODO: Add your message handler code here and/or call default  

    isDown=TRUE;//Mouse down & NBSP;

    if(PtInRect(picRect,point))//Press the button in the picture area.
    {  
        isSelect=TRUE;//Picture checked & NBSP;

        oldPoint = point;//Record the mouse position & NBSP;
        startPoint = point;//Record the starting position of the mouse & PI;

        GetSystemTime(&startTime);//Get the current time & NBSP;
    }  

    CDialog::OnLButtonDown(nFlags, point);  
}  

//Left mouse button up & NBSP;
void CMovePictureDlg::OnLButtonUp(UINT nFlags, CPoint point)   
{  
    // TODO: Add your message handler code here and/or call default  

    isDown=FALSE;//Mouse snap & NBSP;

    if(isSelect)  
    {  
        CString strDV,strF;  
        m_editDV.GetWindowText(strDV);  
        m_editF.GetWindowText(strF);  

        dv = atof(strDV);  
        f = atof(strF);   

        isSelect=FALSE;//Release picture & NBSP;

        GetSystemTime(&endTime);//Get the current time & NBSP;

        double dx = point.x-startPoint.x;//Calculate the X-axis displacement & PI;
        double dy = point.y-startPoint.y;//Calculate y axis displacement & PI;

        int s = TimeDiff(endTime,startTime);//Calculate the time difference & noon;

        //double r = sqrt(dx*dx+dy*dy);// Calculate the mouse displacement length   
        //double v=r/s;// Average velocity   

        vx=dv*dx/s;//Average X-axis velocity & NBSP;
        vy=dv*dy/s;//Y axis average speed & NBSP;

        SetTimer(1,1,NULL);//Set a timer & NBSP;
    }  

    CDialog::OnLButtonUp(nFlags, point);  
}  

//Mouse movement & NBSP;
void CMovePictureDlg::OnMouseMove(UINT nFlags, CPoint point)   
{  
    // TODO: Add your message handler code here and/or call default  

    if(isDown&&isSelect)//Move in mouse down mode & NBSP;
    {  
        int dx = point.x-oldPoint.x;//Calculate the relative change of x value & PI;
        int dy = point.y-oldPoint.y;//Calculate the relative change in y value & PI;

        //Reset PictureBox location & NBSP;
        picRect.left=picRect.left+dx;  
        picRect.top=picRect.top+dy;  

        SetPicRect(picRect.left,picRect.top);//Reset image position & NBSP;

        pictureBox->MoveWindow(picRect.left,picRect.top,m_nBmpWidth,m_nBmpHeight);//Changing the size of the picture frame & NBSP;

        oldPoint=point;//Reset the original coordinates & NBSP;
    }  

    CDialog::OnMouseMove(nFlags, point);  
}  

//Set system path & NBSP;
void CMovePictureDlg::SetSysPath()  
{  
    //Gets the current path and stores it in the character array strBuff & PI.
    char strBuff[256];  
    GetCurrentDirectory(256,strBuff);   
    sysPath.Format("%s",strBuff);//Saves the path to the global variable & PI;
}  

//Set control area & NBSP;
void CMovePictureDlg::SetPicRect(int x, int y)  
{  
    picRect.top=y;  
    picRect.bottom=picRect.top+m_nBmpHeight;  
    picRect.left=x;  
    picRect.right=picRect.left+m_nBmpWidth;  
}  

//Gets the bitmap handle & NBSP;
void CMovePictureDlg::GetHandleFromPath(CString path)  
{  
    hBitmap= (HBITMAP)::LoadImage(AfxGetInstanceHandle(),path,IMAGE_BITMAP,0,0,LR_CREATEDIBSECTION|LR_LOADFROMFILE);//Create bitmap handle & NBSP;
}  

//Getting a bitmap object & NBSP;
void CMovePictureDlg::GetBitMap(HBITMAP hBitmap)  
{  
   m_BitMap.Attach(hBitmap);//Creates a bitmap object & NBSP; through a bitmap handle;

    //Getting image information & NBSP;
    BITMAPINFOHEADER bminfo;   
    m_BitMap.GetObject(sizeof(bminfo),&bminfo);   

    //Get bitmap width and height & NBSP;
    m_nBmpWidth=bminfo.biWidth;  
    m_nBmpHeight=bminfo.biHeight;  
}  

//Timer event & NBSP;
void CMovePictureDlg::OnTimer(UINT nIDEvent)   
{  
    // TODO: Add your message handler code here and/or call default  

    if(abs(vx)>abs(vy))//When the horizontal velocity is greater than the vertical velocity, only the increment of the horizontal direction is changed.
    {  
        if(picRect.left==clientRect.left)  
        {  
            vx=-vx;  
        }  
        if(picRect.left==clientRect.right-m_nBmpWidth)  
        {  
            vx=-vx;  
        }  
        picRect.left+=vx;  
    }  
    else if(abs(vx)<abs(vy))//When the horizontal velocity is less than the vertical velocity, only the vertical increment & NBSP; is changed.
    {  
        if(picRect.top==clientRect.top)  
        {  
            vy=-vy;  
        }  
        if(picRect.top==clientRect.bottom-m_nBmpHeight)  
        {  
            vy=-vy;  
        }  
        picRect.top+=vy;  
    }  

    //Border judgment & NBSP;
    if(picRect.left<clientRect.left)  
    {  
        picRect.left=clientRect.left;  
    }  
    if(picRect.left>clientRect.right-m_nBmpWidth)  
    {  
        picRect.left=clientRect.right-m_nBmpWidth;  
    }  
    if(picRect.top<clientRect.top)  
    {  
        picRect.top=clientRect.top;  
    }  
    if(picRect.top>clientRect.bottom-m_nBmpHeight)  
    {  
        picRect.top=clientRect.bottom-m_nBmpHeight;  
    }  

    pictureBox->MoveWindow(picRect.left,picRect.top,m_nBmpWidth,m_nBmpHeight);//Changing the size of the picture frame & NBSP;

    //Incremental decline, uniform deceleration movement & NBSP;
    if(vx>0)  
    {  
        vx-=f;  
        if(vx<0)  
        {  
            vx=0;  
        }  
    }  
    else if(vx<0)  
    {  
        vx+=f;  
        if(vx>0)  
        {  
            vx=0;  
        }  
    }  

    if(vy>0)  
    {  
        vy-=f;  
        if(vy<0)  
        {  
            vy=0;  
        }  
    }  
    else if(vy<0)  
    {  
        vy+=f;  
        if(vy>0)  
        {  
            vy=0;  
        }  
    }  

    SetPicRect(picRect.left,picRect.top);//Reset image position & NBSP;

    CDialog::OnTimer(nIDEvent);  
}  

void CMovePictureDlg::OnDestroy()   
{  
    CDialog::OnDestroy();  

    // TODO: Add your message handler code here  
    this->KillTimer(1);//Destruction timer & NBSP;
} 

1. Add a PictureBox control in the dialog box, set the ID as IDC_PICTUREBOX, type as bitmap
2. Create CPictureBox class inherited from CStatic
Declare in the dialog class
CPictureBox * pictureBox; // picture control
4. Get the control pointer in the OnInitDialog method of the dialog class
PictureBox = (CPictureBox *) GetDlgItem (IDC_PICTUREBOX); // get the picture box pointer
5. Display bitmaps
PictureBox - > SetBitmap (hBitmap); // display bitmap
6. Set the control location
PictureBox - > MoveWindow (picRect); // sets the control location


Related articles: