C# 改进我的问题,这是目前为止最好的答案,但不是我的确切意思。我能想到的一种可能性是将PictureBox子类化,修改消息处理程序以允许点击,然后使用子类显示“真实”图像。请稍等(一两分钟),你能重新检查一下主柱吗?我认为这解释得更好。@mjw comment

C# 改进我的问题,这是目前为止最好的答案,但不是我的确切意思。我能想到的一种可能性是将PictureBox子类化,修改消息处理程序以允许点击,然后使用子类显示“真实”图像。请稍等(一两分钟),你能重新检查一下主柱吗?我认为这解释得更好。@mjw comment,c#,winforms,controls,transparency,region,C#,Winforms,Controls,Transparency,Region,改进我的问题,这是目前为止最好的答案,但不是我的确切意思。我能想到的一种可能性是将PictureBox子类化,修改消息处理程序以允许点击,然后使用子类显示“真实”图像。请稍等(一两分钟),你能重新检查一下主柱吗?我认为这解释得更好。@mjw comment中的链接解释了如何使用WinForms执行此操作-您需要使用GraphicsPath修改关联控件的Region属性,以便在2中绘制可以为该控件注册单击的位置。如果我需要改变它的一部分,我应该重新修补图像,对吗?没错。这是一个快速的操作,所以不要


改进我的问题,这是目前为止最好的答案,但不是我的确切意思。我能想到的一种可能性是将
PictureBox
子类化,修改消息处理程序以允许点击,然后使用子类显示“真实”图像。请稍等(一两分钟),你能重新检查一下主柱吗?我认为这解释得更好。@mjw comment中的链接解释了如何使用WinForms执行此操作-您需要使用
GraphicsPath
修改关联控件的
Region
属性,以便在2中绘制可以为该控件注册单击的位置。如果我需要改变它的一部分,我应该重新修补图像,对吗?没错。这是一个快速的操作,所以不要担心!您需要维护带有搜索点的搜索列表,并且应注意只保留每个图像的一个副本。.列表>图像>是否是存储图像的好选择,而不是ImageList?在程序运行时存储?是的,所有图像都是独立的。它们不会编译成exe,但这可能不是您想要的。
public partial class Form1 : Form {
    readonly Color mask = Color.Black;
    public Form1() {
        InitializeComponent();
    }

    private void pictureBox1_Click(object sender, EventArgs e) {
        var me = e as MouseEventArgs;
        using (var bmp = new Bitmap(pictureBox1.Image)) {
            if (me.X < pictureBox1.Image.Width && me.Y < pictureBox1.Image.Height) {
                var colorAtMouse = bmp.GetPixel(me.X, me.Y);
                if (colorAtMouse.ToArgb() == mask.ToArgb()) {
                    MessageBox.Show("Mask clicked!");
                }
            }
        }
    }
}
List<Point> points = new List<Point>();
points.Add(new Point(50,50));points.Add(new Point(60,65));points.Add(new Point(40,70));
points.Add(new Point(50,90));points.Add(new Point(30,95));points.Add(new Point(20,60));
points.Add(new Point(40,55));

using (GraphicsPath gp = new GraphicsPath())
{
    gp.AddClosedCurve(points.ToArray());
    panel1.Region = new Region(gp);
}
List<Tuple<Image, Point>> imgList = new List<Tuple<Image, Point>>();
private void pictureBox1_MouseClick(object sender, MouseEventArgs e)
{
    int found = -1;
    // I search backward because I drew forward:
    for (int i = imageList1.Images.Count - 1; i >= 0; i--)
    {
        Bitmap bmp = (Bitmap) imgList[i].Item1;
        Point  pt = (Point) imgList[i].Item2;
        Point pc = new Point(e.X - pt.X, e.Y - pt.Y);
        Rectangle bmpRect = new Rectangle(pt.X, pt.Y, bmp.Width, bmp.Height);
        // I give a little slack (11) but you could also check for > 0!
        if (bmpRect.Contains(e.Location) && bmp.GetPixel(pc.X, pc.Y).A > 11)
           { found = i; break; }
    }

    // do what you want with the found image..
    // I show the image in a 2nd picBox and its name in the form text:
    if (found >= 0) { 
        pictureBox2.Image = imageList1.Images[found];
        Text = imageList1.Images.Keys[found];
    }

}
Bitmap patchImages()
{
    Bitmap bmp = new Bitmap(pictureBox1.ClientSize.Width, pictureBox1.ClientSize.Height);
    imgList.Clear();
    Random R = new Random(1);

    using (Graphics G = Graphics.FromImage(bmp) )
    {
        foreach (Image img in imageList1.Images)
        {
            // for testing: put each at a random spot
            Point pt = new Point(R.Next(333), R.Next(222));
            G.DrawImage(img, pt);
            // also add to the searchable list:
            imgList.Add(new Tuple<Image, Point>(img, pt));
        }
    }
    return bmp;
}
private void Form1_Load(object sender, EventArgs e)
{
    pictureBox1.Image = patchImages();
}