winforms 为什么我的winform button.BackgroundImage值显示为System.Drawing.Bitmap?

qnzebej0  于 2023-10-23  发布在  其他
关注(0)|答案(2)|浏览(105)

我目前正在用c#创建扫雷游戏,使用winform按钮作为瓦片。我有一个鼠标事件,检查当鼠标右键向下(右键单击)应用'标志'的瓷砖。

private void Button_MouseDown(object sender, MouseEventArgs e)
{
    if (e.Button == MouseButtons.Right)
    {
        var tile = (Button)sender;
        tile.BackgroundImage = Image.FromFile(@"C:\Users\xxxxx\Documents\MyFiles\flag.png");
        Console.WriteLine("BackgroundImage: "+tile.BackgroundImage);
    }
}

当运行游戏时,我可以右键单击一个瓷砖,它将应用flag.png图像,但控制台消息“BackgroundImage:系统.绘图.位图”。计划是检查点击的瓷砖有什么背景图像,这样我就可以把它变成一个普通的瓷砖,如果我再次点击它,就像这样:

if tile.BackgroundImage == Image.FromFile(@"C:\Users\xxxxx\Documents\MyFiles\flag.png")
{
  tile.BackgroundImage = Image.FromFile(@"C:\Users\xxxxx\Documents\MyFiles\tile.png");
}

我尝试使用BackgroundImage.tag为按钮添加一个标识符,但似乎无法保存,因为它显示为空白。为什么按钮不保存BackgroundImage作为文件路径,而不是“System.Drawing.Bitmap”,有没有一种方法可以检查按下的按钮是否将该图像分配给其背景?

zd287kbt

zd287kbt1#

对于为什么我的winform button.BackgroundImage值显示为System.Drawing.Bitmap,一个可能的补救方法是确保图像可以被定位。从文件中加载图像时,您所做的似乎并没有那么离谱,但您可能希望通过一些建议来简化该过程:

确保文件被定位的一种直接方法是将它们标记为要复制到输出目录。

然后,您可以通过从应用程序在运行时已知的位置加载来创建字典(或ImageList)。

enum SelectedImage{ None, Flag, Bomb, }

Dictionary<SelectedImage, Image> Images = new Dictionary<SelectedImage, Image>
{
    {  SelectedImage.None, null },
    {  SelectedImage.Flag, Image.FromFile(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Images", "flag.png")) },
    {  SelectedImage.Bomb, Image.FromFile(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Images", "bomb.png")) },
};

继承按钮

如果您创建一个自定义按钮类,使其能够识别SelectedImage枚举,并且可以在该属性更改时触发事件,那么事情可能会变得更容易。

class MSButton : Button
{
    public SelectedImage SelectedImage
    {
        get => _selectedImage;
        set
        {
            if (!Equals(_selectedImage, value))
            {
                _selectedImage = value;
                SelectedImageChanged?.Invoke(this, EventArgs.Empty);
            }
        }
    }
    SelectedImage _selectedImage = 0;
    public event EventHandler SelectedImageChanged;

    // Cycle through the images
    protected override void OnClick(EventArgs e)
    {
        base.OnClick(e);
        SelectedImage = (SelectedImage)(((int)SelectedImage + 1) % 3);
    }
}

游戏板

现在,您可以使用TableLayoutPanel(具有您选择的尺寸)为游戏板使用自定义按钮类。

public MainForm()
{
    InitializeComponent();
    const float DIM = 40F;
    tableLayoutPanel.CellBorderStyle = TableLayoutPanelCellBorderStyle.Single;
    tableLayoutPanel.RowCount = 10;
    tableLayoutPanel.RowStyles.Clear();
    tableLayoutPanel.ColumnCount = 10;
    tableLayoutPanel.ColumnStyles.Clear();
    for (int col = 0; col < 10; col++)
    {
        tableLayoutPanel.ColumnStyles.Add(new ColumnStyle(SizeType.Absolute, DIM));
        for (int row = 0; row < 10; row++)
        {
            tableLayoutPanel.RowStyles.Add(new RowStyle(SizeType.Absolute, DIM));
            var button = new MSButton
            {
                Anchor = (AnchorStyles)0xF, // All
                BackgroundImageLayout = ImageLayout.Stretch,
            };
            button.SelectedImageChanged += (sender, e) =>
            {
                if(sender is MSButton msbutton)
                {
                    msbutton.BackgroundImage = Images[msbutton.SelectedImage];
                }
            };
            tableLayoutPanel.Controls.Add(button, col, row);
        }
    }
    // Size including 1 px borders.
    tableLayoutPanel.Width = (int)((DIM * 10) + 11);
    tableLayoutPanel.Height = (int)((DIM * 10) + 11);
}
jogvjijk

jogvjijk2#

为什么按钮不保存BackgroundImage作为文件路径,而不是“System.Drawing.Bitmap”
字符串连接只是为非字符串对象调用ToString()Bitmap没有被覆盖的ToString(),这就是为什么你只能在控制台中看到它的类型的全名。但它不能返回任何文件名,因为它是简单的不存储。一个位图可以创建没有任何文件,如。从存储器流或简单地通过指定大小和像素格式。
有没有一种方法可以检查按下的按钮是否将该图像分配到其背景?
实际上,有一种本机支持的方法可以为预定义的图像关联字符串名称:
1.创建一个ImageList(您可以在设计时完成,您可以在工具栏中找到ImageList)。不要忘记将位深度设置为24或32 bpp。
1.将图像添加到您的图像列表中。你可以在设计器中为每个图像设置Name。如果你用编程的方式来做,你可以这样做:imageList1.Images.Add("flag.png", Image.FromFile(@"C:\Users\xxxxx\Documents\MyFiles\flag.png"));
1.对于您的按钮,只需设置ImageList属性。你也可以在设计的时候做。
现在,在运行时,您可以设置ImageKey属性来设置图像。您也可以阅读此内容以确定当前显示的图像。

private void Button_MouseDown(object sender, MouseEventArgs e)
{
    if (e.Button == MouseButtons.Right)
    {
        var tile = (Button)sender;
        tile.ImageKey = "flag.png";
        Console.WriteLine("Current image: " + tile.ImageKey);
    }
}

这样做的另一个明显的好处是,你不需要一次又一次地从文件加载图像。

相关问题