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?
Solved! Go to Solution.
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?
How I deal with this is:
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"
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?
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?
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.
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.