Images on Buttons disappear when XP/Vista themes are active

Amyuni's Development Team would like to share with fellow developers general information about Windows and Web development. These are issues encountered by Amyuni's team and were either solved or pending solution.
Post Reply
Devteam
Posts: 119
Joined: Fri Oct 14 2005
Location: Montreal
Contact:

Images on Buttons disappear when XP/Vista themes are active

Post by Devteam »

Problem description:
Applications that have support for Vista or XP User Interface themes might see some of their buttons with no bitmaps displayed on them. This problem seems to happen because of the new common controls DLL (version 6) that is used to create the new visual effects.

Applications or controls that need to display images on buttons typically use the BM_SETIMAGE windows message to specify whic icon or image to display, e.g.:
// create a button with the BS_ICON style in order to show an icon only with not text
// the button size is set to 10x10 pixels

hChild = CreateWindowEx(0, _T("BUTTON"), _T(""), BS_ICON | WS_CHILD | WS_VISIBLE, 0, 0, 10, 10, m_hWnd, (HMENU)IDC_CMD, hExeInst, 0);
// load the icon to be displayed on the button
// it is assumed here that the icon stored in the resources is also 10x10 pixels

m_hIcon = (HICON)LoadImage(hResInst, MAKEINTRESOURCE(IDI_ICON), IMAGE_ICON, 10, 10, 0);
// set the button' s icon to the one loaded from resources
::SendMessage(hChild , BM_SETIMAGE, IMAGE_ICON, (LPARAM) m_hIcon);

The main advantage of using an icon is that this format supports transparencies, and we need to have an image with a transparent background so that it displays nicely on a button with any color.

This method unfortunately fails to display the image as soon as the application starts using the new Vista button styles. No information is available to indicate that there is something wrong. At first, the problem seemed to be the unconventional 10x10 pixel size for the icons, but choosing a different size did not help.

Workaround:
The workaround we found after playing around with this problem for a while was to use a BITMAP instead of an ICON to draw the button. After converting all the icons to bitmaps and changing the code to load and draw bitmaps, the buttons started appearing on any system:
// create a button with the BS_BITMAP style in order to show a bitmap only with not text
// the button size is set to 10x10 pixels

hChild = CreateWindowEx(0, _T("BUTTON"), _T(""), BS_BITMAP | WS_CHILD | WS_VISIBLE, 0, 0, 10, 10, m_hWnd, (HMENU)IDC_CMD, hExeInst, 0);
// load the bitmap to be displayed on the button
// it is assumed here that the bitmap stored in the resources is also 10x10 pixels

m_hBmp = (HBITMAP)LoadImage(hResInst, MAKEINTRESOURCE(IDB_BITMAP), IMAGE_BITMAP, 10, 10, LR_LOADTRANSPARENT | LR_LOADMAP3DCOLORS);
// set the button' s bitmap to the one loaded from resources
::SendMessage(hChild , BM_SETIMAGE, IMAGE_BITMAP, (LPARAM) m_hBmp);

The options LR_LOADTRANSPARENT | LR_LOADMAP3DCOLORS were very handy in allowing the system to draw transparent bitmaps on top of the buttons.
Amyuni Development Team

Efficient and accurate conversion to PDF, XPS, PDF/A and more. Free trials at - https://www.amyuni.com
Post Reply