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
{
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控件,设置ID为IDC_PICTUREBOX,类型为位图
2.创建CPictureBox类继承于CStatic
3.在对话框类中声明
CPictureBox* pictureBox;//图片控件
4.在对话框类的OnInitDialog方法中获得控件指针
pictureBox = (CPictureBox*)GetDlgItem(IDC_PICTUREBOX);//获得图片框指针
5.显示位图
pictureBox->SetBitmap(hBitmap);//显示位图
6.设置控件位置
pictureBox->MoveWindow(picRect);//设置控件位置
VC实现图片拖拽及动画的更多相关文章
- CSS 奇思妙想 | 使用 resize 实现强大的图片拖拽切换预览功能
本文将介绍一个非常有意思的功能,使用纯 CSS 利用 resize 实现强大的图片切换预览功能.类似于这样: 思路 首先,要实现这样一个效果如果不要求可以拖拽,其实有非常多的办法. 将两张图片叠加在一 ...
- canvas 图片拖拽旋转之二——canvas状态保存(save和restore)
引言 在上一篇日志“canvas 图片拖拽旋转之一”中,对坐标转换有了比较深入的了解,但是仅仅利用坐标转换实现的拖拽旋转,会改变canvas坐标系的状态,从而影响画布上其他元素的绘制.因此,这个时候需 ...
- canvas 图片拖拽旋转之一——坐标转换translate
引言 对canvas中绘制的图片进行旋转操作,需要使用ctx.translate变换坐标系,将图片旋转的基点设为坐标系的原点,然后ctx.rotate旋转. 这个时候,因为canvas坐标系发生了旋转 ...
- HTML5图片拖拽预览原理及实现
一.前言 这两天恰好有一位同事问我怎样做一个图片预览功能.作为现代人的我们首先想到的当然是HTML5啦,其实HTML5做图片预览已经是一个老生常谈的问题了.我在这里就简单说说其中相关的一些东西,当然会 ...
- HTML5多图片拖拽上传带进度条
前言 昨天利用css2的clip属性实现了网页进度条觉得还不错,但是很多情况下,我们在那些时候用进度条呢,一般网页加载的时候如果有需要可以用,那么问题就来了,怎么才算整个加载完毕呢,是页面主要模块加载 ...
- 自制一个H5图片拖拽、裁剪插件(原生JS)
前言 如今的H5运营活动中,有很多都是让用户拍照或者上传图片,然后对照片加滤镜.加贴纸.评颜值之类的.尤其是一些拍照软件公司的运营活动几乎全部都是这样的. 博主也做过不少,为了省事就封装了一个简单的图 ...
- Android 仿微信朋友圈发表图片拖拽和删除功能
朋友圈实现原理 我们使用 Android Device Monitor 来分析朋友圈发布图片的界面实现原理.如果需要分析其他应用的界面实现也是采用这种方法哦. 打开 Android Device Mo ...
- Vue富文本编辑器(图片拖拽缩放)
富文本编辑器(图片拖拽缩放) 需求: 根据业务要求,需要能够上传图片,且上传的图片能在移动端中占满屏幕宽度,故需要能等比缩放上传的图片,还需要能拖拽.缩放.改变图片大小.尝试多个第三方富文本编辑器,很 ...
- vue在移动端使用alloyfinger手势库操作图片拖拽、缩放
最近开发一个活动需要在手机上给上传的头像加上边框.装饰,需要拖拽.手势缩放边框下的头像图片,因为是vue项目,开始尝试了vue-drag-resize这个组件,对图片拖拽支持很完美,但是无法手势缩放, ...
随机推荐
- DOSUSB 2.0 免费版的限制原理
两年前,我在写USB的文章时,多次提到了DOSUSB这个东东,这两年也没有关注这方面的变化,最近,有机会重新进入DOSUSB的官方网站(www.dosusb.net),欣喜地发现,这个网站不仅依然存在 ...
- Keil C -WARNING L15: MULTIPLE CALL TO SEGMENT
1.第一种错误信息 ***WARNING L15: MULTIPLE CALL TO SEGMENT SEGMENT: ?PR?_WRITE_GMVLX1_REG?D_GMVLX1 CALLER1: ...
- javascript之Error
一.Error()构造函数 构造函数:new Error(); new Error(message); 二.Error.message //人类可读的错误消息 语法:error.message; 三. ...
- CircleImageView自定义圆形控件的使用
1.自定义圆形控件github地址: https://github.com/hdodenhof/CircleImageView 主要的类: package de.hdodenhof.circleima ...
- Hibernate 配置详解(8)
hibernate.generate_statistics 这个配置大家应该都很熟悉,用于开启Hibernate统计信息,便于对Hibernate相关性能调试提供数据依据.在开发过程当中,可以把这个选 ...
- UVA 10129-Play on Words(欧拉通路)
题意:给N个单词,判断是否单词首尾(前一个单词的尾字符与后一个单词的头字符相同)相连能否形成一条链. 解析:找欧拉通路(欧拉回路或是欧拉链路),但这题事先需要并查集一下,判断是否只属于一个集合,如aa ...
- UGUI 滚动视图
滚动视图是常用的UI控件之一,它是由多个基本控件组合而成.如图 ==================================================================== ...
- UGUI Scrollbar控件
如题就是Scrollbar控件,它简单可以看成 Scrollbar 和 Image组件组成 它基本上不单独使用多数是制作滚动视图.我们来看看他独特的属性,重复的属性就不在介绍了! 属性讲解: Hand ...
- iOS学习之iOS沙盒(sandbox)机制和文件操作(一)
1.iOS沙盒机制 iOS应用程序仅仅能在为该改程序创建的文件系统中读取文件,不能够去其他地方訪问,此区域被成为沙盒,所以全部的非代码文件都要保存在此,比如图像,图标,声音,映像,属性列表,文本文件等 ...
- iOS开发-CGAffineTransformMakeRotation改变了中心解决的方法
坑爹的. 为了这个问题折腾了2个小时. 恼.. 今天在写一个时钟demo的时候, 时针的旋转用到了CGAffineTransformMakeRotation, 按理说. 图像的旋转是以图像本身的中心 ...