来自:mjsws > 馆藏分类
配色: 字号:
C#图片缩放平移从功能分析到编码实现
2019-01-29 | 阅:  转:  |  分享 
  
C#图片缩放平移从功能分析到编码实现一直都是在看别人的博客,查到想要的,看完后把页面一关就万事大吉了,没啥感觉;直到后来遇到了同样的问题,总
想不起来咋弄,关键是还查不到以前看过的,郁闷!现在想想,还是“好记性不如烂笔头”啊,自己弄过的东西总要留下的什么呀,不然你都不知道
自己曾经多么优秀。注册博客园也好久了,因为不知道该写点啥,再加上懒,一直没有去管它,今日有空,正好开张!1.需求说明这个没啥好说
的,主要干三个事,用电脑的照片查看器打开一张你宝贝的自拍照。(1)拉动显示窗口,图片按照原有比例被放大和缩小,照片查看器中当图片没
能完全显示时,拉框时只是拉框,我们不管这个,只要图片显示窗口变了,那就按照原有比例被放大和缩小。(2)鼠标放在图片的有效区域,鼠标
滚轮放大和缩小图片,缩小时最小只能到图片原大小;放大无限制,照片查看器放大也有限制,咱也不管它。(3)鼠标放在图片的有效区域,按住
鼠标左键平移图片,平移时只能平移图片有效范围。2.功能分析想想上面要实现的功能,结合C#,我们用Winform的窗体程序来实现,
图片显示用PictureBox控件,它有一个PictureBoxSizeMode属性,值改成Zoom,这样就能保证PictureB
ox控件里面的图片随PictureBox控件大小改变而按照原有比例缩放,然后把PictureBox控件放大Form窗体中,dock
属性改成Fill填满就可以了,但dock属性改成Fill填满之后,PictureBox控件的大小变得无法改变(我也是试了之后才知道
的),一种有效的解决方案是在窗体里面放一个Panel控件,dock属性Fill,然后把PictureBox控件放在Panel中,大
小改成和Panel控件一样大,再加一个Panel控件的SizeChanged事件,随时设置PictureBox控件和Panel控件
一样大。这里不细说,具体看下面的C#编码实现,咱重点说说PictureBox控件里的图斑如何缩放和平移。要想实现缩放和平移,首先我
们得了解它实现的原理,这是下面编码实现的基础。因为图片随PictureBox控件大小改变而按照原有比例缩放,因此我们改变Pictu
reBox控件的大小,也就是它的Width和Height属性,在视觉上就能看到图片被放大和缩小,也就是缩放;当图片被放大后,窗体中
不能显示完整的图片内容,这时就需要我们通过平移来查看未能显示在窗体上的图片部分了,同样的,我们只要改变PictureBox控件的位
置,也就是它的Left和Top属性,就能把需要展示的图片局部正好显示在窗体上,从而在视觉上看到图片平移。原理简单说明了一下后,所以
,我们想要实现缩放与偏移,本质上就是计算PictureBox控件的大小和位置,只要搞定了这个,缩放平移也就搞定了。那么这个大小和位
置咋算呢,请接着往下看。我们知道照片查看器缩放用的鼠标滚轮,前滚放大,后滚缩小。PictureBox控件中找一下,MouseWhe
el事件正好干这个事。再一查,哎呀,SystemInformation.MouseWheelScrollLines代码滚一格(微软
叫它制动器)代表多少行。那就好办了,我们把这个多少行按一定的比例转换成PictureBox控件Left、Top、Width、Hei
ght四个属性的增量,加上原值后,调整与显示窗体大小以及图片有效区域的位置关系,重新赋值回去就OK了。平移稍稍麻烦一点,其实也不是
太麻烦。涉及到MouseDown、MouseMove、MouseUp三个事件,在鼠标按下时记录下按下点坐标,同时标识正在平移操作;
在鼠标移动时计算移动的距离,换算Left、Top的增量,并与显示窗体大小和图片有效区域做调整,最后赋值会这俩属性;鼠标弹起时结束平
移操作标识。3.编码实现新建一个窗体应用程序,改窗体名称为frmMian,在其内添加一个Panel控件,命名pel;再在Pane
l控件中添加一个PictureBox控件,命名pboImage,以下为窗体类需要编写的代码:www.44226.net?12345
67891011121314151617181920212223242526272829303132333435363738394
04142434445464748495051525354555657585960616263646566676869707172
73747576777879808182838485868788899091929394959697989910010110210
31041051061071081091101111121131141151161171181191201211221231241
25126127128129130131132133134135136137138139140141142143144145146
14714814915015115215315415515615715815916016116216316416516616716
8169170171172173174publicpartialclassfrmMian:Form{?publicfr
mMian()?{?InitializeComponent();??this.pel.Dock=System.Windows.
Forms.DockStyle.Fill;?this.pel.SizeChanged+=newSystem.EventHan
dler(this.pel_SizeChanged);??this.pboImage.Margin=newSystem.Wi
ndows.Forms.Padding(0);?this.pboImage.Location=newSystem.Drawi
ng.Point(0,0);?this.pboImage.Size=newSystem.Drawing.Size(this
.pel.Width,this.pel.Height);?this.pboImage.SizeMode=System.Win
dows.Forms.PictureBoxSizeMode.Zoom;?this.pboImage.Cursor=Cursor
s.SizeAll;?this.pboImage.MouseDown+=newSystem.Windows.Forms.Mo
useEventHandler(this.pboImage_MouseDown);?this.pboImage.MouseEnte
r+=newSystem.EventHandler(this.pboImage_MouseEnter);?this.pboI
mage.MouseMove+=newSystem.Windows.Forms.MouseEventHandler(this
.pboImage_MouseMove);?this.pboImage.MouseUp+=newSystem.Windows
.Forms.MouseEventHandler(this.pboImage_MouseUp);?this.pboImage.Mo
useWheel+=newSystem.Windows.Forms.MouseEventHandler(this.pboIm
age_MouseWheel);??pboImage.Image=Image.FromFile(@"C:\宝贝自拍照.jpg"
);?}??privateSystem.Drawing.PointMouseDownPoint=newSystem.Dr
awing.Point();//平移时鼠标按下的位置?privateboolIsSelected=false;//鼠标是否
是按下状态??//pboImage获取焦点事件?privatevoidpboImage_MouseEnter(objects
ender,EventArgse)?{?pboImage.Focus();?}??//pboImage鼠标滚轮事件?priva
tevoidpboImage_MouseWheel(objectsender,MouseEventArgse)?{?if
(pboImage.Image==null)return;??//计算缩放后的锚点和宽高?inti=e.Delta
SystemInformation.MouseWheelScrollLines/4;?intleft=pboImag
e.Left-i/2,top=pboImage.Top-i/2;?intwidth=pboImage.
Width+i,heigth=pboImage.Height+i;??if(i<0)//缩小时需要考虑与显示范
围间关系,放大时无需考虑?{?//计算缩放后图片有效范围?doubleWidthScale=Convert.ToDouble
(pboImage.Image.Width)/width;?doubleHeigthScale=Convert.ToDo
uble(pboImage.Image.Height)/heigth;?if(WidthScale>HeigthScal
e)?{?top=top+Convert.ToInt32(Math.Ceiling(heigth-(pboImage.
Image.Height/WidthScale)))/2;?heigth=Convert.ToInt32(Math.C
eiling(pboImage.Image.Height/WidthScale));?}?else?{?left=left
+Convert.ToInt32(Math.Ceiling(width-(pboImage.Image.Width/H
eigthScale)))/2;?width=Convert.ToInt32(Math.Ceiling(pboImage.
Image.Width/HeigthScale));?}??if(left>0)//左侧在显示范围内部,调整到左边界?{
?if(width-leftdth-left;?left=0;?}?if(left+width调整到右边界www.77884.net?{?if(pel.Width-width>0)left=0;?else
left=pel.Width-width;?width=pel.Width-left;?}??if(top>
0)//上侧在显示范围内部,调整到上边界?{?if(heigth-topl.Height;?elseheigth=heigth-top;?top=0;?}?if(top+heigth
0)t
op=0;?elsetop=pel.Height-heigth;?heigth=pel.Height-top
;?}?}??pboImage.Width=width;?pboImage.Height=heigth;?pboImage
.Left=left;?pboImage.Top=top;?}??//pboImage鼠标按下事件?privatevoi
dpboImage_MouseDown(objectsender,MouseEventArgse)?{?if(pboIm
age.Image==null)return;??if(e.Button==MouseButtons.Left)?{?
//记录摁下点坐标,作为平移原点?MouseDownPoint.X=PointToClient(System.Windows.
Forms.Cursor.Position).X;?MouseDownPoint.Y=PointToClient(System
.Windows.Forms.Cursor.Position).Y;?IsSelected=true;?pboImage.Cu
rsor=Cursors.Hand;?}?}??//pboImage鼠标移动事件?privatevoidpboImage_
MouseMove(objectsender,MouseEventArgse)?{?if(pboImage.Image=
=null)return;??//计算图片有效范围?doubleWidthScale=Convert.ToDouble(
pboImage.Image.Width)/pboImage.Width;?doubleHeigthScale=Conv
ert.ToDouble(pboImage.Image.Height)/pboImage.Height;?intInvali
dTop=pboImage.Top,InvalidHeigth=pboImage.Height,InvalidLeft
=pboImage.Left,InvalidWidth=pboImage.Width;?if(WidthScale>
HeigthScale)?{?InvalidTop=InvalidTop+((int)Math.Ceiling(Inva
lidHeigth-(pboImage.Image.Height/WidthScale)))/2;?InvalidHe
igth=(int)Math.Ceiling(pboImage.Image.Height/WidthScale);?}?e
lse?{?InvalidLeft=InvalidLeft+((int)Math.Ceiling(InvalidWidth
-(pboImage.Image.Width/HeigthScale)))/2;?InvalidWidth=(in
t)Math.Ceiling(pboImage.Image.Width/HeigthScale);?}??//鼠标是否摁在图片
上?boolIsMouseInPanel=InvalidLefts.Forms.Cursor.Position).X&&?PointToClient(System.Windows.Forms.
Cursor.Position).XointToClient(System.Windows.Forms.Cursor.Position).Y&&?PointToCl
ient(System.Windows.Forms.Cursor.Position).YidHeigth;?if(IsSelected&&IsMouseInPanel)?{?//计算平移后图片有效范围的锚点和宽高
?intleft=InvalidLeft+(PointToClient(System.Windows.Forms.Cur
sor.Position).X-MouseDownPoint.X);?inttop=InvalidTop+(Poin
tToClient(System.Windows.Forms.Cursor.Position).Y-MouseDownPoin
t.Y);?intright=left+InvalidWidth;?intdown=top+InvalidHe
igth;??if(left>=InvalidLeft&&left>=0)left=0;//向右平移且平移后
在显示范围内部,调整到左边界?if(left=left+pel.Width-right;//向左平移且平移后在显示范围内部,调整到右边界?if(top>=I
nvalidTop&&top>=0)top=0;//向下平移且平移后在显示范围内部,调整到上边界?if(top<
InvalidTop&&down<=pel.Height)top=top+pel.Height-down;
//向上平移且平移后在显示范围内部,调整到下?边界??//有效范围锚点换算到整体的锚点?left=left+pboIma
ge.Left-InvalidLeft;?top=top+pboImage.Top-InvalidTop;??if
(InvalidLeft<=0)pboImage.Left=left;?if(InvalidTop<=0)pb
oImage.Top=top;??//记录当前平移点坐标,作为平移下一次代码执行时的平移原点?MouseDownPoint.X
=PointToClient(System.Windows.Forms.Cursor.Position).X;?MouseDownPoint.Y=PointToClient(System.Windows.Forms.Cursor.Position).Y;?}?}??//pboImage鼠标弹起事件?privatevoidpboImage_MouseUp(objectsender,MouseEventArgse)?{?if(pboImage.Image==null)return;?IsSelected=false;?pboImage.Cursor=Cursors.SizeAll;?}??//pel大小改变事件?privatevoidpel_SizeChanged(objectsender,EventArgse)?{?pboImage.Left=0;?pboImage.Top=0;?pboImage.Width=pel.Width;?pboImage.Height=pel.Height;?}www.f-1.cc}
献花(0)
+1
(本文系mjsws首藏)