VC实现图片拖拽及动画

该程序实现鼠标拖拽图像,图像匀减速平移,碰撞反弹效果,程序界面如下:

VC实现图片拖拽及动画_第1张图片

基础知识

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 { 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 /*=NULL*/) : 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;//初始化鼠标按下状态 isSelect = FALSE;//初始化选中状态 f = 0.05;//初始化阻力 dv = 5;//初始化动力增量 } 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 //对话框初始化 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); } else { 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) { // TODO: Add your message handler code here and/or call default 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) { // TODO: Add your message handler code here and/or call default 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::GetHandleFromPath(CString path) { hBitmap= (HBITMAP)::LoadImage(AfxGetInstanceHandle(),path,IMAGE_BITMAP,0,0,LR_CREATEDIBSECTION|LR_LOADFROMFILE);//创建位图句柄 } //获取位图对象 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; } //定时器事件 void CMovePictureDlg::OnTimer(UINT nIDEvent) { // TODO: Add your message handler code here and/or call default if(abs(vx)>abs(vy))//当水平速度大于垂直速度时,只改变水平方向增量 { 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))//当水平速度小于垂直速度时,只改变垂直方向增量 { if(picRect.top==clientRect.top) { vy=-vy; } if(picRect.top==clientRect.bottom-m_nBmpHeight) { vy=-vy; } 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) { 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);//重置图片位置 CDialog::OnTimer(nIDEvent); } void CMovePictureDlg::OnDestroy() { CDialog::OnDestroy(); // TODO: Add your message handler code here this->KillTimer(1);//销毁定时器 }

1.在对话框中添加一PictureBox控件,设置IDIDC_PICTUREBOX,类型为位图

2.创建CPictureBox类继承于CStatic

3.在对话框类中声明

CPictureBox* pictureBox;//图片控件

4.在对话框类的OnInitDialog方法中获得控件指针

pictureBox = (CPictureBox*)GetDlgItem(IDC_PICTUREBOX);//获得图片框指针

5.显示位图

pictureBox->SetBitmap(hBitmap);//显示位图

6.设置控件位置

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

你可能感兴趣的:(Microsoft,System,insert,dialog,Path,initialization)