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

WinForms中如何创建可存入数组并删除的叠加图像对象?

WinForms图像分层叠加程序:叠加图像无法删除的解决方案

问题描述

开发一款WinForms图像分层叠加程序,需求如下:

  • 将叠加图像以对象形式存入集合,方便后续管理
  • 通过列表选中指定叠加图像后,点击删除按钮移除该图像

目前已实现背景图功能,但添加叠加图像转为Bitmap后无法精准删除已叠加的图像,现有代码如上。

核心问题分析

当前代码直接将PictureBox添加到Strats.Controls中,但未维护独立集合追踪这些叠加图像对象,也未建立列表项与对应图像的关联,导致无法定位并删除指定叠加图像;同时直接引用Resources中的图像可能引发资源锁定问题。

修改方案与完整代码

1. 创建叠加图像实体类

封装叠加图像的名称与对应的PictureBox,实现列表项与图像的关联:

public class OverlayImage
{
    public string Name { get; set; }
    public PictureBox PictureBox { get; set; }
}

2. 完整修改后的Form代码

using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Windows.Forms;

namespace BattlePlannerTryTwo
{
    public class OverlayImage
    {
        public string Name { get; set; }
        public PictureBox PictureBox { get; set; }
    }

    public partial class Form1 : Form
    {
        private Image file;
        private Image Mapfile;
        private List<OverlayImage> _overlayImages = new List<OverlayImage>();

        public Form1()
        {
            InitializeComponent();
            Strats.SizeMode = PictureBoxSizeMode.Zoom;
            textBox1.Location = new Point();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            // 初始化控件布局
            Strats.Width = this.Width - 400;
            Strats.Height = this.Height - 90;

            ObjectListView.Width = 300;
            ObjectListView.Height = this.Height - 70;
            ObjectListView.Location = new Point(this.Width - 330, 10);

            textBox2.Location = new Point(200, this.Height - 70);
            textBox1.Location = new Point(12, this.Height - 70);

            OperatorComboBox.Location = new Point(100, this.Height - 70);
            MapComboBox.Location = new Point(290, this.Height - 70);

            SaveBtn.Location = new Point(390, this.Height - 70);
            ClearPageBtn.Location = new Point(450, this.Height - 70);
            
            // 添加删除按钮(若窗体已存在则无需此段)
            Button deleteBtn = new Button();
            deleteBtn.Text = "删除选中项";
            deleteBtn.Location = new Point(520, this.Height - 70);
            deleteBtn.Click += DeleteBtn_Click;
            this.Controls.Add(deleteBtn);
        }

        private void StratBox_Click(object sender, EventArgs e)
        {
            if (file == null || OperatorComboBox.SelectedItem == null) return;

            // 创建独立Bitmap实例,避免资源锁定
            Bitmap bitmap = new Bitmap(file);

            PictureBox operatorBox = new PictureBox();
            operatorBox.Image = bitmap;
            operatorBox.Width = 100;
            operatorBox.Height = 100;
            // 转换为PictureBox内部坐标,确保图像添加到点击位置
            Point clientPoint = Strats.PointToClient(MousePosition);
            operatorBox.Location = new Point(clientPoint.X - 50, clientPoint.Y - 50);
            operatorBox.SizeMode = PictureBoxSizeMode.Zoom;

            // 创建叠加图像对象并加入集合
            string operatorName = OperatorComboBox.SelectedItem.ToString();
            OverlayImage overlay = new OverlayImage
            {
                Name = operatorName,
                PictureBox = operatorBox
            };

            _overlayImages.Add(overlay);
            Strats.Controls.Add(operatorBox);
            ObjectListView.Items.Add(operatorName);
        }

        private void OperatorComboBox_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (OperatorComboBox.SelectedItem == null) return;

            string selectedOperator = OperatorComboBox.SelectedItem.ToString();
            // 使用switch表达式简化大量if-else逻辑
            file = selectedOperator switch
            {
                "Ace" => new Bitmap(Properties.Resources.ace),
                "Alibi" => new Bitmap(Properties.Resources.alibi),
                "Amaru" => new Bitmap(Properties.Resources.amaru),
                "Aruni" => new Bitmap(Properties.Resources.aruni),
                "Ash" => new Bitmap(Properties.Resources.ash),
                "Azami" => new Bitmap(Properties.Resources.azami),
                "Bandit" => new Bitmap(Properties.Resources.bandit),
                "Blackbeard" => new Bitmap(Properties.Resources.blackbeard),
                "Blitz" => new Bitmap(Properties.Resources.blitz),
                "Buck" => new Bitmap(Properties.Resources.buck),
                "Capitao" => new Bitmap(Properties.Resources.capitao),
                "Castle" => new Bitmap(Properties.Resources.castle),
                "Caveira" => new Bitmap(Properties.Resources.caveira),
                "Clash" => new Bitmap(Properties.Resources.clash),
                "Doc" => new Bitmap(Properties.Resources.doc),
                "Dokkaebi" => new Bitmap(Properties.Resources.dokkaebi),
                "Echo" => new Bitmap(Properties.Resources.echo),
                "Ela" => new Bitmap(Properties.Resources.ela),
                "Finka" => new Bitmap(Properties.Resources.finka),
                "Flores" => new Bitmap(Properties.Resources.flores),
                "Frost" => new Bitmap(Properties.Resources.frost),
                "Fuze" => new Bitmap(Properties.Resources.fuze),
                "Glaz" => new Bitmap(Properties.Resources.glaz),
                "Goyo" => new Bitmap(Properties.Resources.goyo),
                "Gridlock" => new Bitmap(Properties.Resources.gridlock),
                "Grim" => new Bitmap(Properties.Resources.grim),
                "Hibana" => new Bitmap(Properties.Resources.hibana),
                "Iana" => new Bitmap(Properties.Resources.iana),
                "IQ" => new Bitmap(Properties.Resources.iq),
                "Jackal" => new Bitmap(Properties.Resources.jackal),
                "Jager" => new Bitmap(Properties.Resources.jager),
                "Kaid" => new Bitmap(Properties.Resources.kaid),
                "Kali" => new Bitmap(Properties.Resources.kali),
                "Kapkan" => new Bitmap(Properties.Resources.kapkan),
                "Lesion" => new Bitmap(Properties.Resources.lesion),
                "Lion" => new Bitmap(Properties.Resources.lion),
                "Maestro" => new Bitmap(Properties.Resources.maestro),
                "Maverick" => new Bitmap(Properties.Resources.maverick),
                "Melusi" => new Bitmap(Properties.Resources.melusi),
                "Mira" => new Bitmap(Properties.Resources.mira),
                "Montagne" => new Bitmap(Properties.Resources.montagne),
                "Mozzie" => new Bitmap(Properties.Resources.mozzie),
                "Mute" => new Bitmap(Properties.Resources.mute),
                "Nokk" => new Bitmap(Properties.Resources.nokk),
                "Nomad" => new Bitmap(Properties.Resources.nomad),
                "Oryx" => new Bitmap(Properties.Resources.oryx),
                "Osa" => new Bitmap(Properties.Resources.osa),
                "Pulse" => new Bitmap(Properties.Resources.pulse),
                "Rook" => new Bitmap(Properties.Resources.rook),
                "Sens" => new Bitmap(Properties.Resources.sens),
                "Sledge" => new Bitmap(Properties.Resources.sledge),
                "Smoke" => new Bitmap(Properties.Resources.smoke),
                "Solis" => new Bitmap(Properties.Resources.solis),
                "Tachanka" => new Bitmap(Properties.Resources.tachanka),
                "Thatcher" => new Bitmap(Properties.Resources.thatcher),
                "Thermite" => new Bitmap(Properties.Resources.thermite),
                "Thorn" => new Bitmap(Properties.Resources.thorn),
                "Thunderbird" => new Bitmap(Properties.Resources.thunderbird),
                "Twitch" => new Bitmap(Properties.Resources.twitch),
                "Valkyrie" => new Bitmap(Properties.Resources.valkyrie),
                "Vigil" => new Bitmap(Properties.Resources.vigil),
                "Wamai" => new Bitmap(Properties.Resources.wamai),
                "Warden" => new Bitmap(Properties.Resources.warden),
                "Ying" => new Bitmap(Properties.Resources.ying),
                "Zero" => new Bitmap(Properties.Resources.zero),
                "Zofia" => new Bitmap(Properties.Resources.zofia),
                _ => file
            };
        }

        private void textBox1_TextChanged(object sender, EventArgs e)
        {
            // 暂不处理
        }

        private void MapComboBox_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (MapComboBox.SelectedItem == null) return;

            string selectedMap = MapComboBox.SelectedItem.ToString();
            Mapfile = selectedMap switch
            {
                "Oragan Basement" => new Bitmap(Properties.Resources.OraganBasement),
                "Oragan Kids" => new Bitmap(Properties.Resources.OraganKids),
                _ => Mapfile
            };
            Strats.Image = Mapfile;
        }

        private void SaveBtn_Click(object sender, EventArgs e)
        {
            // 可在此实现保存逻辑:将背景图与所有叠加图像合并后保存
        }

        private void ClearPageBtn_Click(object sender, EventArgs e)
        {
            // 清空所有叠加图像并释放资源
            foreach (var overlay in _overlayImages)
            {
                Strats.Controls.Remove(overlay.PictureBox);
                overlay.PictureBox.Image.Dispose();
                overlay.PictureBox.Dispose();
            }
            _overlayImages.Clear();
            ObjectListView.Items.Clear();
        }

        private void DeleteBtn_Click(object sender, EventArgs e)
        {
            if (ObjectListView.SelectedItems.Count == 0) return;

            string selectedName = ObjectListView.SelectedItems[0].Text;
            // 根据列表项名称找到对应的叠加图像
            OverlayImage targetOverlay = _overlayImages.FirstOrDefault(o => o.Name == selectedName);
            if (targetOverlay != null)
            {
                // 从控件移除并释放资源
                Strats.Controls.Remove(targetOverlay.PictureBox);
                targetOverlay.PictureBox.Image.Dispose();
                targetOverlay.PictureBox.Dispose();
                // 从集合与列表中移除
                _overlayImages.Remove(targetOverlay);
                ObjectListView.Items.Remove(ObjectListView.SelectedItems[0]);
            }
        }

        private void DisplayImage()
        {

        }

        private void Strats_Paint(object sender, PaintEventArgs e)
        {

        }
    }
}

关键改进点

  • 集合追踪:使用List<OverlayImage>存储所有叠加图像,确保每个图像对象可被精准定位
  • 资源管理:创建Bitmap独立实例并在删除时调用Dispose(),避免资源锁定与内存泄漏
  • 坐标修正:将屏幕坐标转换为Strats内部坐标,确保图像添加到点击的正确位置
  • 代码简化:用switch表达式替代大量if-else,提升代码可读性与维护性

内容的提问来源于stack exchange,提问作者Cory G

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.03 14:20:40