Thanks to the previous comment I was able to understand how to use an image mask. I adapted the code to VB.NET and modified it to create a gray scale mask instead of just a black and white mask.
Public Class IPictureDisp
Inherits System.Windows.Forms.AxHost
Public Sub New()
MyBase.New("59EE46BA-677D-4d20-BF10-8D8067CB8B32")
End Sub
Public Shared Function FromImage(ByVal pImg As System.Drawing.Image) As stdole.IPictureDisp
Dim b As New Bitmap(16, 16)
Dim g As Graphics = Graphics.FromImage(b)
' fill the bitmap with white
g.FillRectangle(Brushes.White, 0, 0, 16, 16)
' draw the image over the white bitmap
g.DrawImage(pImg, 0, 0, 16, 16)
' return the opaque image
Return GetIPictureFromPicture(b)
End Function
Public Shared Function MaskFromImage(ByVal pImg As System.Drawing.Image) As stdole.IPictureDisp
Dim b As New Bitmap(16, 16)
Dim g As Graphics = Graphics.FromImage(b)
' draw the image over the transparent bitmap
g.DrawImage(pImg, 0, 0, 16, 16)
' convert pixels to grayscale
For x As Integer = 0 To 15
For y As Integer = 0 To 15
' get the pixel alpha
Dim pa As Integer
pa = b.GetPixel(x, y).A
' get the grayscale alpha equivalent of the pixel alpha
Dim pg As Integer
pg = 255 - pa
' replace the current pixel with a grayscale equivalent
b.SetPixel(x, y, Color.FromArgb(pg, pg, pg))
Next
Next
' return the picture
Return GetIPictureFromPicture(b)
End Function
End Class
To use the code, just do something like:
button.Picture = IPictureDisp.FromImage(my.resources.icon1)
button.Mask = IPictureDisp.MaskFromImage(my.resources.icon1)