Changing icon on AddIn Button

3915
5
Jump to solution
11-11-2015 05:39 PM
BerndtNording
Occasional Contributor

I have a bit of code that toggles the icon of an Addin button:

isChecked = Not isChecked
Dim pUID As New UIDClass
pUID.Value = My.ThisAddIn.IDs.FloorCBX
Dim pCI As ICommandItem
Dim bm As Bitmap
pCI = My.ArcMap.Application.Document.CommandBars.Find(pUID, True, True)

If isChecked Then
  bm = New Bitmap("E:\customnet\spacedemo\Images\FloorCBX2.png")
Else
  bm = New Bitmap("E:\customnet\spacedemo\Images\FloorCBX.png")
End If
'Dim bm As New Bitmap("E:\customnet\spacedemo\Images\FloorCBX2.png")
pCI.FaceID = ESRI.ArcGIS.ADF.COMSupport.OLE.GetIPictureDispFromBitmap(bm)

While this works on my development machine, it obviously won't elsewhere due to the hard-coded image file paths. I have seen in the "Build Action" of the image that I can set it to "AddInContent", but I have not found any info on how to reference that embedded bitmap in my code. So, how do I modify my code to get the bitmap from the Addin's content instead of a file?

0 Kudos
1 Solution

Accepted Solutions
DuncanHornby
MVP Notable Contributor

OK here is a bit of a fudge and slightly different code. I have 2 images in my image folder button1.png which is AddInContent and no copy and is the icon the button starts with so config file is happy. I have button2.png which is set to Content and copy always.

The onclick of button changes the icon.

Dim path As String
Dim codeBase As String = System.Reflection.Assembly.GetExecutingAssembly().Location
Dim uriBuilder As New UriBuilder(codeBase)
Dim assemblyPath As String = Uri.UnescapeDataString(uriBuilder.Path)
path = System.IO.Path.GetDirectoryName(assemblyPath) & "\Images\Button2.png"
MsgBox(path, MsgBoxStyle.OkOnly, "hello")
Dim pUID As New UIDClass
pUID.Value = My.ThisAddIn.IDs.Button1
Dim pCI As ICommandItem
Dim bm As Bitmap
pCI = My.ArcMap.Application.Document.CommandBars.Find(pUID, True, True)
bm = New Bitmap(path)
pCI.FaceID = ESRI.ArcGIS.ADF.COMSupport.OLE.GetIPictureDispFromBitmap(bm)
pCI.Refresh()

The message box returns a path

C:\Users\hornbydd\AppData\Local\ESRI\Desktop10.3\AssemblyCache\{41A95ECC-C462-4A9F-BCB9-1FB3F3B2DF04}\Images\Button2.png

As button2.png is now content that is set to always copy to output directory is now exists a separate file that I can build a path to.

I have to admit I was unable to find a way of drilling into the Addin itself and getting the Icon. If anyone else reading this knows how to get a handle on an AddIn Content image I would love to know how?

View solution in original post

0 Kudos
5 Replies
DuncanHornby
MVP Notable Contributor

How I deal with this is:

  1. In Visual Studio Solution Explorer I create a folder called Images and I add my icons there.
  2. The Build Action for the icons are set to AddInContent.
  3. In the Config.esriaddinx any buttons that have an icon have the property set to image="Images\xxx.bmp" where xxx.bmp is the name of the image file.
  4. Now to reference the image you need to get the location of the addin, the following code shows you how to get it

Dim path As String
Dim codeBase As String = System.Reflection.Assembly.GetExecutingAssembly().CodeBase
Dim uriBuilder As New UriBuilder(codeBase)
Dim assemblyPath As String = Uri.UnescapeDataString(uriBuilder.Path)
path = System.IO.Path.GetDirectoryName(assemblyPath) & "\Images\xxx.bmp"
BerndtNording
Occasional Contributor

Thank you for this suggestion, it almost works!

It seems that if Build Action is set to AddInContent, then the image(s) are NOT copied to the output directory regardless of what "Copy to output directory" is set to, and then the code throws an exception since it can't find the image file. It does however show the image specified in Config.esriaddinx, on the button automatically, therefore the image must be buried somewhere in there.

However, if Build Action is set to Content, then the images ARE copied to the output directory and the code does work, but the image specified in Config.esriaddinx does not appear on the button.

I can use the code to then make the button appear as sort of a workaround, but the question still stands: Is there a way to reference images that are buried somewhere in the AddIn via the AddInContent Build Action?

The addin itself can do it since there are no actual image files in the installed addIn's folder, but perhaps ESRI didn't see fit to provide that capability to the developer?

0 Kudos
DuncanHornby
MVP Notable Contributor

OK here is a bit of a fudge and slightly different code. I have 2 images in my image folder button1.png which is AddInContent and no copy and is the icon the button starts with so config file is happy. I have button2.png which is set to Content and copy always.

The onclick of button changes the icon.

Dim path As String
Dim codeBase As String = System.Reflection.Assembly.GetExecutingAssembly().Location
Dim uriBuilder As New UriBuilder(codeBase)
Dim assemblyPath As String = Uri.UnescapeDataString(uriBuilder.Path)
path = System.IO.Path.GetDirectoryName(assemblyPath) & "\Images\Button2.png"
MsgBox(path, MsgBoxStyle.OkOnly, "hello")
Dim pUID As New UIDClass
pUID.Value = My.ThisAddIn.IDs.Button1
Dim pCI As ICommandItem
Dim bm As Bitmap
pCI = My.ArcMap.Application.Document.CommandBars.Find(pUID, True, True)
bm = New Bitmap(path)
pCI.FaceID = ESRI.ArcGIS.ADF.COMSupport.OLE.GetIPictureDispFromBitmap(bm)
pCI.Refresh()

The message box returns a path

C:\Users\hornbydd\AppData\Local\ESRI\Desktop10.3\AssemblyCache\{41A95ECC-C462-4A9F-BCB9-1FB3F3B2DF04}\Images\Button2.png

As button2.png is now content that is set to always copy to output directory is now exists a separate file that I can build a path to.

I have to admit I was unable to find a way of drilling into the Addin itself and getting the Icon. If anyone else reading this knows how to get a handle on an AddIn Content image I would love to know how?

0 Kudos
BerndtNording
Occasional Contributor

Yes, that's a slight variation on the fudge of what I have now, but it still doesn't work. Since the button is a toggle, it's OK on startup when the addin gets the image from the Addin content, and its OK when switching to the second image, but if you then try to switch back to the original image it crashes because its trying to find the first image as a file.

I'll mark this as answered and just have to live with my dislike of fudge. The whole thing is a fudge anyways because it is a way to mimic a checkbox, which could be done the "old" way with a userform in a toolbar but isn't supported under Addins.

0 Kudos
DuncanHornby
MVP Notable Contributor

Ah well the fudge to fudge what is already fudged is to have a third button which is Contents only and is an exact copy of the button icon on startup. You then toggle between those and essentially abandon the icon that was the AddInContent. 

0 Kudos