【C#】C# Winform 相册功能,图片缩放,拖拽,预览图分页
CrazyPanda发表于:2024-02-02 22:48:51浏览:322次
一、前言
在一些项目中也会用到预览图片的功能,至于为什么有一个添加图片的按钮,是因为有些项目,比如视觉相关的项目,摄像头拍摄图片,然后显示在界面上,拍一次显示一张。另一个,就是分页功能,当预览图位置不够用时就会用到。
当前软件的功能
1.添加图片
如果8个预览图都满了,会自动分页,就可以点击上一页,或者下一页了。
2.点击预览图显示大图
点击预览图,之前的拖拽和放大会自动复位
3.大图可以拖拽,放大,缩小
如果图片比较小,有这个功能就看到图片的更多细节了。
4.图片倒序排列
最后拍摄的图片,始终显示在前面,方便用户更好的观察到最新的图片
二、实现功能
新建一个winform项目,界面如下:
界面中大图和预览图都是 PictureBox 控件 ,至于控件的名字,在下面的代码中可以看到,在文章的最后面,我会附上这个Demo源码,Visual Studio 版本为2019.
代码:
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.IO; using System.Linq; using System.Reflection; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; namespace 相册功能 { public partial class Form1 : Form { public Form1() { InitializeComponent(); } //本地的相册列表 private string AlbumPath = Application.StartupPath + "\\Album"; //相册列表 private List<PictureBox> PictureBoxList = new List<PictureBox>(); //图片路径列表 private List<string> FilesinfoList = new List<string>(); //相册显示的图片列表 private List<Bitmap> BitmapList = new List<Bitmap>(); //pictureBox1的初始位置 private Point PicStartPos; //pictureBox1的初始大小 private Size PicSize; //测试用 int index = -1; //当前页数 private int NowPage = 1; //总页数 private int TotalPage = 1; //鼠标滚轮缩放图片的增量值 private int ZoomStep = 20; //鼠标是否在拖拽中 private bool IsMove = false; //鼠标点击的位置 private Point MouseDownPoint; private void Form1_Load(object sender, EventArgs e) { PicStartPos = pictureBox1.Location; PicSize = pictureBox1.Size; this.pictureBox1.MouseWheel += new MouseEventHandler(this.pictureBox1_MouseWheel); PictureBoxList.Add(PictureBox_ImgList1); PictureBoxList.Add(PictureBox_ImgList2); PictureBoxList.Add(PictureBox_ImgList3); PictureBoxList.Add(PictureBox_ImgList4); PictureBoxList.Add(PictureBox_ImgList5); PictureBoxList.Add(PictureBox_ImgList6); PictureBoxList.Add(PictureBox_ImgList7); PictureBoxList.Add(PictureBox_ImgList8); //添加图片的点击事件 for (int i = 0; i < PictureBoxList.Count; i++) { PictureBoxList[i].Click += new System.EventHandler(PictureBoxClick); } DirectoryInfo directory = new DirectoryInfo(AlbumPath); FileSystemInfo[] filesArray = directory.GetFileSystemInfos(); foreach (var item in filesArray) { if (item.Attributes != FileAttributes.Directory) { FilesinfoList.Add(item.FullName); } } } /// <summary> /// 上一页 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void Button_Back_Click(object sender, EventArgs e) { if (NowPage <= 1) return; NowPage--; for (int i = 0; i < PictureBoxList.Count; i++) { PictureBoxList[i].Image = null; } List<Bitmap> list = GetPagesBitmap(NowPage); for (int i = 0; i < list.Count; i++) { PictureBoxList[i].Image = list[i]; } pictureBox1.Image = list[0]; //设置坐标 pictureBox1.Location = PicStartPos; //设置控件宽高 pictureBox1.Size = PicSize; Label_NumberOfPages.Text = string.Format("{0} / {1}", NowPage, TotalPage); BackNextButtonType(); } /// <summary> /// 下一页 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void Button_Next_Click(object sender, EventArgs e) { if (NowPage >= TotalPage) return; NowPage++; for (int i = 0; i < PictureBoxList.Count; i++) { PictureBoxList[i].Image = null; } List<Bitmap> list = GetPagesBitmap(NowPage); for (int i = 0; i < list.Count; i++) { PictureBoxList[i].Image = list[i]; } pictureBox1.Image = list[0]; //设置坐标 pictureBox1.Location = PicStartPos; //设置控件宽高 pictureBox1.Size = PicSize; Label_NumberOfPages.Text = string.Format("{0} / {1}", NowPage, TotalPage); BackNextButtonType(); } /// <summary> /// 添加图片 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void Button_Add_Click(object sender, EventArgs e) { index++; AddPicture(new Bitmap(FilesinfoList[index])); if (index >= FilesinfoList.Count - 1) index = -1; } /// <summary> /// 添加图片 /// </summary> /// <param name="bitmap"></param> private void AddPicture(Bitmap bitmap) { if (bitmap == null) return; //添加到图片列表 BitmapList.Add(bitmap); //界面预留图中显示 pictureBox1.Image = bitmap; //设置坐标 pictureBox1.Location = PicStartPos; //设置控件宽高 pictureBox1.Size = PicSize; //计算当前总页数 int page = BitmapList.Count / PictureBoxList.Count; int remainder = BitmapList.Count % PictureBoxList.Count; TotalPage = remainder > 0 ? page + 1 : page; Label_NumberOfPages.Text = string.Format("{0} / {1}", NowPage, TotalPage); BackNextButtonType(); //让图片按逆向顺序显示 List<Bitmap> reverseSort = new List<Bitmap>(); for (int i = BitmapList.Count - 1; i >= 0; i--) { reverseSort.Add(BitmapList[i]); } for (int i = 0; i < reverseSort.Count; i++) { if (i <= 7) PictureBoxList[i].Image = reverseSort[i]; } } /// <summary> /// 8张预览图片的点击事件 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void PictureBoxClick(Object sender, System.EventArgs e) { PictureBox pictureBox = (PictureBox)sender; if (pictureBox != null && pictureBox.Image != null) { pictureBox1.Image = pictureBox.Image; //设置坐标 pictureBox1.Location = PicStartPos; } } /// <summary> /// 获取索引对应的图片 /// </summary> /// <param name="index"></param> /// <returns></returns> private List<Bitmap> GetPagesBitmap(int index) { if (BitmapList.Count <= 0) return null; //页数 int page = BitmapList.Count / PictureBoxList.Count; //余数 int remainder = BitmapList.Count % PictureBoxList.Count; //总页数 int allPage = remainder > 0 ? page + 1 : page; if (index > allPage) return null; //索引起点 int start = (index * PictureBoxList.Count) - PictureBoxList.Count; //索引结束点 int end = (index * PictureBoxList.Count) - 1; if (end > BitmapList.Count) end = BitmapList.Count - 1; List<Bitmap> reverseSort = new List<Bitmap>(); for (int i = BitmapList.Count - 1; i >= 0; i--) { reverseSort.Add(BitmapList[i]); } List<Bitmap> list = new List<Bitmap>(); for (int i = start; i <= end; i++) { list.Add(reverseSort[i]); } if (list.Count > 0) return list; return null; } /// <summary> /// 上一页,下一页按钮状态 /// </summary> private void BackNextButtonType() { Button_Next.Enabled = true; Button_Back.Enabled = true; //现在页 = 总页数 if (NowPage == TotalPage) Button_Next.Enabled = false; //现在页 小于等于 1 if (NowPage <= 1) Button_Back.Enabled = false; } private void pictureBox1_MouseDown(object sender, MouseEventArgs e) { if (pictureBox1.Image == null) return; if (e.Button == MouseButtons.Left) { MouseDownPoint.X = Cursor.Position.X; //记录鼠标左键按下时位置 MouseDownPoint.Y = Cursor.Position.Y; IsMove = true; pictureBox1.Focus(); //鼠标滚轮事件(缩放时)需要picturebox有焦点 } } private void pictureBox1_MouseUp(object sender, MouseEventArgs e) { if (e.Button == MouseButtons.Left) { IsMove = false; } } private void pictureBox1_MouseMove(object sender, MouseEventArgs e) { if (pictureBox1.Image == null) return; pictureBox1.Focus(); //鼠标在picturebox上时才有焦点,此时可以缩放 if (IsMove) { int x, y; //新的pictureBox1.Location(x,y) int moveX, moveY; //X方向,Y方向移动大小。 moveX = Cursor.Position.X - MouseDownPoint.X; moveY = Cursor.Position.Y - MouseDownPoint.Y; x = pictureBox1.Location.X + moveX; y = pictureBox1.Location.Y + moveY; pictureBox1.Location = new Point(x, y); MouseDownPoint.X = Cursor.Position.X; MouseDownPoint.Y = Cursor.Position.Y; } } private void pictureBox1_MouseWheel(object sender, MouseEventArgs e) { if (pictureBox1.Image == null) return; PictureBox pbox = pictureBox1; int x = e.Location.X; int y = e.Location.Y; int ow = pbox.Width; int oh = pbox.Height; int VX, VY; //因缩放产生的位移矢量 if (e.Delta > 0) //放大 { //第1步 pbox.Width += ZoomStep; pbox.Height += ZoomStep; //第2步 PropertyInfo pInfo = pbox.GetType().GetProperty("ImageRectangle", BindingFlags.Instance | BindingFlags.NonPublic); Rectangle rect = (Rectangle)pInfo.GetValue(pbox, null); //第3步 pbox.Width = rect.Width; pbox.Height = rect.Height; //Console.WriteLine(string.Format("宽:{0},高:{1}",pbox.Width,pbox.Height)); } if (e.Delta < 0) //缩小 { //防止一直缩成负值 if (pbox.Width < 300) return; pbox.Width -= ZoomStep; pbox.Height -= ZoomStep; PropertyInfo pInfo = pbox.GetType().GetProperty("ImageRectangle", BindingFlags.Instance | BindingFlags.NonPublic); Rectangle rect = (Rectangle)pInfo.GetValue(pbox, null); pbox.Width = rect.Width; pbox.Height = rect.Height; } //第4步,求因缩放产生的位移,进行补偿,实现锚点缩放的效果 VX = (int)((double)x * (ow - pbox.Width) / ow); VY = (int)((double)y * (oh - pbox.Height) / oh); pbox.Location = new Point(pbox.Location.X + VX, pbox.Location.Y + VY); } } }
代码中,鼠标缩放,拖拽功能,需要在控件里选择对应的方法,否则运行就没有效果
运行后,效果就如文章开头的 Gif 图片
源码:点击下载
结束
如果这个帖子对你有用,欢迎 关注 + 点赞 + 留言,谢谢
end
猜你喜欢
- 【C#】C# Winform 多个程序之间的通信(非Scoket)
- 效果功能:打开窗体自动连接主程序,并自动添加到列表,可以向子程序群发消息可以向单个程序单独发送消息在退出程序后,添加的程序列表会自动移除一、概述参考:C# Winfrom程序之间通讯_c# sendmessege copydatastruct 返回多个值_熊思宇的博客-CSDN博客在之前我写过 winform 程序与程序之间的通信,但是这个版本有个问题,那就是只能由两个程序进行通信,同时打开多个程序的话,接收方收到的数据就会一模一样,这次发表这个教程,也就是要解决这个问题。归根结底,还是&nbs
- 【C#】C# Winfrom 常用功能整合-2
- 目录Winfrom 启动一个外部exe文件,并传入参数Winform ListBox用法HTTP下载文件(推荐)Winform HTTP下载并显示进度Winform HTTP下载文件Winform 跨线程访问UI组件Winform 改变文字的颜色和大小Winfrom 启动一个外部exe文件,并传入参数在我们常用的一些软件中,经常有些软件,双击之后根本打不开,这是因为启动时做了限制,我们需要传入一些参数才能打开,在工作中,这个需求也可以用在软件的自动更新上,
- 【C#】C#实现Excel合并单元格数据导入数据集
- 目录功能需求Excel与DataSet的映射关系范例运行环境Excel DCOM 配置设计实现组件库引入方法设计返回值 参数设计打开数据源并计算Sheets拆分合并的单元格创建DataTable将单元格数据写入DataTable总结功能需求将Excel里的worksheet表格导入到DataSet里,是项目应用里常用的一种操作。一般情况下,worksheet是一个标准的二维数组,如下图:我们可以效仿 MS SQL SERVER 的一些基本导入选项,如首行是否包含数据,要导入哪个Shee
- 【C#】c#开发桌面应用程序用什么框架
- style="text-wrap: wrap;">在C#开发桌面应用程序时,可以使用以下几种常见的框架:</p><ol class=" list-paddingleft-2" style="width: 1529.1px; text-wrap: wrap;"><li><p>Windows Forms:这是一种由.NET Framework提供的GUI框架,它提供了丰富的GUI控件和易于使用的编程模型。Windows Forms在C#开发领域中使用非常广泛,并且已经存在多年,获得了广泛的支持和优化。</p></li></ol
- 【C#】C# 开源框架(整理)
- C# 开源框架(整理)Json.NEThttp://json.codeplex.com/Json.Net 是一个读写Json效率比较高的.Net框架.Json.Net 使得在.Net环境下使用Json更加简单。通过Linq To JSON可以快速的读写Json,通过JsonSerializer可以序列化你的.Net对象。让你轻松实现.Net中所有类型(对象,基本数据类型 等)和Json的转换。Math.NEThttp://www.mathdotnet.com/Math.NET的目标是为提供一款
- 【C#】从零开始用C#写一个桌面应用程序(二)一个表白程序
- 恶搞表白小程序如何添加按钮,如何添加属性和事件请移步前文。基础操作第一步:新建窗口 在工具箱内找到label和button,拖到form上,设置它们的size属性,autosize属性,text属性。第二步:添加事件为了实现我们的效果,需要给三个按钮分别设计点击事件,鼠标移入事件,鼠标点下事件。分别为click,mouseenter,mousedown事件。第三步:实现移动逻辑this获取form对象,clientsize获取实时大小,使用随机数值,设置对应按钮位置。将对应
- 【C#】C# Winform程序之间通讯
- 实现原理通过Windows系统中 User32.dll 中的 FindWindow 方法来寻找系统正在运行的程序句柄,通过 SendMessage 方法来发送消息,winform 中的 WndProc 方法来接收消息,下面是SendMessage,FindWindow 这两个参数的具体介绍:1.SendMessage该函数将指定的消息发送到一个或多个窗口。此函数为指定的窗口调用窗口程序,直到窗口程序处理完消息再返回。该函数是应用程序和应用程序之间进行消息传递的主要手段之一 函数原型:I
- 【C#】C# Winfrom 右键菜单
- 目录一、概述二、新建 winform 项目三、给图片控件添加右键菜单四、给菜单添加点击事件五、测试结束一、概述ContextMenuStrip 是 Windows 窗体应用程序中的一个控件,它提供了一个弹出菜单,用于在用户右键单击控件或其他界面元素时显示上下文相关的选项。它通常用于在图形用户界面中提供快捷操作和功能。ContextMenuStrip 控件可以通过在 Visual Studio 的设计器中拖放方式添加到窗体上,或者通过编程方式创建和配置。它可以与其他控件(如按钮、文本框等
栏目分类全部>