【问题标题】:How do I get the name of an image resource in a PictureBox?如何获取 PictureBox 中图像资源的名称?
【发布时间】:2021-11-22 23:22:34
【问题描述】:

我正在开发一款游戏,它有一个放置系统,它几乎完成了,我正在尝试使用 My.Settings 制作一个保存系统,这是我到目前为止的代码

Private Sub Menu_Save_Click(sender As Object, e As EventArgs) Handles Menu_Save.Click
    Dg_1 = MessageBox.Show("Are you sure you want to save? This will overwrite your previous save.", "Warning!", MessageBoxButtons.YesNo)
    If (Dg_1) = DialogResult.Yes Then
        If (Generated = 0) Then
            Tb_Chat.Text += Environment.NewLine
            Tb_Chat.Text += "Cannot save a blank world"
        ElseIf Generated = 1 Then
            My.Settings.savslot1_isused = True
            My.Settings.savslot1_hearts = Hp
            My.Settings.savslot1_hunger = Hunger
            My.Settings.stg_slot01 = Pb_BlockSpace001.Image
            My.Settings.stg_slot02 = Pb_BlockSpace002.Image
            My.Settings.stg_slot03 = Pb_BlockSpace003.Image
            My.Settings.stg_slot04 = Pb_BlockSpace004.Image
            My.Settings.stg_slot05 = Pb_BlockSpace005.Image
            Tb_Chat.Text += Environment.NewLine
            Tb_Chat.Text += "World Saved. " + TimeOfDay + "."
        Else
            Exit Sub
        End If
    End If
End Sub

(我只保存了5个块来测试它)

然后它会出现一个错误说:

“图像”类型的值无法转换为“字符串”

我怎样才能让它获取资源的名称,而不是尝试将图像转换为字符串???

【问题讨论】:

  • 我很确定,当您执行类似...string ImagePath = @"D:\mypath\someimage.jpg"; ...Image img = Image.FromFile(ImagePath); ... 那么... ImageImagePath 不会保留在Image 对象本身中。除非您以某种方式保留它,否则该路径将丢失。猜测是可能将ImagePath 保存到img.Tag 属性中。但是,我猜Tag 可能会被清除,然后您将不得不以其他方式维护此“图像到字符串路径”。我猜这就是你要问的。
  • 你提到了image resource,这意味着图片是存储在项目资源中还是从磁盘加载图片?
  • 它位于 My.Resources
  • 我想要它做的是从 My.Resources 获取资源的名称(它保存图片框图像的资源名称)
  • 图像的保存位置无关紧要。图像加载到Image 对象后,图像的“路径”会丢失。正如我之前评论的那样……您“可以”将路径保存在 Image.Tag 属性或其他方式中……重点是……“您的代码”将不得不以某种方式“保存”此图像路径信息。 Image 对象本身不会知道它来自“哪里”……也不应该知道。

标签: vb.net visual-studio winforms


【解决方案1】:

由于位图图像位于 My.Resources 中,请考虑以下内容。

首先如上所述,您可以在 PictureBox 的 Tag 属性中设置图像名称并在需要时检索它,或者使用带有属性的自定义 PictureBox(如果需要,更改名称)ResourceName 将存储资源名字。

Public Class ImageBox
    Inherits PictureBox
    ''' <summary>
    ''' Name of resource in projects Resources
    ''' </summary>
    ''' <returns></returns>
    Public Property ResourceName() As String
    
End Class

创建ImageResourceHelper.vb并添加以下内容

Namespace My
    <ComponentModel.EditorBrowsable(ComponentModel.EditorBrowsableState.Never)>
    Partial Friend Class _MyImages

        Private ReadOnly MyProperties As Reflection.PropertyInfo()
        Private ReadOnly MyBitmapNames As List(Of String)
        Public BitMapImages As new Dictionary(Of String, Bitmap)

        Public ReadOnly Property HasImages() As Boolean
        get
            Return BitMapImages.Count >0
        End Get
        End Property

        Private Sub GetBitMapImages()

            'BitMapImages = New Dictionary(Of String, Bitmap)

            Dim propertyInfo As Reflection.PropertyInfo() =
                GetType(Resources.Resources).GetProperties(Reflection.BindingFlags.NonPublic Or
                                                              Reflection.BindingFlags.Instance Or
                                                              Reflection.BindingFlags.Static)

            Dim BitMaps = (From T In propertyInfo Where T.PropertyType Is GetType(Bitmap)).ToList

            If BitMaps.Count > 0 Then
                For Each pInfo As Reflection.PropertyInfo In BitMaps

                    BitMapImages.Add(
                        pInfo.Name.Replace("_", " "),
                        CType(Resources.ResourceManager.GetObject(pInfo.Name), Bitmap)
                    )

                Next
            End If

        End Sub
        Public Function BitmapFromResource(sender As String) As Bitmap

            Dim Item = (
                    From propertyInfo In MyProperties
                    Where propertyInfo.PropertyType Is GetType(Bitmap) AndAlso propertyInfo.Name = sender
                    ).FirstOrDefault

            If Item IsNot Nothing Then
                Return CType(Resources.ResourceManager.GetObject(Item.Name), Bitmap)
            Else
                Dim bm As New Bitmap(256, 256)
                Dim gr As Graphics = Graphics.FromImage(bm)
                gr.Clear(Color.Transparent)

                Return bm

            End If

        End Function
        Public ReadOnly Property BitmapNames As List(Of String)
            Get
                Return MyBitmapNames
            End Get
        End Property
        Public Sub New()

            MyProperties = GetType(Resources.Resources).
                GetProperties(
                    Reflection.BindingFlags.NonPublic Or
                    Reflection.BindingFlags.Instance Or
                    Reflection.BindingFlags.Static)

            MyBitmapNames = (
                From propertyInfo In MyProperties
                Where propertyInfo.PropertyType Is GetType(Bitmap)
                Select propertyInfo.Name
                ).ToList

            GetBitMapImages()

        End Sub
    End Class
    <HideModuleName()>
    Friend Module Resource_Images
        Private ReadOnly instance As New ThreadSafeObjectProvider(Of _MyImages)
        ReadOnly Property Images() As _MyImages
            Get
                Return instance.GetInstance()
            End Get
        End Property
    End Module
End Namespace

表单设计器

  • 添加一个按钮来设置图像(也可以在 ListBox 的选择更改或 BindingSource 的位置更改事件时完成。
  • 添加另一个按钮以获取当前资源名称。
  • 添加列表框
  • 添加自定义图片框

我的设置

添加一个名为 SelectedImageName 的新设置作为字符串。

表单代码

以下代码加载带有资源名称的 ListBox,确定是否设置了 SelectedImageName,如果设置了 PictureBox 图像,则设置资源名称,如果未设置,则从资源中选择第一张图像。

表单关闭事件 如果通过检查 PictureBox ResourceName 属性设置图像,则设置 SelectedImageName,如果资源仍然存在,将在 Form Shown 事件中拾取。

Imports System.ComponentModel

Public Class Form1

    Private ReadOnly ImageBindingSource As New BindingSource

    Private Sub SetImageButton_Click(sender As Object, e As EventArgs) Handles SetImageButton.Click

        If ListBox1.SelectedItem Is Nothing Then
            Exit Sub
        End If

        Dim current = CType(ListBox1.SelectedItem, KeyValuePair(Of String, Bitmap))

        PictureBox1.Image = current.Value
        PictureBox1.ResourceName = current.Key

    End Sub
    Private Sub GetImageNameButton_Click(sender As Object, e As EventArgs) Handles GetImageNameButton.Click
        If Not String.IsNullOrWhiteSpace(PictureBox1.ResourceName) Then
            MessageBox.Show(PictureBox1.ResourceName)
        Else
            MessageBox.Show("Set an image and try again")
        End If
    End Sub
    Private Sub Form1_Shown(sender As Object, e As EventArgs) Handles Me.Shown

        ImageBindingSource.DataSource = My.Images.BitMapImages

        ListBox1.DataSource = ImageBindingSource
        ListBox1.DisplayMember = "Key"
        ListBox1.ValueMember = "Value"

        If My.Images.HasImages Then
            If Not String.IsNullOrWhiteSpace(My.Settings.SelectedImageName) Then
                If My.Images.BitMapImages.ContainsKey(My.Settings.SelectedImageName) Then
                    PictureBox1.Image = My.Images.BitMapImages(My.Settings.SelectedImageName)
                    PictureBox1.ResourceName = My.Settings.SelectedImageName
                    ListBox1.SelectedIndex = ListBox1.FindString(My.Settings.SelectedImageName)
                Else
                    PictureBox1.Image = My.Images.BitMapImages.First().Value
                    PictureBox1.ResourceName = My.Images.BitMapImages.First().Key
                End If
            End If
        End If

    End Sub

    Private Sub Form1_Closing(sender As Object, e As CancelEventArgs) Handles Me.Closing
        If Not String.IsNullOrWhiteSpace(PictureBox1.ResourceName) Then
            My.Settings.SelectedImageName = CType(ListBox1.SelectedItem, KeyValuePair(Of String, Bitmap)).Key
        End If
    End Sub
End Class

当然这是针对一个 PictureBox,对每个 PictureBox 重复。此外,如果一个或多个资源是图标,则需要相应地调整检索图像的代码。 BitmapFromResource 方法也可用于通过名称从资源中获取图像,如果找不到则返回空图像。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-05-08
    • 1970-01-01
    • 2015-01-30
    • 1970-01-01
    • 1970-01-01
    • 2015-10-09
    • 2011-03-03
    • 1970-01-01
    相关资源
    最近更新 更多