You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何触发‘Parameter is not valid’异常?WinForms PictureBox问题

为什么设置PictureBox.Image时会触发“Parameter is not valid”异常?

问题场景

选中ListBox中的「Free Roam Shape」项时,代码执行到pictureBoxCroppedImages.Image = composedImage;,通过断点确认composedImage是非空的Bitmap对象,但执行该行后并未进入catch块,直接在Program.cs的Application.Run(new Form1())处抛出以下异常:

System.ArgumentException
  HResult=0x80070057
  Message=Parameter is not valid.
  Source=System.Drawing
  StackTrace:
   at System.Drawing.Image.get_Width()
   at System.Drawing.Image.get_Size()
   at System.Windows.Forms.PictureBox.ImageRectangleFromSizeMode(PictureBoxSizeMode mode)
   at System.Windows.Forms.PictureBox.OnPaint(PaintEventArgs pe)
   at System.Windows.Forms.Control.PaintWithErrorHandling(PaintEventArgs e, Int16 layer)
   at System.Windows.Forms.Control.WmPaint(Message& m)
   at System.Windows.Forms.Control.WndProc(Message& m)
   at System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)
   at System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
   at System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)

关联代码

ListBox选中索引变更事件

private void listBoxCroppedImages_SelectedIndexChanged(object sender, EventArgs e)
{
    if (!isRealTimeCropping)
    {
        var si = ((ListBox)sender).SelectedIndex;
        if (si >= 0 && si < MyItems.Count)
        {
            var selectedItem = MyItems[si];

            // 检查选中项是否为自由漫游形状
            if (selectedItem.Message == "Free Roam Shape")
            {
                // 显示自由漫游形状
                DisplayFreeRoamShape();
            }
            else
            {
                // 显示矩形裁剪图
                var selectedKey = FileList.Keys.ElementAt(si); // 获取对应索引的键
                var selectedValue = FileList.Values.ElementAt(si);

                RichTextBoxController(si, selectedKey, selectedValue);

                if (!string.IsNullOrEmpty(selectedKey) && FileList.ContainsKey(selectedKey))
                {
                    var filePath = FileList[selectedKey];
                    if (File.Exists(filePath))
                    {
                        // 从选中键中提取位置和尺寸
                        Point location = ExtractLocation(selectedKey);
                        Size size = ExtractSize(selectedKey);

                        // 加载图片
                        Image croppedImage = System.Drawing.Image.FromFile(filePath);

                        // 创建带透明背景的新位图
                        Bitmap composedImage = new Bitmap(pictureBoxCroppedImages.Width, pictureBoxCroppedImages.Height);
                        using (Graphics g = Graphics.FromImage(composedImage))
                        {
                            g.Clear(Color.Transparent);

                            // 在指定位置绘制裁剪后的图片
                            g.DrawImage(croppedImage, new Rectangle(location, size));
                        }

                        // 将合成图片设置给PictureBox
                        pictureBoxCroppedImages.Image = composedImage;
                    }
                }
            }
        }
    }
    else
    {
        var si = ((ListBox)sender).SelectedIndex;
        if (si >= 0 && si < FileList.Count)
        {
            var selectedKey = FileList.Keys.ElementAt(si); // 获取对应索引的键
            var selectedValue = FileList.Values.ElementAt(si);

            RichTextBoxController(si, selectedKey, selectedValue);
        }
    }
}

自由漫游形状显示方法

private void DisplayFreeRoamShape()
{
    var si = listBoxCroppedImages.SelectedIndex;

    if (si >= 0 && si < MyItems.Count)
    {
        var selectedItem = MyItems[si];

        if (selectedItem.Message == "Free Roam Shape")
        {
            try
            {
                // 加载并显示对应的自由漫游形状
                if (FreeRoamShapes.Count > 0)
                {
                    var freeRoamShape = FreeRoamShapes[0]; // 假设只有一个自由漫游形状
                    using (Bitmap composedImage = new Bitmap(pictureBoxCroppedImages.Width, pictureBoxCroppedImages.Height))
                    using (Graphics g = Graphics.FromImage(composedImage))
                    {
                        g.Clear(Color.Transparent);
                        using (Pen pen = new Pen(freeRoamShape.Color, 2f))
                        {
                            g.DrawPath(pen, freeRoamShape.Path);
                        }
                        try
                        {
                            pictureBoxCroppedImages.Image = composedImage;
                        }
                        catch(Exception ex)
                        {
                            // 处理显示自由漫游形状时的异常
                            MessageBox.Show("Error displaying the free roam shape: " + ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                // 处理显示自由漫游形状时的异常
                MessageBox.Show("Error displaying the free roam shape: " + ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }
    }
}

问题原因

核心问题出在DisplayFreeRoamShape方法中:composedImage被包裹在using语句中,using块结束时会自动调用Bitmap.Dispose()释放其底层GDI+资源。

虽然你在using块内把composedImage赋值给了pictureBoxCroppedImages.Image,但PictureBox只是持有这个Bitmap对象的引用。当using块执行完毕,Bitmap资源被销毁,后续PictureBox触发重绘(比如OnPaint方法)时,尝试访问已释放资源的Width/Size属性,就会抛出“Parameter is not valid”异常。

另外,异常没有被你的catch块捕获,是因为这个异常并非在赋值语句执行时抛出,而是在后续UI线程的消息循环中处理重绘消息时才触发,超出了当前catch块的作用范围。

解决方案

有两种可行的修复方式:

  1. 移除composedImage的using声明
    手动管理Bitmap的生命周期,注意在设置新Image前释放旧的资源,避免内存泄漏:

    // 替换DisplayFreeRoamShape中的对应代码段
    var freeRoamShape = FreeRoamShapes[0];
    Bitmap composedImage = new Bitmap(pictureBoxCroppedImages.Width, pictureBoxCroppedImages.Height);
    using (Graphics g = Graphics.FromImage(composedImage))
    {
        g.Clear(Color.Transparent);
        using (Pen pen = new Pen(freeRoamShape.Color, 2f))
        {
            g.DrawPath(pen, freeRoamShape.Path);
        }
    }
    // 先释放旧的Image资源
    pictureBoxCroppedImages.Image?.Dispose();
    pictureBoxCroppedImages.Image = composedImage;
    
  2. 创建Bitmap的副本
    在赋值给PictureBox前,创建一个composedImage的副本,这样即使原Bitmap被using释放,副本仍能正常使用:

    // 在using块内修改赋值语句
    pictureBoxCroppedImages.Image = new Bitmap(composedImage);
    

    同样需要注意在设置新Image前释放旧资源。

内容的提问来源于stack exchange,提问作者Daniel Lip

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.07 00:24:55