none
External resources designer RRS feed

  • Question

  • Hello,

    I have a big application (more than 100 forms) and I would like to create a plug-in with all the picture I use.

    For example I have a button Articles in some forms (with one icon always the same) and I would like to allow the user to change this icon in all the project (in one  replace).

    I though I simply had to create an external project and the the user simply needs to replace the images then compile the DLL so my program can use it (I change the DLL and all the images are changed). This works very well, but if I change something in the designer of a form, then all the resources are copied into the form  and not read in the external resources so the user doesn't see the new icons and I have to change the images in all the form again.

    Of course I could put all the images in the form_load event but I wouldn't see the icons in the designer (and if I let the images in the resources and in the designer, I can forget one image).

    Is there a way to make it automatically?

    Thank you

    Marc

    Tuesday, February 27, 2018 6:49 AM

Answers

  • You could use an ImageList to specify the button image, then you can replace the image by key in the image list and update all buttons using that particular image list and image key.

    You could start with a "shared resources" class which contains a shared ImageList that is preloaded with keyed images:

    Public NotInheritable Class SharedResources
        Public Shared Property ButtonImages As New ImageList
    
        Shared Sub New()
            ButtonImages.ColorDepth = ColorDepth.Depth32Bit
            ButtonImages.ImageSize = New Size(32, 32)
    
            With ButtonImages.Images
                .Add("Image1", My.Resources.Dragon_Egg_A)
                .Add("Image2", My.Resources.Dragon_Egg_B)
                .Add("Image3", My.Resources.Dragon_Egg_C)
            End With
        End Sub
        Protected Sub New()
        End Sub
    End Class

    Then you could create a derived button class that uses this shared ImageList:

    Public Class DynamicImageButton
        Inherits Button
    
        Public Sub New()
            ImageAlign = ContentAlignment.MiddleLeft
            TextAlign = ContentAlignment.MiddleRight
            ImageList = SharedResources.ButtonImages
        End Sub
    End Class

    When you place an instance of DynamicImageButton on a form you can then use the ImageKey dropdown to select the desired image at design time.

    Then you can use code to replace the image with the given key with a different image.  This code could be executed by the user, allowing them to select an image.  After changing the image with the given key you can refresh the form to see the new button image.

    Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
        Using dlg As New OpenFileDialog
            dlg.Filter = "Image Files|*.bmp;*.jpg;*.png"
            If dlg.ShowDialog = DialogResult.OK Then
                SharedResources.ButtonImages.Images.RemoveByKey("Image1")
                SharedResources.ButtonImages.Images.Add("Image1", Bitmap.FromFile(dlg.FileName))
                Me.Refresh()
            End If
        End Using
    End Sub

    This way there doesn't need to be a separate DLL and the user does not have to compile anything.


    Reed Kimble - "When you do things right, people won't be sure you've done anything at all"

    • Marked as answer by Marc_Allard Wednesday, February 28, 2018 7:15 AM
    Tuesday, February 27, 2018 3:40 PM
    Moderator
  • There's no good way to set the ImageList property for the button control to a "global" or "shared" ImageList that I can see, so I used the custom control as a way to set the ImageList.  Instead, you could execute a loop when the form loads that iterates over all controls and sets the ImageList property for you.  However, then you would not see the images on the buttons at design time.  The concept only works with controls that can use an ImageList for their images so it would not work for the Form Icon.  But then again, your original question doesn't have anything to do with the form icon, that would be totally separate from images in a control (you won't have more than one of the same form so there aren't multiple copies to change like there would be with a button).

    I can't think of reasonable way to implement your idea so I can only suggest this alternative which would have a similar result.  There are all kinds of things you could probably do to get the runtime support you want, but I don't know how you'd also implement it at design time - without creating custom controls for everything just like you'd have to do with my suggestion.  Any solution which can work with the existing controls will almost have to execute at runtime so that it can iterate over the controls and change their images.


    Reed Kimble - "When you do things right, people won't be sure you've done anything at all"

    • Marked as answer by Marc_Allard Wednesday, February 28, 2018 7:15 AM
    Tuesday, February 27, 2018 6:36 PM
    Moderator

All replies

  • You could use an ImageList to specify the button image, then you can replace the image by key in the image list and update all buttons using that particular image list and image key.

    You could start with a "shared resources" class which contains a shared ImageList that is preloaded with keyed images:

    Public NotInheritable Class SharedResources
        Public Shared Property ButtonImages As New ImageList
    
        Shared Sub New()
            ButtonImages.ColorDepth = ColorDepth.Depth32Bit
            ButtonImages.ImageSize = New Size(32, 32)
    
            With ButtonImages.Images
                .Add("Image1", My.Resources.Dragon_Egg_A)
                .Add("Image2", My.Resources.Dragon_Egg_B)
                .Add("Image3", My.Resources.Dragon_Egg_C)
            End With
        End Sub
        Protected Sub New()
        End Sub
    End Class

    Then you could create a derived button class that uses this shared ImageList:

    Public Class DynamicImageButton
        Inherits Button
    
        Public Sub New()
            ImageAlign = ContentAlignment.MiddleLeft
            TextAlign = ContentAlignment.MiddleRight
            ImageList = SharedResources.ButtonImages
        End Sub
    End Class

    When you place an instance of DynamicImageButton on a form you can then use the ImageKey dropdown to select the desired image at design time.

    Then you can use code to replace the image with the given key with a different image.  This code could be executed by the user, allowing them to select an image.  After changing the image with the given key you can refresh the form to see the new button image.

    Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
        Using dlg As New OpenFileDialog
            dlg.Filter = "Image Files|*.bmp;*.jpg;*.png"
            If dlg.ShowDialog = DialogResult.OK Then
                SharedResources.ButtonImages.Images.RemoveByKey("Image1")
                SharedResources.ButtonImages.Images.Add("Image1", Bitmap.FromFile(dlg.FileName))
                Me.Refresh()
            End If
        End Using
    End Sub

    This way there doesn't need to be a separate DLL and the user does not have to compile anything.


    Reed Kimble - "When you do things right, people won't be sure you've done anything at all"

    • Marked as answer by Marc_Allard Wednesday, February 28, 2018 7:15 AM
    Tuesday, February 27, 2018 3:40 PM
    Moderator
  • Hello,

    Thank you for the help but,

    The idea is interesting, but

    My idea was

    User chooses a DLL (with all the pictures inside it) and all the buttons everywhere are changed. The only thing that is in the DLL are the resources. (for example you put all the pictures in a directory and I create a compilation thread or something like that).

    With what you suggest, I must create a new button control with the picture, a new toolstrip button, a new tooolstrip menu, a new form for the icon...).

    All the pictures will still be delivered with the application  and replaced later (even if I save what the user replaces for all the pictures, the user will need do copy all the pictures in a directory and if one is missing all the icons won't be replaced).

    Also, like that I won't see the picture of the button in the code. I need  to put all the resources manually inside the imagelist (with the designer) and after I can replace the pictures one by one.

    Marc

    Tuesday, February 27, 2018 6:05 PM
  • There's no good way to set the ImageList property for the button control to a "global" or "shared" ImageList that I can see, so I used the custom control as a way to set the ImageList.  Instead, you could execute a loop when the form loads that iterates over all controls and sets the ImageList property for you.  However, then you would not see the images on the buttons at design time.  The concept only works with controls that can use an ImageList for their images so it would not work for the Form Icon.  But then again, your original question doesn't have anything to do with the form icon, that would be totally separate from images in a control (you won't have more than one of the same form so there aren't multiple copies to change like there would be with a button).

    I can't think of reasonable way to implement your idea so I can only suggest this alternative which would have a similar result.  There are all kinds of things you could probably do to get the runtime support you want, but I don't know how you'd also implement it at design time - without creating custom controls for everything just like you'd have to do with my suggestion.  Any solution which can work with the existing controls will almost have to execute at runtime so that it can iterate over the controls and change their images.


    Reed Kimble - "When you do things right, people won't be sure you've done anything at all"

    • Marked as answer by Marc_Allard Wednesday, February 28, 2018 7:15 AM
    Tuesday, February 27, 2018 6:36 PM
    Moderator
  • Thank you for the help.

    MArc

    Wednesday, February 28, 2018 7:15 AM