C# 显示目录中的图像

C# 显示目录中的图像,c#,.net,loops,directory,picturebox,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()); Pic

我有以下代码:

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]);
        }
    }
MessageBox似乎显示了正确的诊断信息(文件夹位置、卡片文件名,甚至files.Count()似乎也正确),但我无法在pictureboxes中显示任何文件。有什么建议吗

编辑:显然,这条线

MessageBox.Show(Form1.programdir + "\\card_images\\" + files[i]);
永远都不会跑,即使

MessageBox.Show(files.ElementAt(1).ToString());
它跑了。而且

MessageBox.Show(i.ToString());
仅运行一次,在messagebox中输出“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]);
        }
    }
private void Form2\u加载(对象发送方,事件参数e)
{
Uri baseUri=新Uri(Form1.programdir+“\\card\u images\\”;
string[]files=Directory.GetFiles(Form1.programdir+“\\card\u images”、“*”,SearchOption.TopDirectoryOnly);
Show(files.Count().ToString());
PictureBox[]卡=新PictureBox[files.Count()];
对于(int i=0;i

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

因此,问题似乎是,由于对
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\u images
文件夹中有任何文件不能由
Bitmap
类处理。这很好,但它不会从文档文件或DLL中呈现图像:p

最后一个想法:断点和单步调试肯定会帮助您更快地发现问题。如果您没有其他任何东西,Visual Studio Express就足以完成此任务


更新:处理长路径名

长话短说,长文件名是后端的难题

说来话长

经过一点检查后,似乎.NET framework设计的(参见2007年)不会处理长路径名。所有.NET类都会拒绝
\\?\
前缀,如果长度超过MAX\u路径字符,则形式为
//localhost/C$//……
的UNC路径也会被拒绝

对此,您只能做几件事:

  • NET设计人员建议的解决方案是通过将文件重新定位到较短的路径来消除长路径(换句话说,甚至不要尝试使用长路径)

  • 创建具有长路径支持的
    System.IO
    类的新版本。(不适用于胆小鬼。)

  • 各种各样的破解方法比比皆是,包括(旧的
    subst
    dos命令的核心)将可用的驱动器号映射到符合MAX_路径限制的路径子集。(有趣,但很有技巧。)

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

  • 我将关注最后一个选项

    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
    {
    const int MAX_PATH=260;
    //强制unicode版本获得长路径支持
    [DllImport(“kernel32.dll”,CharSet=CharSet.Unicode,SetLastError=true)]
    静态外部uint GetShortPathNameW(
    [Marshallas(UnmanagedType.LPTStr)]
    字符串lpszLongPath,
    [Marshallas(UnmanagedType.LPTStr)]
    StringBuilder lpszShortPath,
    uint cchBuffer
    );
    公共静态字符串短路径(字符串长路径)
    {
    //检查路径是否已经足够短
    if(string.IsNullOrWhiteSpace(longPath)| | longPath.Length 4字节有效
    
    如果(结果)可能是一个愚蠢的问题,但您是否尝试过
    卡片[i].Visible=true;
    ?@Corey是的,我已经尝试过了;一个有趣的信息也引起了我的注意,我将用新信息编辑我的原始问题……也许因为这只是您代码的一个示例,这对您来说不是一个真正的问题,而是
    目录.GetFiles()
    返回文件的完整路径,而不仅仅是它们的名称。因此,您的连接步骤将产生无效路径。此外,我已经有一段时间没有看到这个问题了(VS的旧版本),但过去有一些错误不容易在
    中捕获
    
    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;
        }
    }