先看图,基本按你的要求
[attach]66592[/attach]
一、这里为了方便示例我增加了一个“文件夹”按钮,其余和你要求的相同,这个按钮的作用是点击后弹出一个FolderBrowserDialog供选择文件夹,选定一个文件夹后在这个文件夹及其子文件夹中查找是否有图片文件,放置有图片文件的文件夹将被添加到ComboBox中以供下一步选择;
二、在ComboBox中选择文件夹,然后点击“载入图片”按钮将选定文件夹中的图片生成缩略图并在缩略图区域的各个PictureBox中显示,载入的数量不超过缩略图区PictureBox的数量;
三、点击缩略图将从文件中载入相应的原图显示在最上方的PictureBox中;
四、最下方的HScrollBar在载入缩略图后确定其Maximum值,拖动可以变更缩略图显示的范围;
五、缩略图区域PictureBox的数量由缩略图PictureBox控件所占区域大小和应用程序窗体宽度决定,窗体宽度的变更可以导致缩略图PictureBox的数量减少或增加,缩略图PictureBox的数量增加后可以显示更多的之前未能显示出来的图片(假如有的话,如果没有则不显示任何东西);
六、作为一个例子,这里展示了Windows窗体控件的动态使用、事件处理、Linq、图片缩略图的获取、类的扩展等一点知识,这些都是很基本的东西,希望你能掌握;
七、代码里面我没有添加任何注释,这样做不是希望你看不懂,恰恰相反,我是希望你能深刻理解这些代码,直接看到注释知道代码的功能显然不能给你留下深刻的印象,下次要用的时候不一定写得出来,实在没办法理解你再问吧,到时我再标上去;
八、仓促写成,仅为了示例,没有进行错误处理等。另如有错漏之处,还望指正!
下面是代码:
FormMain.cs
程序代码:using System;
using System.Collections.Generic;
using System.Drawing;
using using System.Linq;
using System.Windows.Forms;
namespace ImageViewDemo
{
public partial class FormMain : Form
{
#region 只读全局字段
private readonly List<PictureBox> _pictureBoxs; //用来存放缩略图PictureBox控件的集合
private readonly int _thumbPictureBoxHeight; //缩略图PictureBox的高度,用于生成缩略图
private readonly int _thumbPictureBoxWidth; //缩略图PictureBox的宽度,用于生成缩略图
private readonly int _regionWidthPerThumbPictureBox; //缩略图PictureBox在界面上占用的宽度,用于计算是否需要添加或减少缩略图PuctureBox
#endregion
#region 构造函数
public FormMain()
{
InitializeComponent();
_pictureBoxs = new List<PictureBox>(); //初始化集合
//循环将Flp中的所有类型为PicutreBox的控件添加进集合并设置PicutreBox鼠标点击时的处理程序
foreach (var pictureBox in Flp.Controls.OfType<PictureBox>())
{
_pictureBoxs.Add(pictureBox);
pictureBox.Click += ThumbPictureBox_Click;
}
_thumbPictureBoxHeight = _pictureBoxs[0].Height;
_thumbPictureBoxWidth = _pictureBoxs[0].Width;
_regionWidthPerThumbPictureBox = _thumbPictureBoxWidth + _pictureBoxs[0].Margin.Left + _pictureBoxs[0].Margin.Right;
}
#endregion
#region 控件事件
private void ButBrowser_Click(object sender, EventArgs e)
{
//打开一个目录选择对话框选择目录
var fbd = new FolderBrowserDialog { ShowNewFolderButton = true };
if (fbd.ShowDialog() != DialogResult.OK) return;
CobFolders.Items.Clear();
//获取选定目录及其所有子文件夹中包含有指定类型图片的文件夹并将其路径添加进CobFolders
foreach (var directory in GetDirectoriesIncludeImage(fbd.SelectedPath))
CobFolders.Items.Add(directory);
}
private void ButLoad_Click(object sender, EventArgs e)
{
if (CobFolders.SelectedIndex == -1) return; //当前没有任何路径则退出
var files = CobFolders.Text.GetImageFiles(); //获取CobFolders当前选择路径中所有的图片文件路径数组
Hsb.Tag = files; //将获得的文件路径数组保存到Hsb中
Hsb.Maximum = files.Count - 1; //设置滚动栏最大滚动范围
Hsb.Value = 0; //重置滚动栏初始位置
LoadThumbil(); //载入缩略图显示在缩略图PictureBox中
}
//当窗体宽度改变时,确定是否需要增加或减少缩略图PictureBox的数量,需要则增加或减少
private void Flp_SizeChanged(object sender, EventArgs e)
{
var thumbPictureBoxCount = (int)Math.Floor((double)Flp.Width / _regionWidthPerThumbPictureBox);//计算当前的宽度能够容纳多少个缩略图PictureBox
var files = (List<string>) Hsb.Tag;
if (thumbPictureBoxCount > _pictureBoxs.Count)
{
//如果能容纳的缩略图PictureBox数量大于现有的缩略图PictureBox的数量则添加缩略图PictureBox
var lastThumbPictureBox = _pictureBoxs[_pictureBoxs.Count - 1]; //获取当前最后一个缩略图PictureBox
//应该增加的缩略图PictureBox的数量是可容纳数量-现有数量,就循环这么多次进行添加
for (var i = 0; i < thumbPictureBoxCount - _pictureBoxs.Count; i++)
{
var thumbPictureBox = new PictureBox { Width = _thumbPictureBoxWidth, Height = _thumbPictureBoxHeight }; //创建PictureBox的实例并设置宽高
_pictureBoxs.Add(thumbPictureBox); //添加进数组
Flp.Controls.Add(thumbPictureBox); //添加到父容器
thumbPictureBox.Click += ThumbPictureBox_Click; //指定鼠标点击处理事件
if (lastThumbPictureBox.Tag == null) continue; //如果当前最后一个缩略图PictureBox的Tag为Null说明所有的图片已全部显示了,则继续添加
var pictureBoxFileIndex = (int)lastThumbPictureBox.Tag; //取当前最后一个缩略图的索引值
pictureBoxFileIndex++;
if (pictureBoxFileIndex >= files.Count) continue; //如果索引值大于文件数量则也不用生成缩略图
thumbPictureBox.Tag = pictureBoxFileIndex; //将索引值保存到缩略图PictureBox的Tag属性以便鼠标点击时使用
LoadThumbImageToThumbPictureBox(thumbPictureBox, files[pictureBoxFileIndex]); //生成缩略图并显示在刚添加的这个缩略图PictureBox中
}
}
else if (thumbPictureBoxCount < _pictureBoxs.Count)
{
//如果能容纳的缩略图PictureBox数量小于现有的缩略图PictureBox的数量则减少缩略图PictureBox的数量
for (var i = 0; i < _pictureBoxs.Count - thumbPictureBoxCount; i++)
{
_pictureBoxs.RemoveAt(_pictureBoxs.Count - 1);//在数组中移除缩略图PictureBox
Flp.Controls.RemoveAt(Flp.Controls.Count - 1);//在父容器中移除缩略图PictureBox
}
}
else return; //如果可容纳的缩略图PictureBox的数量等于现有的缩略图PictureBox的数量则直接退出
Hsb.LargeChange = _pictureBoxs.Count; //缩略图PictureBox的数量改变后要设置滚动栏的LargeChange值以反映变化
}
//滚动栏Value改变时要更新缩略图区域
private void Hsb_ValueChanged(object sender, EventArgs e)
{
var files = (List<string>) Hsb.Tag;
var value = Hsb.Value;
//根据滚动栏Value的值生成每个缩略图并更新每个缩略图PictureBox的图片索引值
for (var i = 0; i < _pictureBoxs.Count; i++)
{
LoadThumbImageToThumbPictureBox(_pictureBoxs[i], files[i + value]);
_pictureBoxs[i].Tag = i + value;
}
}
//鼠标点击缩略图PictureBox时在上面大图显示原图
void ThumbPictureBox_Click(object sender, EventArgs e)
{
var thumbPictureBox = (PictureBox) sender;
if (thumbPictureBox.Tag == null) return;
Pb.Image = Image.FromFile(((List<string>)Hsb.Tag)[(int)thumbPictureBox.Tag]);
}
#endregion
#region 私有方法
//载入现有缩略图PictureBox数量的图片生成缩略图显示出来
private void LoadThumbil()
{
var files = (List<string>) Hsb.Tag;
for (var i = 0; i < _pictureBoxs.Count; i++)
{
_pictureBoxs[i].Image = null;
if (i >= files.Count) continue;
LoadThumbImageToThumbPictureBox(_pictureBoxs[i], files[i]);
_pictureBoxs[i].Tag = i;
}
}
//从指定路径的图片生成缩略图显示在指定的缩略图PictureBox中
private void LoadThumbImageToThumbPictureBox(PictureBox pictureBox, string filePath)
{
var image = Image.FromFile(filePath); //载入原图
var imageRatio = (double)image.Width / image.Height;//获取图片宽高比
int thumbHeight, thumbWidth;
if (imageRatio >= 1)
{
//如果宽高比大于等于1,说明是横式图片,那么缩略图的最大宽度等于缩略图PictureBox的宽度,当然现在默认的缩略图PictureBox是竖式的,实际使用中如果是横式的则不是这样处理,要反过来
thumbWidth = _thumbPictureBoxWidth;
thumbHeight = (int)Math.Floor((double)thumbWidth / image.Width * image.Height); //根据缩略图宽度按比例得到缩略图高度,这样就不会变形
}
else
{
////如果宽高比小于1,说明是竖式图片,那么缩略图的最大高度等于缩略图PictureBox的高度,实际使用中还是要和PictureBox的比例进行比较的,我这里只是个例子,不做严格处理,但你要明白我这里是不太严谨的
thumbHeight = _thumbPictureBoxHeight;
thumbWidth = (int)Math.Floor((double)thumbHeight / image.Height * image.Width);
}
pictureBox.Image = image.GetThumbnailImage(thumbWidth, thumbHeight, null, IntPtr.Zero); //生成缩略图
}
#endregion
#region 静态私有方法
//在指定目录及其所有子目录下查找所有包含指定类型图片的文件夹
private static IEnumerable<string> GetDirectoriesIncludeImage(string directory)
{
var result = new List<string>();
if (directory.DirectoryHasImageFile()) result.Add(directory);
var directories = Directory.GetDirectories(directory, "*", SearchOption.AllDirectories);
foreach (var dir in directories)
{
if (!dir.DirectoryHasImageFile()) continue;
result.Add(dir);
}
return result;
}
#endregion
}
public static class StringExtension
{
private static readonly string[] extensions = new[] { "*.jpg", "*.png", "*.tif", "*.bmp", "*.gif", "*.wmf" };
#region 类扩展方法
//定义string类的扩展方法以判断此字符串实例所表示的目录下(不包括其子目录)是否存在有指定类型的图片文件
public static bool DirectoryHasImageFile(this string directory)
{
var result = false;
//循环取每种类型图片的文件
foreach (var extension in extensions)
{
result = Directory.GetFiles(directory, extension, SearchOption.TopDirectoryOnly).Any();
if (!result) continue;
break;
}
return result;
}
//定义string类的扩展方法以在此字符串实例所表示的目录下(不包括其子目录)获取指定类型的图片文件的路径集合
public static List<string> GetImageFiles(this string directory)
{
var result = new List<string>();
//循环取每种类型图片的文件加入结果集合
foreach (var extension in extensions)
result.AddRange(Directory.GetFiles(directory, string.Concat("*", extension), SearchOption.TopDirectoryOnly));
return result;
}
#endregion
}
}
FormMain.Designer.cs
程序代码:namespace ImageViewDemo
{
partial class FormMain
{
private components = null;
protected override void Dispose(bool disposing)
{
if (disposing && (components != null)) components.Dispose();
base.Dispose(disposing);
}
private void InitializeComponent()
{
this.Pb = new System.Windows.Forms.PictureBox();
this.CobFolders = new System.Windows.();
this.ButLoad = new System.Windows.Forms.Button();
this.Flp = new System.Windows.Forms.FlowLayoutPanel();
this.pictureBox1 = new System.Windows.Forms.PictureBox();
this.pictureBox2 = new System.Windows.Forms.PictureBox();
this.pictureBox3 = new System.Windows.Forms.PictureBox();
this.pictureBox4 = new System.Windows.Forms.PictureBox();
this.pictureBox5 = new System.Windows.Forms.PictureBox();
this.pictureBox6 = new System.Windows.Forms.PictureBox();
this.Hsb = new System.Windows.Forms.HScrollBar();
this.ButBrowser = new System.Windows.Forms.Button();
(()(this.Pb)).BeginInit();
this.Flp.SuspendLayout();
(()(this.pictureBox1)).BeginInit();
(()(this.pictureBox2)).BeginInit();
(()(this.pictureBox3)).BeginInit();
(()(this.pictureBox4)).BeginInit();
(()(this.pictureBox5)).BeginInit();
(()(this.pictureBox6)).BeginInit();
this.SuspendLayout();
this.Pb.Anchor =
((System.Windows.Forms.AnchorStyles)
((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
| System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.Pb.Location = new System.Drawing.Point(12, 12);
this.Pb.Name = "Pb";
this.Pb.Size = new System.Drawing.Size(456, 249);
this.Pb.SizeMode = System.Windows.Forms.PictureBoxSizeMode.Zoom;
this.Pb.TabIndex = 0;
this.Pb.TabStop = false;
this.CobFolders.Anchor =
((System.Windows.Forms.AnchorStyles)
(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.CobFolders.FormattingEnabled = true;
this.CobFolders.Location = new System.Drawing.Point(109, 267);
this.CobFolders.Name = "CobFolders";
this.CobFolders.Size = new System.Drawing.Size(249, 20);
this.CobFolders.TabIndex = 1;
this.ButLoad.Anchor =
((System.Windows.Forms.AnchorStyles)
((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
this.ButLoad.Location = new System.Drawing.Point(364, 265);
this.ButLoad.Name = "ButLoad";
this.ButLoad.Size = new System.Drawing.Size(104, 23);
this.ButLoad.TabIndex = 2;
this.ButLoad.Text = "载入图片(&L)";
this.ButLoad.UseVisualStyleBackColor = true;
this.ButLoad.Click += new System.EventHandler(this.ButLoad_Click);
this.Flp.Anchor =
((System.Windows.Forms.AnchorStyles)
(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.Flp.Controls.Add(this.pictureBox1);
this.Flp.Controls.Add(this.pictureBox2);
this.Flp.Controls.Add(this.pictureBox3);
this.Flp.Controls.Add(this.pictureBox4);
this.Flp.Controls.Add(this.pictureBox5);
this.Flp.Controls.Add(this.pictureBox6);
this.Flp.Location = new System.Drawing.Point(12, 293);
this.Flp.Name = "Flp";
this.Flp.Size = new System.Drawing.Size(456, 96);
this.Flp.TabIndex = 3;
this.Flp.WrapContents = false;
this.Flp.SizeChanged += new System.EventHandler(this.Flp_SizeChanged);
this.pictureBox1.Location = new System.Drawing.Point(3, 3);
this.pictureBox1.Name = "pictureBox1";
this.pictureBox1.Size = new System.Drawing.Size(70, 90);
this.pictureBox1.TabIndex = 0;
this.pictureBox1.TabStop = false;
this.pictureBox2.Location = new System.Drawing.Point(79, 3);
this.pictureBox2.Name = "pictureBox2";
this.pictureBox2.Size = new System.Drawing.Size(70, 90);
this.pictureBox2.TabIndex = 1;
this.pictureBox2.TabStop = false;
this.pictureBox3.Location = new System.Drawing.Point(155, 3);
this.pictureBox3.Name = "pictureBox3";
this.pictureBox3.Size = new System.Drawing.Size(70, 90);
this.pictureBox3.TabIndex = 2;
this.pictureBox3.TabStop = false;
this.pictureBox4.Location = new System.Drawing.Point(231, 3);
this.pictureBox4.Name = "pictureBox4";
this.pictureBox4.Size = new System.Drawing.Size(70, 90);
this.pictureBox4.TabIndex = 3;
this.pictureBox4.TabStop = false;
this.pictureBox5.Location = new System.Drawing.Point(307, 3);
this.pictureBox5.Name = "pictureBox5";
this.pictureBox5.Size = new System.Drawing.Size(70, 90);
this.pictureBox5.TabIndex = 4;
this.pictureBox5.TabStop = false;
this.pictureBox6.Location = new System.Drawing.Point(383, 3);
this.pictureBox6.Name = "pictureBox6";
this.pictureBox6.Size = new System.Drawing.Size(70, 90);
this.pictureBox6.TabIndex = 5;
this.pictureBox6.TabStop = false;
this.Hsb.Anchor =
((System.Windows.Forms.AnchorStyles)
(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.Hsb.LargeChange = 6;
this.Hsb.Location = new System.Drawing.Point(12, 392);
this.Hsb.Maximum = 7;
this.Hsb.Name = "Hsb";
this.Hsb.Size = new System.Drawing.Size(456, 17);
this.Hsb.TabIndex = 4;
this.Hsb.ValueChanged += new System.EventHandler(this.Hsb_ValueChanged);
this.ButBrowser.Anchor =
((System.Windows.Forms.AnchorStyles)
((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
this.ButBrowser.Location = new System.Drawing.Point(12, 265);
this.ButBrowser.Name = "ButBrowser";
this.ButBrowser.Size = new System.Drawing.Size(91, 23);
this.ButBrowser.TabIndex = 5;
this.ButBrowser.Text = "文件夹(&F)...";
this.ButBrowser.UseVisualStyleBackColor = true;
this.ButBrowser.Click += new System.EventHandler(this.ButBrowser_Click);
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(480, 415);
this.Controls.Add(this.ButBrowser);
this.Controls.Add(this.Hsb);
this.Controls.Add(this.Flp);
this.Controls.Add(this.ButLoad);
this.Controls.Add(this.CobFolders);
this.Controls.Add(this.Pb);
this.Name = "FormMain";
this.ShowIcon = false;
this.Text = "Image Viewer Demo by mmxo";
(()(this.Pb)).EndInit();
this.Flp.ResumeLayout(false);
(()(this.pictureBox1)).EndInit();
(()(this.pictureBox2)).EndInit();
(()(this.pictureBox3)).EndInit();
(()(this.pictureBox4)).EndInit();
(()(this.pictureBox5)).EndInit();
(()(this.pictureBox6)).EndInit();
this.ResumeLayout(false);
}
private System.Windows.Forms.PictureBox Pb;
private System.Windows. CobFolders;
private System.Windows.Forms.Button ButLoad;
private System.Windows.Forms.FlowLayoutPanel Flp;
private System.Windows.Forms.PictureBox pictureBox1;
private System.Windows.Forms.PictureBox pictureBox2;
private System.Windows.Forms.PictureBox pictureBox3;
private System.Windows.Forms.PictureBox pictureBox4;
private System.Windows.Forms.PictureBox pictureBox5;
private System.Windows.Forms.PictureBox pictureBox6;
private System.Windows.Forms.HScrollBar Hsb;
private System.Windows.Forms.Button ButBrowser;
}
}
[ 本帖最后由 mmxo 于 2012-11-29 22:07 编辑 ]









