Transparent Bitmap Background for VB (or Office) Addin Buttons and Menu Items


Environment: VB5/VB6

When a VB Addin tries to add a button to a VB commandbar or menu, it has no simple way to properly specify a transparent background for the button or menu item bitmap. Since we have to use the clipboard to transfer the image to the button, it can’t be an icon. This generally makes the button look very ugly, especially when the user has selected a fancy color scheme. Since built-in addins display their bitmapped buttons properly, I guessed that there should be a way… Here it is.

First add the following declarations to your General section in your addin:

private Type COLORMAP
    from as Long
    to as Long
End Type

private Type PICTDESC
    Size as Long
    Type as Long
    hBmp as Long
    hPal as Long
    Reserved as Long
End Type

private Type IID
    Data1 as Long
    Data2 as Integer
    Data3 as Integer
    Data4(7) as Byte
End Type

private Declare Function CreateMappedBitmap _
                    Lib "comctl32.dll" (byval hInstance as Long, _
                    byval idBitmap as Long, _
                    byval wFlags as Long, _
                    lpColorMap as COLORMAP, _
                    byval iNumMaps as Long) as Long

private Declare Function OleCreatePictureIndirect _
                    Lib "olepro32.dll" (desc as PICTDESC, _
                        RefIID as IID, _
                        byval fPictureOwnsHandle as Long, _
                        IPic as IPicture) as Long

private Declare Function GetSysColor Lib "user32" (byval nIndex as Long) as Long
Const COLOR_MENU = 4

Dim g_map as COLORMAP

This declares Win32 API and OLE functions that we’ll need later. Then add the following function to your addin:

Function BitmapToPicture(byval hBmp as Long, _
                         optional byval hPal as Long = 0) as IPicture

    ' Code adapted from HardCore Visual Basic articles in MSDN

    ' Fill picture description

    Dim IPic as IPicture, picdes as PICTDESC, iidIPicture as IID

    picdes.Size = len(picdes)
    picdes.Type = vbPicTypeBitmap
    picdes.hBmp = hBmp
    picdes.hPal = hPal

    ' Fill in magic IPicture GUID {7BF80980-BF32-101A-8BBB-00AA00300CAB}

    iidIPicture.Data1 = &H7BF80980
    iidIPicture.Data2 = &HBF32
    iidIPicture.Data3 = &H101A
    iidIPicture.Data4(0) = &H8B
    iidIPicture.Data4(1) = &HBB
    iidIPicture.Data4(2) = &H0
    iidIPicture.Data4(3) = &HAA
    iidIPicture.Data4(4) = &H0
    iidIPicture.Data4(5) = &H30
    iidIPicture.Data4(6) = &HC
    iidIPicture.Data4(7) = &HAB

    ' Create picture from bitmap handle

    OleCreatePictureIndirect picdes, iidIPicture, true, IPic
    set BitmapToPicture = IPic

End Function

Finally, when your addin is about to add the bitmap representing your command in the VB menu or CommandBar, use the following code (assuming that mcbMenuCommandBarCtrl is the target CommandBarControl that you just created).

g_map.from = RGB(192, 192, 192) = GetSysColor(COLOR_MENU)

Clipboard.SetData BitmapToPicture(CreateMappedBitmap(App.hInstance, _
                                  BMP_ID, 0, g_map, 1))

BMP_ID being the resource identifier of the bitmap.

A few explanations : CreateMappedBitmap is a Win32 API function creating a new bitmap from an existing bitmap resource by translating specified a specified color to another color. The "from" and "to" colors are specified in a COLORMAP structure. You can translate as many colors as you wish. Here, we merely translate the bitmap background color (in that case RGB(192, 192, 192)) to the background color of menus and commandbars (which we get from GetSysColor)

However, CreateMappedBitmap returns a bitmap handle which we can’t use as-is. BitmapToPicture is a handy function that is partially described and implemented in the MSDN. It creates an IPicture interface from the bitmap handle (a picture in VB actually points to an IPicture COM interface). So, you can assign the result of BitmapToPicture to a Picture object variable.

Once we have a "standard" VB picture, we can copy it to the clipboard and then paste it to the button face.

We use a global variable for the COLORMAP because we may have to re-use it if the CommandBarControl changes its state and therefore changes its bitmap.

That’s it. Your VB Addin buttons and menu items will now be displayed properly. The Downloads section points to a VB Addin using this technique (and also allowing to automatically restore the last project when launching VB).

Download Restore Addin Demo Project (27kb)

Download Other freeware utilities from MainSoft’s Web Site

More by Author

Must Read