You can use ImageList_Draw and ILD_TRANSPARENT to draw icons with transparency.
Test with a .png for the ImageList, in C++/Win32 with an OD context menu :
#include <windows.h>
#include <tchar.h>
#include <commctrl.h>
#pragma comment (lib, "comctl32")
#include <Vsstyle.h>
#include <vssym32.h>
#include <uxtheme.h>
#pragma comment(lib, "UxTheme")
#include <gdiplus.h>
using namespace Gdiplus;
#pragma comment(lib, "gdiplus.lib")
#pragma comment(linker,"\"/manifestdependency:type='win32' \
name='Microsoft.Windows.Common-Controls' version='6.0.0.0' \
processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"")
HINSTANCE hInst;
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
int nWidth = 600, nHeight = 400;
#define IDC_STATIC 10
#define IDC_BUTTON 11
struct ODM_DATA
{
int nImageListIndex;
TCHAR szItemText[128];
};
int m_nSizeBitmap = 48;
HIMAGELIST m_hImageList = NULL;
HBITMAP m_hBitmapImageList = NULL;
void MeasureItem(HWND hWnd, LPMEASUREITEMSTRUCT lpMeasure);
void DrawItem(HWND hWnd, LPDRAWITEMSTRUCT lpDraw);
enum PreferredAppMode { Default, AllowDark, ForceDark, ForceLight, Max };
typedef PreferredAppMode(WINAPI* fnSetPreferredAppMode)(PreferredAppMode appMode);
fnSetPreferredAppMode pSetPreferredAppMode;
int APIENTRY wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance, _In_ LPWSTR lpCmdLine, _In_ int nCmdShow)
{
GdiplusStartupInput gdiplusStartupInput;
ULONG_PTR gdiplusToken;
GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);
hInst = hInstance;
WNDCLASSEX wcex =
{
sizeof(WNDCLASSEX), CS_HREDRAW | CS_VREDRAW, WndProc, 0, 0, hInst, LoadIcon(NULL, IDI_APPLICATION),
LoadCursor(NULL, IDC_ARROW), (HBRUSH)(COLOR_WINDOW + 1), NULL, TEXT("WindowClass"), NULL,
};
if (!RegisterClassEx(&wcex))
return MessageBox(NULL, TEXT("Cannot register class !"), TEXT("Error"), MB_ICONERROR | MB_OK);
int nX = (GetSystemMetrics(SM_CXSCREEN) - nWidth) / 2, nY = (GetSystemMetrics(SM_CYSCREEN) - nHeight) / 2;
HWND hWnd = CreateWindowEx(0, wcex.lpszClassName, TEXT("Test"), WS_OVERLAPPEDWINDOW, nX, nY, nWidth, nHeight, NULL, NULL, hInst, NULL);
if (!hWnd)
return MessageBox(NULL, TEXT("Cannot create window !"), TEXT("Error"), MB_ICONERROR | MB_OK);
ShowWindow(hWnd, SW_SHOWNORMAL);
UpdateWindow(hWnd);
MSG msg;
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
GdiplusShutdown(gdiplusToken);
return (int)msg.wParam;
}
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
static HWND hWndButton = NULL, hWndStatic = NULL;
int wmId, wmEvent;
switch (message)
{
case WM_CREATE:
{
// hWndStatic = CreateWindowEx(0, TEXT("Static"), TEXT(""), WS_CHILD | WS_VISIBLE | SS_BITMAP, 10, 10, 200, 200, hWnd, (HMENU)IDC_STATIC, hInst, NULL);
// hWndButton = CreateWindowEx(0, L"Button", L"Click", WS_CHILD | WS_VISIBLE | BS_PUSHLIKE, 100, 60, 60, 32, hWnd, (HMENU)IDC_BUTTON, hInst, NULL);
// copied at https://i.ibb.co/0RmQM2dp/Balls-Image-List.png
Bitmap* bitmap = new Bitmap(TEXT("Balls_ImageList.png"));
Gdiplus:Status nStatus = bitmap->GetHBITMAP(Gdiplus::Color(255, 255, 255), &m_hBitmapImageList);
m_hImageList = ImageList_Create(m_nSizeBitmap, m_nSizeBitmap, ILC_COLOR32 | ILC_MASK, 1, 0);
int nIndex = ImageList_AddMasked(m_hImageList, m_hBitmapImageList, RGB(255, 255, 255));
HMODULE hDll = LoadLibrary(TEXT("UXTheme.dll"));
pSetPreferredAppMode = (fnSetPreferredAppMode)GetProcAddress(hDll, MAKEINTRESOURCEA(135));
if (pSetPreferredAppMode)
pSetPreferredAppMode(AllowDark);
return 0;
}
break;
case WM_RBUTTONDOWN:
{
HMENU hMenu = CreatePopupMenu();
ODM_DATA data;
for (int i = 1; i <= 10; i++)
{
ODM_DATA* pData = (ODM_DATA*)malloc(sizeof(ODM_DATA));
if (pData)
{
data.nImageListIndex = i - 1;
swprintf_s(data.szItemText, TEXT("Menu Item %d"), i);
memcpy(pData, &data, sizeof(ODM_DATA));
AppendMenu(hMenu, MF_BYCOMMAND | MF_OWNERDRAW, i, (LPCWSTR)pData);
}
}
POINT pt;
GetCursorPos(&pt);
int nChoice = TrackPopupMenu(hMenu, TPM_LEFTALIGN | TPM_RETURNCMD, pt.x, pt.y, 0, hWnd, NULL);
if (nChoice != 0)
{
MENUITEMINFO mii = { sizeof(MENUITEMINFO) };
mii.fMask = MIIM_DATA;
if (GetMenuItemInfo(hMenu, nChoice, FALSE, &mii))
{
free((ODM_DATA*)mii.dwItemData);
TCHAR wsMessage[MAX_PATH] = _T("");
wsprintf(wsMessage, TEXT("Selected item : %d"), nChoice);
MessageBox(NULL, wsMessage, TEXT("Information"), MB_OK | MB_ICONINFORMATION);
}
}
DestroyMenu(hMenu);
}
break;
case WM_MEASUREITEM:
{
MeasureItem(hWnd, (LPMEASUREITEMSTRUCT)lParam);
return TRUE;
}
break;
case WM_DRAWITEM:
{
DrawItem(hWnd, (LPDRAWITEMSTRUCT)lParam);
return TRUE;
}
break;
case WM_COMMAND:
{
wmId = LOWORD(wParam);
wmEvent = HIWORD(wParam);
switch (wmId)
{
case IDC_BUTTON:
{
if (wmEvent == BN_CLICKED)
{
Beep(1000, 10);
}
}
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
}
break;
case WM_PAINT:
{
PAINTSTRUCT ps;
HDC hDC = BeginPaint(hWnd, &ps);
EndPaint(hWnd, &ps);
}
break;
case WM_DESTROY:
{
PostQuitMessage(0);
return 0;
}
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
void MeasureItem(HWND hWnd, LPMEASUREITEMSTRUCT pMIS)
{
ODM_DATA* data = (ODM_DATA*)pMIS->itemData;
pMIS->itemHeight = m_nSizeBitmap;
pMIS->itemWidth = 260;
}
void DrawItem(HWND hWnd, LPDRAWITEMSTRUCT pDIS)
{
if (!pDIS || !pDIS->itemData) return;
ODM_DATA* data = (ODM_DATA*)pDIS->itemData;
HTHEME hMenuTheme = OpenThemeData(NULL, TEXT("MENU"));
HDC hdc = pDIS->hDC;
RECT rcItem = pDIS->rcItem;
if (hMenuTheme)
{
DrawThemeBackground(hMenuTheme, hdc, MENU_POPUPBACKGROUND, MPI_NORMAL, &rcItem, NULL);
DrawThemeBackground(hMenuTheme, hdc, MENU_POPUPITEM, (pDIS->itemState & ODS_SELECTED) ? MPI_HOT : MPI_NORMAL,&rcItem, NULL);
}
else
{
HBRUSH hBrush = CreateSolidBrush(GetSysColor((pDIS->itemState & ODS_SELECTED) ? COLOR_HIGHLIGHT : COLOR_MENU));
FillRect(hdc, &rcItem, hBrush);
DeleteObject(hBrush);
}
ImageList_Draw(m_hImageList, data->nImageListIndex, hdc, rcItem.left, rcItem.top, ILD_TRANSPARENT);
RECT rcText = rcItem;
rcText.left += m_nSizeBitmap + 8;
if (hMenuTheme)
{
DrawThemeText(hMenuTheme, hdc, MENU_POPUPITEM, (pDIS->itemState & ODS_SELECTED) ? MPI_HOT : MPI_NORMAL,
data->szItemText, -1, DT_SINGLELINE | DT_VCENTER | DT_NOPREFIX, 0, &rcText);
CloseThemeData(hMenuTheme);
}
else
{
SetBkMode(hdc, TRANSPARENT);
SetTextColor(hdc, GetSysColor((pDIS->itemState & ODS_SELECTED) ? COLOR_HIGHLIGHTTEXT : COLOR_MENUTEXT));
DrawText(hdc, data->szItemText, -1, &rcText, DT_SINGLELINE | DT_VCENTER);
}
}