注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

飞天心宏的博客

依稀旧梦似曾见,相逢只恨缘太迟

 
 
 

日志

 
 
关于我

出身数学,爱好文学,从事软件开发工作。一个阳光、幽默、热爱生活的男孩子,在追求理想的路上风雨无阻,勇往直前,崇尚“梦想有多远,我们就走多远”!

网易考拉推荐

如何:实现类似谷歌的Picasa照片查看器缩放图片功能  

2011-09-22 15:49:57|  分类: WinForm |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |

概要:

本文将讲述如何使PictureBox控件实现类似谷歌Picasa照片查看器的双击图片实现大图查看,可通过鼠标滚轮进行缩放,并可随意拖动图片的功能(姑且命名为PicasaLike吧)。该例程序虽在winform中实现,但思路可方便移植于任何C#其他框架,如ASP.NETWPFSilverlight

关键词:图片查看、PictureBox、图片缩放、图片拖动、PicasaLike< xmlnamespace prefix ="o" ns ="urn:schemas-microsoft-com:office:office" />

解决方案:

下面实现的就是谷歌的Picasa照片查看器实现的部分功能,按照惯例我们还是先来看一下Picasa查看图片的效果和我们自己实现的PicasaLike效果吧。

如何:实现类似谷歌的Picasa照片查看器缩放图片功能 - 飞天心宏 - 飞天心宏的博客

  

图片显示的是我在家乡南昌拍摄的一张“南昌之星摩天轮”,高160,比之前世界最高纪录保持者伦敦之眼还要高出25米,建成后排世界第一高,后来听说新加坡又建了个“新加坡飞行者”,高165米,那好像现在只能排世界第二高了。广告就不打了,言归正传,什么图片无所谓,这就是Picasa照片查看器双击图片的效果:双击后显示的是全屏放大图片,图片可随鼠标滚轮放大缩小,同时可随意拖动,图片下面显示的是Picasa自动在同级目录找到的图片列表,及一些图片的常用操作如:左右翻转等,可按快捷键Esc关闭等功能。

   我们要做的就是类似Picasa的图片查看功能,我们姑且叫它为PicasaLike吧,实现其部分功能,包括:图片查看、缩放、拖动。为什么有人所怎么没有翻转操作呢?那是因为笔者在研究的时候需要的功能只是需要查看,而且为了赶项目进度和个人比较懒的因素结合在一起就暂时实现了部分功能,还望谅解,当然实现翻转也不是什么难事,我看了一下MSDNC#类库中是有现成的该功能方法可供调用的,有兴趣的可以去查些资料。说了这么多废话,还是来看看改装版的PicasaLike效果图吧,运行后如下所示:

如何:实现类似谷歌的Picasa照片查看器缩放图片功能 - 飞天心宏 - 飞天心宏的博客

  

背景透明显示图片,可根据鼠标滑轮滚动放大、缩小、可随意拖动、按Esc快捷键关闭。

该功能可应用于图片列表中,双击查看大图功能,后面会演示效果,这个例子是拿单张图片做测试,也就是我们类似所谓的原型的概念。

实现思路:

我们按下面简单的六步即可实现该功能。

1.       布局

新建一个Form窗体,NameText设置都设为PicasaLike,在工具箱中拖一个PictureBox控件上去,为PictureBoxImage属性随意选择一张图片,并将SizeMode属性值选择为Zoom。如下图所示:

如何:实现类似谷歌的Picasa照片查看器缩放图片功能 - 飞天心宏 - 飞天心宏的博客

 

2.       屏幕居中显示、

修改窗体PicasaLike的属性StartPositionCenterScreenWindowStateMaximized

在属性的事件中双击注册Resize事件,这样的话,通过计算pictureBoxLocation使其居中显示。

        private void PicasaLike_Resize(object sender, EventArgs e)

        {

            //图片居中显示

            rectangleCenter = new Point(this.Width / 2, this.Height / 2);

            pictureBox1.Location = GetRectangleLeftTopPoint(rectangleCenter, pictureBox1.Width, pictureBox1.Height);

        }

其中:rectangleCenter变量为全局变量,默认为空

   Point rectangleCenter = Point.Empty; //矩形中心点坐标

GetRectangleLeftTopPoint方法是通过矩形中心点得到左上角坐标,定义如下:

        /// <summary>

        /// 根据矩形中心点的坐标得到左上角的坐标

        /// </summary>

        /// <param name="center">矩形中心点坐标</param>

        /// <param name="width">矩形的宽度</param>

        /// <param name="height">矩形的高度</param>

        /// <returns></returns>

        private Point GetRectangleLeftTopPoint(Point center, int width, int height)

        {

            int halfWidth = (int)(width/2);

            int halfHeight = (int)(height/2);

            Point leftTop = new Point(center.X - halfWidth, center.Y - halfHeight);

            return leftTop;

}

到这里,只要运行,我们就能看到图片在居中显示了。

3.       鼠标滚动缩放

滚轮事件需要在构造函数中代码注册:

this.MouseWheel += new MouseEventHandler(PicasaLike_MouseWheel); //滚轮缩放事件

        void PicasaLike_MouseWheel(object sender, MouseEventArgs e)

        {

            double scale = 1;

            if (pictureBox1.Height>0)

            {

                scale = (double)pictureBox1.Width / (double)pictureBox1.Height;

            }

            pictureBox1.Width += (int)(e.Delta * scale);

            pictureBox1.Height += e.Delta;

            pictureBox1.Location = GetRectangleLeftTopPoint(rectangleCenter, pictureBox1.Width, pictureBox1.Height);

     }

注意:这里需要等比例缩放。缩放操作就是改变pictureBox1的长宽值,根据中心点得出Location坐标居中显示。

4.       拖动效果

为了实现拖动效果,我们需要对pictureBox注册几个鼠标事件,具体如下所示:

如何:实现类似谷歌的Picasa照片查看器缩放图片功能 - 飞天心宏 - 飞天心宏的博客

  

鼠标光标悬浮事件,将光标变为手形图标(Cursors.Hand),表示可以拖动。光标离开后,改成默认光标形状。

        private void pictureBox1_MouseHover(object sender, EventArgs e)

        {

            Cursor = Cursors.Hand;

            pictureBox1.Focus();

        }

        private void pictureBox1_MouseLeave(object sender, EventArgs e)

        {

            Cursor = Cursors.Default;

        }

        private void pictureBox1_MouseDown(object sender, MouseEventArgs e)

        {

            startMove = true;

            moveStartPoint = e.Location; 

        }

 

在按住鼠标左键后表示可以开始拖动,到放开后表示拖动结束。为了标识这个状态我们定义一个全局变量:

bool startMove = false;//标识是否开始移动图片

鼠标按下时,我们记录开始拖动的坐标,存储在moveStartPoint变量中。

        private void pictureBox1_MouseDown(object sender, MouseEventArgs e)

        {

            startMove = true;

            moveStartPoint = e.Location; 

        }

        private void pictureBox1_MouseUp(object sender, MouseEventArgs e)

        {

            startMove = false;

        }

 

接下来就是鼠标移动事件做的事情了:

        private void pictureBox1_MouseMove(object sender, MouseEventArgs e)

        {

            if (startMove)

            {

                //移动向量

                Point vector = new Point(e.X - moveStartPoint.X, e.Y - moveStartPoint.Y);

                Point original = pictureBox1.Location;

                pictureBox1.Location = new Point(original.X + vector.X, original.Y + vector.Y);

 

                rectangleCenter = new Point(rectangleCenter.X + vector.X, rectangleCenter.Y + vector.Y);

              

            }

        }

重点:鼠标在拖动时,除了pictureBox1Location属性发生变化外,其中心点也发生了相应的变化,如果不注意的话,那么拖动后,将影响缩放的效果。怎么影响,自己把最后那句代码注释掉,运行看看就明白了。

5.       Esc关闭

PicasaLike表单注册KeyDown事件

        private void PicasaLike_KeyDown(object sender, KeyEventArgs e)

        {

            if (e.KeyCode == Keys.Escape)

            {

                this.Close();

            }

     }

Esc快捷键关闭,应该说这个键盘事件是全局的,不管是Form表单还是PictureBox获得焦点,只要发生了Esc键盘事件,就认为是需要关闭了。所以我们还需要在构造函数中设置:

            this.KeyPreview = true; //接收全键盘事件

6.       透明方式设置

我们使用this.TransparencyKey = SystemColors.Control;  //透明方式设置

来代替设置Opcity属性//this.Opacity =0.8;   

 

到这里已经做完了,运行一下效果试试,希望一路顺利。再上一个拖动后的效果图吧:

如何:实现类似谷歌的Picasa照片查看器缩放图片功能 - 飞天心宏 - 飞天心宏的博客

 

实际应用:

最后你可能会问,做这么一个简单的功能有啥用呢?那么我们就来看一下最常用的场所,如下图所示:

如何:实现类似谷歌的Picasa照片查看器缩放图片功能 - 飞天心宏 - 飞天心宏的博客

  

这个功能的应用就是,在一个图片列表中,我们双击任何一副图片都能方便地查看大图,并进行缩放和拖动操作,功能简单,但是不是很友好呢?

 

附后台完整代码:

 

        public PicasaLike()

        {

            InitializeComponent();

 

            this.KeyPreview = true; //接收全键盘事件

            this.MouseWheel += new MouseEventHandler(PicasaLike_MouseWheel); //滚轮缩放事件

            this.TransparencyKey = SystemColors.Control;  //透明方式设置

            //this.Opacity =0.8;

        }

 

        bool startMove = false;//标识是否开始移动图片

        Point moveStartPoint = Point.Empty;

        Point rectangleCenter = Point.Empty; //矩形中心点坐标

 

        void PicasaLike_MouseWheel(object sender, MouseEventArgs e)

        {

            double scale = 1;

            if (pictureBox1.Height>0)

            {

                scale = (double)pictureBox1.Width / (double)pictureBox1.Height;

            }

            pictureBox1.Width += (int)(e.Delta * scale);

            pictureBox1.Height += e.Delta;

            pictureBox1.Location = GetRectangleLeftTopPoint(rectangleCenter, pictureBox1.Width, pictureBox1.Height);

 

        }

 

 

        /// <summary>

        /// 根据矩形中心点的坐标得到左上角的坐标

        /// </summary>

        /// <param name="center">矩形中心点坐标</param>

        /// <param name="width">矩形的宽度</param>

        /// <param name="height">矩形的高度</param>

        /// <returns></returns>

        private Point GetRectangleLeftTopPoint(Point center, int width, int height)

        {

            int halfWidth = (int)(width/2);

            int halfHeight = (int)(height/2);

            Point leftTop = new Point(center.X - halfWidth, center.Y - halfHeight);

            return leftTop;

        }

 

        private void pictureBox1_MouseHover(object sender, EventArgs e)

        {

            Cursor = Cursors.Hand;

            pictureBox1.Focus();

        }

 

        private void pictureBox1_MouseLeave(object sender, EventArgs e)

        {

            Cursor = Cursors.Default;

        }

 

        private void pictureBox1_MouseMove(object sender, MouseEventArgs e)

        {

            if (startMove)

            {

                //移动向量

                Point vector = new Point(e.X - moveStartPoint.X, e.Y - moveStartPoint.Y);

                Point original = pictureBox1.Location;

                pictureBox1.Location = new Point(original.X + vector.X, original.Y + vector.Y);

 

                rectangleCenter = new Point(rectangleCenter.X + vector.X, rectangleCenter.Y + vector.Y);

              

            }

        }

 

        private void pictureBox1_MouseDown(object sender, MouseEventArgs e)

        {

            startMove = true;

            moveStartPoint = e.Location; 

        }

 

        private void pictureBox1_MouseUp(object sender, MouseEventArgs e)

        {

            startMove = false;

        }

 

        private void PicasaLike_Resize(object sender, EventArgs e)

        {

            //图片居中显示

            rectangleCenter = new Point(this.Width / 2, this.Height / 2);

            pictureBox1.Location = GetRectangleLeftTopPoint(rectangleCenter, pictureBox1.Width, pictureBox1.Height);

        }

 

        private void PicasaLike_KeyDown(object sender, KeyEventArgs e)

        {

            if (e.KeyCode == Keys.Escape)

            {

                this.Close();

            }

        }

 

 

 

                                                 飞天心宏 2011-09-22

  评论这张
 
阅读(2472)| 评论(0)
推荐 转载

历史上的今天

在LOFTER的更多文章

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2018