65.9K
CodeProject 正在变化。 阅读更多。
Home

DataGridView中的图像缩略图预览

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.42/5 (16投票s)

2008年9月16日

CPOL

3分钟阅读

viewsIcon

124268

downloadIcon

7119

展示了如何在 DataGridView 中显示图像,并进行图像大小调整和分页的实现。

引言

这是一个展示如何在 DataGridView 中显示缩略图,并进行图像大小调整和分页的实现。我创建它的主要原因是为了允许用户快速高效地预览数千张图像,同时仍然具有 DataGridView 的核心功能,例如,选择单元格等。

我见过的其他解决方案使用所有者面板或其他控件,这些控件运行良好,但不允许用户选择图像。此外,由于控件是所有者绘制的,因此它们没有像 SelectIndexChanged 等内置事件,这在我的情况下使它们无法使用。我见过的其他解决方案仅显示带有上一个下一个预览的主图像,就像胶片预览一样。同样,我无法使用它们,因为我需要显示数千张图像并且能够快速浏览它们。

所以,如果它可以节省一些人的时间,或者给他们灵感,那就太好了。

ImageDataGridView.png

演示/示例

该实现将尝试动态创建正确的列数以适应 DataGridView 宽度。当 DataGridView 调整大小以适应正确的宽度时,图像会重新加载。

使用滑块控件选择图像缩略图大小。当值更改时,图像会重新加载,并以新的选定图像大小显示当前图像集。

每页显示的图像数量可以通过下拉列表修改。如果值更改,则图像将从头开始重新显示;这纯粹是为了使实现更容易!

代码

列宽是使用以下代码计算的,这使我们能够动态创建所需的列数以适应 DataGridView 的实际宽度

int numColumnsForWidth = (dataViewImages.Width - 10) / (_imageSize + 20);

另一个要求是显示每页所需图像数量的最少行数,原因是我想让它看起来尽可能专业。要计算行数,我们需要计算要显示的图像数量,然后使用适合 DataViewGrid 所需的列数。接下来,我们使用模数运算符来检查计算的余数;如果得到结果,那么我们添加另一行来显示溢出

numRows = numImagesRequired / numColumnsForWidth; 

// Do we have a an overfill for a row
if (numImagesRequired % numColumnsForWidth > 0) 
{ 
   numRows += 1; 
}

该代码使用先前计算的值动态创建列和行。值 **20** 只是一个用于在图像周围创建边框的值,以便用户可以看到选择了哪些图像

// Dynamically create the columns
{
    dataViewImages.Columns.Add(dataGridViewColumn);
    dataViewImages.Columns[index].Width = _imageSize + 20;
}

// Create the rows
for (int index = 0; index < numColumnsForWidth; index++)
{
    DataGridViewImageColumn dataGridViewColumn = 
                            new DataGridViewImageColumn();

    dataViewImages.Rows.Add();
    dataViewImages.Rows[index].Height = _imageSize + 20;
}

图像是从先前加载的 List<string> 变量动态加载的,该变量包含图像路径。实际图像是从文件系统加载的。该代码将文件名分配给工具提示,以便可以轻松识别图像

// Load the image from the file and add to the DataGridView
Image image = Helper.ResizeImage(_files[index], 
                                 _imageSize, 
                                 _imageSize, 
                                 false);

dataViewImages.Rows[rowIndex].Cells[columnIndex].Value = image;
dataViewImages.Rows[rowIndex].Cells[columnIndex].ToolTipText = 
                    Path.GetFileName(_files[index]);

上面的代码引用了一个 Helper.ResizeImage 函数,这是一个简单的例程,顾名思义,它将在内存中调整图像大小

public static Image ResizeImage(string file,
                                     int width,
                                     int height,
                                     bool onlyResizeIfWider)
{
    using (Image image = Image.FromFile(file))
    {
        // Prevent using images internal thumbnail
        image.RotateFlip(RotateFlipType.Rotate180FlipNone);
        image.RotateFlip(RotateFlipType.Rotate180FlipNone);

        if (onlyResizeIfWider == true)
        {
            if (image.Width <= width)
            {
                width = image.Width;
            }
        }

        int newHeight = image.Height * width / image.Width;
        if (newHeight > height)
        {
            // Resize with height instead
            width = image.Width * height / image.Height;
            newHeight = height;
        }

        Image NewImage = image.GetThumbnailImage(width, 
                                                 newHeight, 
                                                 null, 
                                                 IntPtr.Zero);

        return NewImage;
    }
}

因为某些行将具有没有图像的单元格,原因是显示的图像数量不等于行数 * 列数,我们需要将单元格设置为 null 值,否则会显示一个通用的未找到图像图标,这很难看

// Blank the unused cells
if (numGeneratedCells > numImagesRequired)
{
    for (int index = 0; index < 
         numGeneratedCells - numImagesRequired; index++)
    {
        DataGridViewCellStyle dataGridViewCellStyle = 
                              new DataGridViewCellStyle();
        dataGridViewCellStyle.NullValue = null;
        dataGridViewCellStyle.Tag = "BLANK";
        dataViewImages.Rows[rowIndex].Cells[columnIndex + 
                            index].Style = dataGridViewCellStyle;
    }
}

其余代码处理检查列表边界条件,以处理诸如用户显示的图像少于每页图像数量设置的情况。此外,另一个关键检查是确保当我们到达列表末尾时,我们可以显示所有图像。

历史

  • v1.0.0 - 初始版本。
© . All rights reserved.