显示目录中的图像

时间:2013-12-05 00:19:25

标签: c# .net loops directory picturebox

我有以下代码:

private void Form2_Load(object sender, EventArgs e)
    {
        string[] files = Directory.GetFiles(Form1.programdir + "\\card_images", "*", SearchOption.TopDirectoryOnly);
        MessageBox.Show(files.ElementAt(1).ToString());
        PictureBox[] cards = new PictureBox[files.Count()];
        for (int i = 0; i < files.Count(); i++)
        {
            MessageBox.Show(i.ToString());
            cards[i] = new PictureBox();
            cards[i].BackgroundImage = new Bitmap(Form1.programdir + "\\card_images\\" + files[i]);
            MessageBox.Show(Form1.programdir + "\\card_images\\" + files[i]);
            cards[i].Padding = new Padding(0);
            cards[i].BackgroundImageLayout = ImageLayout.Stretch;
            cards[i].MouseDown += new MouseEventHandler(card_click);
            cards[i].Size = new Size((int)(this.ClientSize.Width / 2) - 15, images.Height);
                images.Controls.Add(cards[i]);
        }
    }

注意:“images”是我程序的图形设计器中的FlowLayoutPanel。我用它来轻松跟踪图像。

我正试图从目录中显示一些扑克牌的图像。目录是正确的,文件夹在那里,以前文件夹的使用工作; Form1是该程序的第一种形式,“programdir”是:

public static string programdir = Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location);

消息框似乎显示正确的诊断信息(文件夹位置,卡文件名,甚至files.Count()似乎是正确的),但我无法在图片框中显示任何文件。有什么建议吗?

编辑:显然,行

MessageBox.Show(Form1.programdir + "\\card_images\\" + files[i]);

即使

,也根本不会运行
MessageBox.Show(files.ElementAt(1).ToString());

运行。同样,

MessageBox.Show(i.ToString());

只运行一次,在消息框中输出“0”(因为“i”最初设置为0),即使它应该运行4次,因为数组“files”的大小是4。

编辑2:运行完美的新代码是:

private void Form2_Load(object sender, EventArgs e)
    {
        Uri baseUri = new Uri(Form1.programdir + "\\card_images\\");
        string[] files = Directory.GetFiles(Form1.programdir + "\\card_images", "*", SearchOption.TopDirectoryOnly);
        MessageBox.Show(files.Count().ToString());
        PictureBox[] cards = new PictureBox[files.Count()];
        for (int i = 0; i < files.Count(); i++)
        {
            Bitmap bmp = null;
            Uri completeUri = new Uri(baseUri, files[i]);
            try
            {
                bmp = new Bitmap(completeUri.LocalPath);
            }
            catch (Exception exc)
            {
                // remove this if you don't want to see the exception message
                MessageBox.Show(exc.Message);
                continue;
            }
            MessageBox.Show(i.ToString());
            cards[i] = new PictureBox();
            cards[i].BackgroundImage = bmp;
            MessageBox.Show(Form1.programdir + "\\card_images\\" + files[i]);
            cards[i].Padding = new Padding(0);
            cards[i].BackgroundImageLayout = ImageLayout.Stretch;
            cards[i].MouseDown += new MouseEventHandler(card_click);
            cards[i].Size = new Size((int)(this.ClientSize.Width / 2) - 15, images.Height);
            cards[i].Visible = true;
                images.Controls.Add(cards[i]);
        }
    }

try / catch块不是强制性的,因为它不再捕获任何错误,但我正在引导它,以防万一其他事情发生在路上。此代码将从文件夹中获取所有图像(假设只有图像文件位于文件夹中,这是一个单独的问题),显示它们,并一次性为您烘焙蛋糕。

1 个答案:

答案 0 :(得分:2)

所以问题似乎是你试图加载的路径是无效的,因为对Directory.GetFiles()的输出有一些假设,再加上你通常希望看到的异常是默默地放弃了。

考虑到这一点,这是我对重写的看法:

private void Form2_Load(object sender, EventArgs e)
{
    string[] files = Directory.GetFiles(Form1.programdir + "\\card_images", "*", SearchOption.TopDirectoryOnly);

    foreach (var filename in files)
    {
        Bitmap bmp = null;
        try
        {
            bmp = new Bitmap(filename);
        }
        catch (Exception e)
        {
            // remove this if you don't want to see the exception message
            MessageBox.Show(e.Message);
            continue;
        }

        var card = new PictureBox();
        card.BackgroundImage = bmp;
        card.Padding = new Padding(0);
        card.BackgroundImageLayout = ImageLayout.Stretch;
        card.MouseDown += new MouseEventHandler(card_click);
        card.Size = new Size((int)(this.ClientSize.Width / 2) - 15, images.Height);

        images.Controls.Add(card);
    }
}

我跳过创建一个数组,因为你还没有保留它,并取出了你的诊断MessageBox来电。此代码应加载它找到的任何文件,忽略因任何原因无法加载的任何文件,并为每个成功加载的文件创建PictureBox

顺便提一下,失败的一个可能原因是card_images文件夹中有Bitmap类无法处理的任何文件。这很好,但它不会从文档文件或DLL渲染图像:P

最后的想法:断点和单步调试肯定会帮助您更快地找到问题。如果您没有其他任何内容,Visual Studio Express就足以完成任务。


更新:处理长路径名

长话短说,长文件名是后端的痛苦。

长篇故事......

经过一些检查后,似乎.NET框架按设计(参见2007年的this series of articles)将无法处理长路径名。 \\?\前缀被所有.NET类拒绝,如果//localhost/C$/...........形式的UNC路径长度超过MAX_PATH字符,也会被拒绝。

您只能做一些事情:

  1. .NET设计人员建议的解决方案是通过将文件重定位到更短的路径来摆脱长路径。 (换句话说,甚至尝试使用长路径。)

  2. 使用长路径支持创建System.IO类的新版本。 (不适合胆小的人。)

  3. 各种各样的黑客攻击比比皆是,包括using the DefineDosDevice API(旧subst dos命令的核心),以将可用的驱动器号映射到适合MAX_PATH限制内的路径的某个子集。 (有趣,但很难。)

  4. 使用GetShortPathName API函数,使用文件系统中创建的8.3缩写将长路径转换为自身的缩写版本。

  5. 我将专注于最后一个选项。

    public static class NativeMethods
    {
        const int MAX_PATH = 260;
    
        // Force unicode version to get long-path support
        [DllImport("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
        static extern uint GetShortPathNameW(
                [MarshalAs(UnmanagedType.LPTStr)]
                string lpszLongPath,
                [MarshalAs(UnmanagedType.LPTStr)]
                StringBuilder lpszShortPath,
                uint cchBuffer
            );
    
        public static string ShortenPath(string longPath)
        {
            // check if path is already short enough
            if (string.IsNullOrWhiteSpace(longPath) || longPath.Length <= MAX_PATH)
                return longPath;
    
            // Get short version of path 
            StringBuilder shortNameBuffer = new StringBuilder(MAX_PATH);
            uint result = GetShortPathNameW(@"\\?\" + longPath, shortNameBuffer, (uint)MAX_PATH);
    
            // result is length of returned path.  Must be >4 bytes to be valid
            if (result <= 4)
                return null;
    
            // Get result, removing "\\?\" prefix
            var res = shortNameBuffer.ToString().Substring(4);
            return res;
        }
    }
    

    使用任意长度的有效路径调用NativeMethods.ShortenPath,如有必要,它会尝试缩短它。如果找不到文件,将在长路径上失败,并且如果结果缩短的文件名长度大于MAX_PATH字符,则可能返回无效结果...这意味着您在路径中有27个具有长名称的目录,这是反正很傻:P

    当然,现在你已经发布了你的解决方法......事实证明这条路径实际上并不太长。 叹息如果您达到了路径限制,这仍然有用。