Ну, я нашел один метод, который работает для моих нужд;Я не знаю, является ли это идеальным решением, но если никто не может придумать что-то лучшее, я приму свой собственный ответ через несколько дней.
Итак, вот трюк, который я использую (перенесено изиспользование ATI CImage для сырых Win32 API, поэтому могут быть некоторые ошибки):
LRESULT CALLBACK MyButtonProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch(uMsg)
{
case WM_ERASEBKGND:
if(!m_BackgroundBitmap)
{
// first time the button's background is being erased
// all the controls below it in the z-order have already
// been drawn at this point, so take a snapshot of the
// contents of the device context to use in the future
RECT rc;
GetWindowRect(hWnd, &rc);
int cx = rc.right - rc.left;
int cy = rc.bottom - rc.top;
HDC hDC = (HDC)wParam;
HDC hDCMem = CreateCompatibleDC(hDC);
m_BackgroundBitmap = CreateCompatibleBitmap(hDC, cx, cy);
HBITMAP hBmpOld = (HBITMAP)SelectObject(hDCMem, m_BackgroundBitmap);
BitBlt(hDCMem, 0, 0, cx, cy, hDC, 0, 0, SRCCOPY);
SelectObject(hDCMem, hBmpOld);
hBmpOld = NULL;
DeleteDC(hDCMem);
hDCMem = NULL;
}
break;
}
return CallWindowProc(m_PrevProc, hWnd, uMsg, wParam, lParam);
}
INT_PTR CALLBACK MyDialogProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch(uMsg)
{
case WM_INITDIALOG:
// load resources, subclass buttons, etc.
return TRUE;
case WM_DRAWITEM:
// figure out if display needs to be updated, which face to draw, etc.
HDC hDC = lpDrawItemStruct->hDC;
HDC hDCMem = CreateCompatibleDC(hDC);
// first copy the background from the snapshot taken earlier
HBITMAP hBmpOld = (HBITMAP)SelectObject(hDCMem, m_BackgroundBitmap);
BitBlt(hDC, x, y, w, h, hDCMem, 0, 0, SRCCOPY);
// then alphablend the button face on top of that
SelectObject(hDCMem, m_AlphaButtonBitmap);
AlphaBlend(hDC, x, y, w, h, hDCMem, 0, 0, w, h, bf);
SelectObject(hDCMem, hBmpOld);
hBmpOld = NULL;
DeleteDC(hDCMem);
hDCMem = NULL;
return TRUE;
}
return FALSE;
}