天天看點

VC實作圖檔拖拽及動畫

基礎知識 

1.PictureBox控件的使用 

2.加載位圖檔案 

1.通過檔案路徑獲得位圖句柄 

//獲得位圖句柄  

void CMovePictureDlg::GetHandleFromPath(CString path)  

{  

    hBitmap= (HBITMAP)::LoadImage(AfxGetInstanceHandle(),path,IMAGE_BITMAP,0,0,LR_CREATEDIBSECTION|LR_LOADFROMFILE);//建立位圖句柄  

2.通過位圖句柄建立位圖對象并獲得位圖資訊 

//擷取位圖對象  

void CMovePictureDlg::GetBitMap(HBITMAP hBitmap)  

   m_BitMap.Attach(hBitmap);//通過位圖句柄建立位圖對象  

    //擷取圖像資訊  

    BITMAPINFOHEADER bminfo;   

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

//擷取位圖寬高  

    m_nBmpWidth=bminfo.biWidth;  

    m_nBmpHeight=bminfo.biHeight;  

實作步驟: 

1.建立一個對話框工程命名為MovePicture 

2.打開對話框資源拖入一個PictureBox控件,設定ID為:IDC_PICTUREBOX,設定類型為:位圖 

3.拖入兩個靜态文本控件和兩個編輯框控件,靜态文本控件标題分别為:輸入動量系數:、輸入阻力系數:,編輯框ID分别為:IDC_EDITDV、IDC_EDITF,為IDC_EDITDV關聯變量為:m_editDV,為IDC_EDITF關聯變量為:m_editF 

4.實作代碼 

頭檔案 

// 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;//儲存系統路徑  

    CString bmpPath;//位圖路徑  

    HBITMAP hBitmap;//位圖句柄  

    CBitmap m_BitMap;//位圖對象  

    int m_nBmpWidth;//位圖寬度  

    int m_nBmpHeight;//位圖高度  

    CPictureBox* pictureBox;//圖檔控件  

    CRect picRect;//控件所占區域  

    BOOL isSelect;//判斷控件是否被選中  

    BOOL isDown;//判斷滑鼠是否按下  

    CPoint oldPoint;//滑鼠原始位置  

    CPoint startPoint;//移動起始位置  

    SYSTEMTIME startTime;//開始時間  

    SYSTEMTIME endTime;//結束時間  

    double vx;//x方向速度  

    double vy;//y方向速度  

    double f;//阻力  

    double dv;//動力增量  

    CRect clientRect;//客戶區域  

};  

//{{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_) 

實作檔案 

// 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  

//計算時間差   

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;//計算日期比較麻煩,就交給MFC去做吧   

    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  

    CAboutDlg();  

    //{{AFX_DATA(CAboutDlg)  

    enum { IDD = IDD_ABOUTBOX };  

    //{{AFX_VIRTUAL(CAboutDlg)  

    //{{AFX_MSG(CAboutDlg)  

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::CMovePictureDlg(CWnd* pParent /*=NULL*/)  

    : CDialog(CMovePictureDlg::IDD, pParent)  

    //{{AFX_DATA_INIT(CMovePictureDlg)  

    // Note that LoadIcon does not require a subsequent DestroyIcon in Win32  

    m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);  

    isDown = FALSE;//初始化滑鼠按下狀态  

    isSelect = FALSE;//初始化選中狀态  

    f = 0.05;//初始化阻力  

    dv = 5;//初始化動力增量  

void CMovePictureDlg::DoDataExchange(CDataExchange* pDX)  

    //{{AFX_DATA_MAP(CMovePictureDlg)  

    DDX_Control(pDX, IDC_EDITF, m_editF);  

    DDX_Control(pDX, IDC_EDITDV, m_editDV);  

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()  

// CMovePictureDlg message handlers  

//對話框初始化  

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);//獲得圖檔框指針  

    SetSysPath();//設定系統路徑  

    bmpPath = sysPath+"//image.bmp";//設定位圖路徑  

    GetHandleFromPath(bmpPath);//建立位圖句柄  

    GetBitMap(hBitmap);//獲得位圖  

    //設定位圖控件區域  

    SetPicRect(0,0);  

    pictureBox->MoveWindow(picRect);//設定控件位置  

    //設定文本框值  

    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.  

//重繪函數  

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);  

        this->GetClientRect(&clientRect);//獲得客戶區域大小  

        pictureBox->SetBitmap(hBitmap);//顯示位圖  

        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;  

//滑鼠左鍵按下  

void CMovePictureDlg::OnLButtonDown(UINT nFlags, CPoint point)   

    // TODO: Add your message handler code here and/or call default  

    isDown=TRUE;//滑鼠按下  

    if(PtInRect(picRect,point))//滑鼠在圖檔區域按下  

        isSelect=TRUE;//圖檔選中  

        oldPoint = point;//記錄下滑鼠位置  

        startPoint = point;//記錄下滑鼠起始位置  

        GetSystemTime(&startTime);//得到目前時間  

    CDialog::OnLButtonDown(nFlags, point);  

//滑鼠左鍵彈起  

void CMovePictureDlg::OnLButtonUp(UINT nFlags, CPoint point)   

    isDown=FALSE;//滑鼠彈起  

    if(isSelect)  

        CString strDV,strF;  

        m_editDV.GetWindowText(strDV);  

        m_editF.GetWindowText(strF);  

        dv = atof(strDV);  

        f = atof(strF);   

        isSelect=FALSE;//釋放圖檔  

        GetSystemTime(&endTime);//得到目前時間  

        double dx = point.x-startPoint.x;//計算x軸位移  

        double dy = point.y-startPoint.y;//計算y軸位移  

        int s = TimeDiff(endTime,startTime);//計算時間差  

        //double r = sqrt(dx*dx+dy*dy);//計算滑鼠位移長度  

        //double v=r/s;//求平均速度  

        vx=dv*dx/s;//x軸平均速度  

        vy=dv*dy/s;//y軸平均速度  

        SetTimer(1,1,NULL);//設定定時器  

    CDialog::OnLButtonUp(nFlags, point);  

//滑鼠移動  

void CMovePictureDlg::OnMouseMove(UINT nFlags, CPoint point)   

    if(isDown&&isSelect)//在滑鼠按下狀态下移動  

        int dx = point.x-oldPoint.x;//計算x值的相對變化  

        int dy = point.y-oldPoint.y;//計算y值的相對變化  

        //重新設定PictureBox位置  

        picRect.left=picRect.left+dx;  

        picRect.top=picRect.top+dy;  

        SetPicRect(picRect.left,picRect.top);//重置圖檔位置  

        pictureBox->MoveWindow(picRect.left,picRect.top,m_nBmpWidth,m_nBmpHeight);//改變圖檔框大小  

        oldPoint=point;//重置原始坐标  

    CDialog::OnMouseMove(nFlags, point);  

//設定系統路徑  

void CMovePictureDlg::SetSysPath()  

    //擷取目前路徑,儲存到字元數組strBuff中  

    char strBuff[256];  

    GetCurrentDirectory(256,strBuff);   

    sysPath.Format("%s",strBuff);//将路徑儲存到全局變量中  

//設定控件區域  

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;  

    //擷取位圖寬高  

//定時器事件  

void CMovePictureDlg::OnTimer(UINT nIDEvent)   

    if(abs(vx)>abs(vy))//當水準速度大于垂直速度時,隻改變水準方向增量  

        if(picRect.left==clientRect.left)  

            vx=-vx;  

        if(picRect.left==clientRect.right-m_nBmpWidth)  

        picRect.left+=vx;  

    else if(abs(vx)<abs(vy))//當水準速度小于垂直速度時,隻改變垂直方向增量  

        if(picRect.top==clientRect.top)  

            vy=-vy;  

        if(picRect.top==clientRect.bottom-m_nBmpHeight)  

        picRect.top+=vy;  

    //邊界判斷  

    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);//改變圖檔框大小  

    //增量遞減,勻減速運動  

    if(vx>0)  

        vx-=f;  

        if(vx<0)  

            vx=0;  

    else if(vx<0)  

        vx+=f;  

        if(vx>0)  

    if(vy>0)  

        vy-=f;  

        if(vy<0)  

            vy=0;  

    else if(vy<0)  

        vy+=f;  

        if(vy>0)  

    SetPicRect(picRect.left,picRect.top);//重置圖檔位置  

    CDialog::OnTimer(nIDEvent);  

void CMovePictureDlg::OnDestroy()   

    CDialog::OnDestroy();  

    // TODO: Add your message handler code here  

    this->KillTimer(1);//銷毀定時器  

1.在對話框中添加一PictureBox控件,設定ID為IDC_PICTUREBOX,類型為位圖 

2.建立CPictureBox類繼承于CStatic 

3.在對話框類中聲明 

CPictureBox* pictureBox;//圖檔控件 

4.在對話框類的OnInitDialog方法中獲得控件指針 

pictureBox = (CPictureBox*)GetDlgItem(IDC_PICTUREBOX);//獲得圖檔框指針 

5.顯示位圖 

pictureBox->SetBitmap(hBitmap);//顯示位圖 

6.設定控件位置 

pictureBox->MoveWindow(picRect);//設定控件位置

繼續閱讀