|
おかげさまでサムネイル表示が完成しました。
希望通りの動作で、ちらつきも無く速度も速いです。
ありがとうございます。
アドバイスを参考にPictureBox+VScrollBarで実装しました。
マウスでの選択も実装できました。
キー操作には対応していませんが、不要と言われているので、どこかで時間をとってコツコツ実装しようと思います。
本件はこれにて解決とします。
ありがとうございます。
まとめとして作成した実験コードを乗せておきます。
※例外処理は省いてあります。
実験用フォームの構成は下記の通りです。
1.フォームにPanelを配置して、BorderStyleをFixedSingleにする。
2.Panel上にVScrollBarを配置して、DockをRightにする。
3.Panel上にPictureBoxを配置して、DockをFill、BackColorをWindowにする。
まず、下記のような画像情報を管理するクラスを用意して、List<T>にサムネイルを収集します。
public class ImageInfo
{
public string FilePath { get; private set; }
public Image Thumbnail { get; private set; }
public string Text { get; private set; }
public ImageInfo(string path, int thumbWidth, int thumbHeight)
{
FilePath = Path.GetFullPath(path); // 画像ファイルのパスを保持
using (FileStream fs = File.OpenRead(path))
using (Image image = Image.FromStream(fs, false, false))
{
// 指定されたサイズのサムネイルと説明(ファイルベース名)を保持
Thumbnail = image.GetThumbnailImage(thumbWidth, thumbHeight, null, IntPtr.Zero);
Text = Path.GetFileName(path);
}
}
}
実験用フォームクラス内のサムネイル読み込み部分です。
今回は実験なので非同期処理はせずに起動時に呼び出して一気に読み込ませました。
const string TargetFolder = @"D:\Test\Jpegs";
const int ThumbWidth = 160;
const int ThumbHeight = 120;
const int ItemHeight = ThumbHeight + 24;
const int TopMargin = 4;
List<ImageInfo> thumbList_ = new List<ImageInfo>();
int selectedIndex_ = -1;
private void LoadThumbnail()
{
string[] jpgFiles = Directory.GetFiles(TargetFolder, "*.jpg");
foreach (string path in jpgFiles)
{
thumbList_.Add(new ImageInfo(path, ThumbWidth, ThumbHeight));
if (!vScrollBar1.Enabled)
{
pictureBox1.Invalidate();
}
if (ItemHeight * thumbList_.Count <= pictureBox1.Height)
{
vScrollBar1.Value = 0;
vScrollBar1.Enabled = false;
}
else
{
int largeChange = pictureBox1.Height;
vScrollBar1.Maximum = ItemHeight * thumbList_.Count - pictureBox1.Height + largeChange;
vScrollBar1.LargeChange = largeChange;
vScrollBar1.SmallChange = largeChange / 4;
vScrollBar1.Enabled = true;
}
}
}
実験用フォームクラス内のスクロールバースクロールイベントです。
Paintイベントが呼ばれるようにpictureBoxの表示全体を無効化するだけです。
private void vScrollBar1_Scroll(object sender, ScrollEventArgs e)
{
pictureBox1.Invalidate();
}
実験用フォームクラス内のPictureBox描画イベントです。
private void pictureBox1_Paint(object sender, PaintEventArgs e)
{
if (thumbList_.Count > 0)
{
int itemIndex = vScrollBar1.Value / ItemHeight;
int x = (pictureBox1.ClientSize.Width - ThumbWidth) / 2;
for (int y = -(vScrollBar1.Value % ItemHeight); y < pictureBox1.Height && itemIndex < thumbList_.Count; y += ItemHeight)
{
Brush br = (itemIndex == selectedIndex_) ? SystemBrushes.Highlight : SystemBrushes.Window;
e.Graphics.FillRectangle(br, 0, y, pictureBox1.ClientSize.Width, ItemHeight);
e.Graphics.DrawImage(thumbList_[itemIndex].Thumbnail, x, y + TopMargin);
int textTop = y + TopMargin + ThumbHeight;
Rectangle rect = new Rectangle(0, textTop, pictureBox1.ClientSize.Width, y + ItemHeight - textTop);
Color color = (itemIndex == selectedIndex_) ? SystemColors.HighlightText : SystemColors.WindowText;
TextRenderer.DrawText(e.Graphics, thumbList_[itemIndex].Text, this.Font, rect, color, TextFormatFlags.HorizontalCenter);
++itemIndex;
}
}
}
実験用フォームクラス内のPictureBoxマウスダウンイベントです。
アイテムを選択します。
private void pictureBox1_MouseDown(object sender, MouseEventArgs e)
{
int itemIndex = (e.Location.Y + vScrollBar1.Value) / ItemHeight;
if (itemIndex < thumbList_.Count)
{
selectedIndex_ = itemIndex;
pictureBox1.Invalidate();
}
}
|