• C# Winform 相册功能,图片缩放,拖拽,预览图分页


    效果

    1.图片放大,缩小,拖拽功能

    2.添加图片,分页功能

    一、前言

    在很多项目中也需要用到预览图片的功能,至于为什么加一个添加图片的功能,是因为有些项目,比如视觉相关的工作,会需要摄像机采集图片,然后显示在界面上,所以,图片也是一张一张的添加的,另外,就是分页功能,当预览图位置不够用时就会用到,所以我也加了进来。

    当前软件的功能

    1.添加图片

    如果8个预览图都满了,会自动分页,就可以点击上一页,或者下一页了。

    2.点击预览图显示大图

    点击预览图,之前的拖拽和放大会自动复位

    3.大图可以拖拽,放大,缩小

    如果图片比较小,有这个功能就看到图片的更多细节了。

    4.图片倒序排列

    最后添加的图片,始终显示在最前面,这也就在分页上和常规的有点区别了,如图

     如果你用的正序排列,可以看看这个帖子:

    C# 分页计算 总页数、当前页数据集合_熊思宇的博客-CSDN博客

    二、代码

    新建一个winform项目,界面如下:

    没有太复杂的界面,大图和预览图都是用的 PictureBox 控件 ,控件的名字,可以看下面的代码,在文章的最下面,我会附上这个Demo源码,有兴趣的可以下载。

    1. using System;
    2. using System.Collections.Generic;
    3. using System.ComponentModel;
    4. using System.Data;
    5. using System.Drawing;
    6. using System.IO;
    7. using System.Linq;
    8. using System.Reflection;
    9. using System.Text;
    10. using System.Threading.Tasks;
    11. using System.Windows.Forms;
    12. namespace 相册功能
    13. {
    14. public partial class Form1 : Form
    15. {
    16. public Form1()
    17. {
    18. InitializeComponent();
    19. }
    20. //本地的相册列表
    21. private string AlbumPath = Application.StartupPath + "\\Album";
    22. //相册列表
    23. private List<PictureBox> PictureBoxList = new List<PictureBox>();
    24. //图片路径列表
    25. private List<string> FilesinfoList = new List<string>();
    26. //相册显示的图片列表
    27. private List<Bitmap> BitmapList = new List<Bitmap>();
    28. //pictureBox1的初始位置
    29. private Point PicStartPos;
    30. //pictureBox1的初始大小
    31. private Size PicSize;
    32. //测试用
    33. int index = -1;
    34. //当前页数
    35. private int NowPage = 1;
    36. //总页数
    37. private int TotalPage = 1;
    38. //鼠标滚轮缩放图片的增量值
    39. private int ZoomStep = 20;
    40. //鼠标是否在拖拽中
    41. private bool IsMove = false;
    42. //鼠标点击的位置
    43. private Point MouseDownPoint;
    44. private void Form1_Load(object sender, EventArgs e)
    45. {
    46. PicStartPos = pictureBox1.Location;
    47. PicSize = pictureBox1.Size;
    48. this.pictureBox1.MouseWheel += new MouseEventHandler(this.pictureBox1_MouseWheel);
    49. PictureBoxList.Add(PictureBox_ImgList1);
    50. PictureBoxList.Add(PictureBox_ImgList2);
    51. PictureBoxList.Add(PictureBox_ImgList3);
    52. PictureBoxList.Add(PictureBox_ImgList4);
    53. PictureBoxList.Add(PictureBox_ImgList5);
    54. PictureBoxList.Add(PictureBox_ImgList6);
    55. PictureBoxList.Add(PictureBox_ImgList7);
    56. PictureBoxList.Add(PictureBox_ImgList8);
    57. //添加图片的点击事件
    58. for (int i = 0; i < PictureBoxList.Count; i++)
    59. {
    60. PictureBoxList[i].Click += new System.EventHandler(PictureBoxClick);
    61. }
    62. DirectoryInfo directory = new DirectoryInfo(AlbumPath);
    63. FileSystemInfo[] filesArray = directory.GetFileSystemInfos();
    64. foreach (var item in filesArray)
    65. {
    66. if (item.Attributes != FileAttributes.Directory)
    67. {
    68. FilesinfoList.Add(item.FullName);
    69. }
    70. }
    71. }
    72. /// <summary>
    73. /// 上一页
    74. /// </summary>
    75. /// <param name="sender"></param>
    76. /// <param name="e"></param>
    77. private void Button_Back_Click(object sender, EventArgs e)
    78. {
    79. if (NowPage <= 1) return;
    80. NowPage--;
    81. for (int i = 0; i < PictureBoxList.Count; i++)
    82. {
    83. PictureBoxList[i].Image = null;
    84. }
    85. List<Bitmap> list = GetPagesBitmap(NowPage);
    86. for (int i = 0; i < list.Count; i++)
    87. {
    88. PictureBoxList[i].Image = list[i];
    89. }
    90. pictureBox1.Image = list[0];
    91. //设置坐标
    92. pictureBox1.Location = PicStartPos;
    93. //设置控件宽高
    94. pictureBox1.Size = PicSize;
    95. Label_NumberOfPages.Text = string.Format("{0} / {1}", NowPage, TotalPage);
    96. BackNextButtonType();
    97. }
    98. /// <summary>
    99. /// 下一页
    100. /// </summary>
    101. /// <param name="sender"></param>
    102. /// <param name="e"></param>
    103. private void Button_Next_Click(object sender, EventArgs e)
    104. {
    105. if (NowPage >= TotalPage) return;
    106. NowPage++;
    107. for (int i = 0; i < PictureBoxList.Count; i++)
    108. {
    109. PictureBoxList[i].Image = null;
    110. }
    111. List<Bitmap> list = GetPagesBitmap(NowPage);
    112. for (int i = 0; i < list.Count; i++)
    113. {
    114. PictureBoxList[i].Image = list[i];
    115. }
    116. pictureBox1.Image = list[0];
    117. //设置坐标
    118. pictureBox1.Location = PicStartPos;
    119. //设置控件宽高
    120. pictureBox1.Size = PicSize;
    121. Label_NumberOfPages.Text = string.Format("{0} / {1}", NowPage, TotalPage);
    122. BackNextButtonType();
    123. }
    124. /// <summary>
    125. /// 添加图片
    126. /// </summary>
    127. /// <param name="sender"></param>
    128. /// <param name="e"></param>
    129. private void Button_Add_Click(object sender, EventArgs e)
    130. {
    131. index++;
    132. AddPicture(new Bitmap(FilesinfoList[index]));
    133. if (index >= FilesinfoList.Count - 1)
    134. index = -1;
    135. }
    136. /// <summary>
    137. /// 添加图片
    138. /// </summary>
    139. /// <param name="bitmap"></param>
    140. private void AddPicture(Bitmap bitmap)
    141. {
    142. if (bitmap == null) return;
    143. //添加到图片列表
    144. BitmapList.Add(bitmap);
    145. //界面预留图中显示
    146. pictureBox1.Image = bitmap;
    147. //设置坐标
    148. pictureBox1.Location = PicStartPos;
    149. //设置控件宽高
    150. pictureBox1.Size = PicSize;
    151. //计算当前总页数
    152. int page = BitmapList.Count / PictureBoxList.Count;
    153. int remainder = BitmapList.Count % PictureBoxList.Count;
    154. TotalPage = remainder > 0 ? page + 1 : page;
    155. Label_NumberOfPages.Text = string.Format("{0} / {1}", NowPage, TotalPage);
    156. BackNextButtonType();
    157. //让图片按逆向顺序显示
    158. List<Bitmap> reverseSort = new List<Bitmap>();
    159. for (int i = BitmapList.Count - 1; i >= 0; i--)
    160. {
    161. reverseSort.Add(BitmapList[i]);
    162. }
    163. for (int i = 0; i < reverseSort.Count; i++)
    164. {
    165. if (i <= 7)
    166. PictureBoxList[i].Image = reverseSort[i];
    167. }
    168. }
    169. /// <summary>
    170. /// 8张预览图片的点击事件
    171. /// </summary>
    172. /// <param name="sender"></param>
    173. /// <param name="e"></param>
    174. private void PictureBoxClick(Object sender, System.EventArgs e)
    175. {
    176. PictureBox pictureBox = (PictureBox)sender;
    177. if (pictureBox != null && pictureBox.Image != null)
    178. {
    179. pictureBox1.Image = pictureBox.Image;
    180. //设置坐标
    181. pictureBox1.Location = PicStartPos;
    182. }
    183. }
    184. /// <summary>
    185. /// 获取索引对应的图片
    186. /// </summary>
    187. /// <param name="index"></param>
    188. /// <returns></returns>
    189. private List<Bitmap> GetPagesBitmap(int index)
    190. {
    191. if (BitmapList.Count <= 0) return null;
    192. //页数
    193. int page = BitmapList.Count / PictureBoxList.Count;
    194. //余数
    195. int remainder = BitmapList.Count % PictureBoxList.Count;
    196. //总页数
    197. int allPage = remainder > 0 ? page + 1 : page;
    198. if (index > allPage) return null;
    199. //索引起点
    200. int start = (index * PictureBoxList.Count) - PictureBoxList.Count;
    201. //索引结束点
    202. int end = (index * PictureBoxList.Count) - 1;
    203. if (end > BitmapList.Count) end = BitmapList.Count - 1;
    204. List<Bitmap> reverseSort = new List<Bitmap>();
    205. for (int i = BitmapList.Count - 1; i >= 0; i--)
    206. {
    207. reverseSort.Add(BitmapList[i]);
    208. }
    209. List<Bitmap> list = new List<Bitmap>();
    210. for (int i = start; i <= end; i++)
    211. {
    212. list.Add(reverseSort[i]);
    213. }
    214. if (list.Count > 0)
    215. return list;
    216. return null;
    217. }
    218. /// <summary>
    219. /// 上一页,下一页按钮状态
    220. /// </summary>
    221. private void BackNextButtonType()
    222. {
    223. Button_Next.Enabled = true;
    224. Button_Back.Enabled = true;
    225. //现在页 = 总页数
    226. if (NowPage == TotalPage)
    227. Button_Next.Enabled = false;
    228. //现在页 小于等于 1
    229. if (NowPage <= 1)
    230. Button_Back.Enabled = false;
    231. }
    232. private void pictureBox1_MouseDown(object sender, MouseEventArgs e)
    233. {
    234. if (pictureBox1.Image == null) return;
    235. if (e.Button == MouseButtons.Left)
    236. {
    237. MouseDownPoint.X = Cursor.Position.X; //记录鼠标左键按下时位置
    238. MouseDownPoint.Y = Cursor.Position.Y;
    239. IsMove = true;
    240. pictureBox1.Focus(); //鼠标滚轮事件(缩放时)需要picturebox有焦点
    241. }
    242. }
    243. private void pictureBox1_MouseUp(object sender, MouseEventArgs e)
    244. {
    245. if (e.Button == MouseButtons.Left)
    246. {
    247. IsMove = false;
    248. }
    249. }
    250. private void pictureBox1_MouseMove(object sender, MouseEventArgs e)
    251. {
    252. if (pictureBox1.Image == null) return;
    253. pictureBox1.Focus(); //鼠标在picturebox上时才有焦点,此时可以缩放
    254. if (IsMove)
    255. {
    256. int x, y; //新的pictureBox1.Location(x,y)
    257. int moveX, moveY; //X方向,Y方向移动大小。
    258. moveX = Cursor.Position.X - MouseDownPoint.X;
    259. moveY = Cursor.Position.Y - MouseDownPoint.Y;
    260. x = pictureBox1.Location.X + moveX;
    261. y = pictureBox1.Location.Y + moveY;
    262. pictureBox1.Location = new Point(x, y);
    263. MouseDownPoint.X = Cursor.Position.X;
    264. MouseDownPoint.Y = Cursor.Position.Y;
    265. }
    266. }
    267. private void pictureBox1_MouseWheel(object sender, MouseEventArgs e)
    268. {
    269. if (pictureBox1.Image == null) return;
    270. PictureBox pbox = pictureBox1;
    271. int x = e.Location.X;
    272. int y = e.Location.Y;
    273. int ow = pbox.Width;
    274. int oh = pbox.Height;
    275. int VX, VY; //因缩放产生的位移矢量
    276. if (e.Delta > 0) //放大
    277. {
    278. //第1步
    279. pbox.Width += ZoomStep;
    280. pbox.Height += ZoomStep;
    281. //第2步
    282. PropertyInfo pInfo = pbox.GetType().GetProperty("ImageRectangle", BindingFlags.Instance | BindingFlags.NonPublic);
    283. Rectangle rect = (Rectangle)pInfo.GetValue(pbox, null);
    284. //第3步
    285. pbox.Width = rect.Width;
    286. pbox.Height = rect.Height;
    287. //Console.WriteLine(string.Format("宽:{0},高:{1}",pbox.Width,pbox.Height));
    288. }
    289. if (e.Delta < 0) //缩小
    290. {
    291. //防止一直缩成负值
    292. if (pbox.Width < 300)
    293. return;
    294. pbox.Width -= ZoomStep;
    295. pbox.Height -= ZoomStep;
    296. PropertyInfo pInfo = pbox.GetType().GetProperty("ImageRectangle", BindingFlags.Instance |
    297. BindingFlags.NonPublic);
    298. Rectangle rect = (Rectangle)pInfo.GetValue(pbox, null);
    299. pbox.Width = rect.Width;
    300. pbox.Height = rect.Height;
    301. }
    302. //第4步,求因缩放产生的位移,进行补偿,实现锚点缩放的效果
    303. VX = (int)((double)x * (ow - pbox.Width) / ow);
    304. VY = (int)((double)y * (oh - pbox.Height) / oh);
    305. pbox.Location = new Point(pbox.Location.X + VX, pbox.Location.Y + VY);
    306. }
    307. }
    308. }

    代码中,鼠标缩放,拖拽功能,需要在控件里添加对应的事件,否则就没有效果了

    运行后,效果就如文章开头所示,这个位置还是先不加图片了

    源码:点击下载

    结束

    如果这个帖子对你有用,欢迎 关注 + 点赞 + 留言,谢谢

    end

  • 相关阅读:
    鸿蒙入门-13Gauge组件
    “SiraitiaMove “app Tech Support(URL)
    [oeasy]python0010_hello_world_unix_c历史迷因
    我国智慧燃气建设应用过程中,有哪些关键问题?
    rhcsa5(日志、维护准确时间)
    衡师11月月赛web题目wp
    恋爱脑学Rust之dyn关键字的作用
    图像处理:U-Net中的重叠-切片(Overlap-tile)
    算法专题篇四:前缀和
    TypeScript的安装与简单使用(第一篇)
  • 原文地址:https://blog.csdn.net/qq_38693757/article/details/125395174