I’m very excited to be joining Brian as a co-author on this blog. It’s my first blogging experience and I’m eager to start writing about the many and varied things we’re doing with Inventor’s API!. To start out I thought it would be interesting to discuss a different way to create IPictureDisp needed for button images.
Having to reference Microsoft.VisualBasic.Compatibility and use Microsoft.VisualBasic.Compatibility.VB6.Support.IconToIPicture() to create an IPictureDisp works, but I always thought there should be a better way to create the image for the user interface. Also in a future release of Inventor there is a good chance that it will support .NET framework 4 and warning messages occur using IconToPicture(). (Inventor 2012 uses .NET 3.5).
I was happy to find a utility class that my colleague Philippe Leefsma recently created that uses stdole.IPictureDisp instead of IconToPicture().
This zip file has a project that creates an AddIn that adds a panel to the assemble tab on the assembly ribbon and a panel to the model tab on the part ribbon. This project is a completed lab used in one of the Inventor API trainings. (Originally using IconToIPicture).
Here is the class from the project that creates the IPicutreDisp. (See below for some instructions on how to use this class).
Imports System.Runtime.InteropServices
Public NotInheritable Class PictureDispConverter
<DllImport("OleAut32.dll", EntryPoint:= _
"OleCreatePictureIndirect", ExactSpelling:=True, _
PreserveSig:=False)> _
Private Shared Function OleCreatePictureIndirect( _
<MarshalAs(UnmanagedType.AsAny)> _
ByVal picdesc As Object, _
ByRef iid As Guid, _
<MarshalAs(UnmanagedType.Bool)> _
ByVal fOwn As Boolean) _
As stdole.IPictureDisp
End Function
Shared iPictureDispGuid As Guid = _
GetType(stdole.IPictureDisp).GUID
Private NotInheritable Class PICTDESC
Private Sub New()
End Sub
'Picture Types
Public Const PICTYPE_UNINITIALIZED As Short = -1
Public Const PICTYPE_NONE As Short = 0
Public Const PICTYPE_BITMAP As Short = 1
Public Const PICTYPE_METAFILE As Short = 2
Public Const PICTYPE_ICON As Short = 3
Public Const PICTYPE_ENHMETAFILE As Short = 4
<StructLayout(LayoutKind.Sequential)> _
Public Class Icon
Friend cbSizeOfStruct As Integer = _
Marshal.SizeOf(GetType(PICTDESC.Icon))
Friend picType As Integer = _
PICTDESC.PICTYPE_ICON
Friend hicon As IntPtr = IntPtr.Zero
Friend unused1 As Integer
Friend unused2 As Integer
Friend Sub New(ByVal icon As _
System.Drawing.Icon)
Me.hicon = icon.ToBitmap().GetHicon()
End Sub
End Class
<StructLayout(LayoutKind.Sequential)> _
Public Class Bitmap
Friend cbSizeOfStruct As Integer = _
Marshal.SizeOf(GetType(PICTDESC.Bitmap))
Friend picType As Integer = _
PICTDESC.PICTYPE_BITMAP
Friend hbitmap As IntPtr = IntPtr.Zero
Friend hpal As IntPtr = IntPtr.Zero
Friend unused As Integer
Friend Sub New(ByVal bitmap As _
System.Drawing.Bitmap)
Me.hbitmap = bitmap.GetHbitmap()
End Sub
End Class
End Class
Public Shared Function ToIPictureDisp(ByVal icon As _
System.Drawing.Icon) As stdole.IPictureDisp
Dim pictIcon As New PICTDESC.Icon(icon)
Return OleCreatePictureIndirect(pictIcon, _
iPictureDispGuid, True)
End Function
Public Shared Function ToIPictureDisp(ByVal bmp _
As System.Drawing.Bitmap) As stdole.IPictureDisp
Dim pictBmp As New PICTDESC.Bitmap(bmp)
Return OleCreatePictureIndirect(pictBmp, _
iPictureDispGuid, True)
End Function
End Class
How to use the PictureDispConverter class.
1. Add a reference to stdole (On the .NET tab of the Add Reference dialog)
2. In your project add a new class and copy the code above into the class.
3. Create a resource in the project.
4. Call PictureDispConverter.ToIPictureDisp() and pass in the resource. Here is the code from the attached project that does this.
Dim mIPictureDisp1 As IPictureDisp = _
PictureDispConverter.ToIPictureDisp _
(My.Resources.Tools)
Dim mIPictureDisp2 As IPictureDisp = _
PictureDispConverter.ToIPictureDisp _
(My.Resources.wbTest)
Wayne Brill