I tried all of the other approaches, and the best case was the correct background being painted, but the group box line was visible behind the group box label. A group box is really a button ( with a static label on it ), and so the button needs to paint the text background solid to draw over the group box line.

This solution creates a brush out of the background of the parent. So, this even works if the tab/dialog background is a drawn image.

The function below can be used for any control, but is only needed in this case for statics and group boxes.

Note that the CBrush (m_brush) is a member of the parent ( dialog )

HBRUSH CSomeDlg::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
{
if ( nCtlColor == CTLCOLOR_STATIC )
{
return CreateCtrlBrush( this, pWnd, m_brush );
}

return CDialog::OnCtlColor(pDC, pWnd, nCtlColor);
}

// Reusable function for all of your dialogs
HBRUSH CreateCtrlBrush( CWnd* a_pDlg, CWnd* a_pCtrl, CBrush& a_brush )
{
CRect ctrlRect;
CRect dlgRect;

CDC* pTempDC = a_pDlg->GetDC();

a_pCtrl->GetWindowRect( &ctrlRect );
a_pDlg->GetWindowRect( &dlgRect );

// Map control rect to parent background
int x = ctrlRect.left - dlgRect.left;
int y = ctrlRect.top - dlgRect.top;
int w = ctrlRect.Width();
int h = ctrlRect.Height();

// Bitmap to hold background for control
CBitmap bkgndBitmap;
bkgndBitmap.CreateCompatibleBitmap( pTempDC, w, h );

// And a DC used to fill it in.
CDC dcBitmap;
dcBitmap.CreateCompatibleDC( pTempDC );
dcBitmap.SelectObject( bkgndBitmap );

// Copy background into bitmap
dcBitmap.BitBlt(0, 0, w, h, pTempDC, x, y, SRCCOPY);

if ( a_brush.m_hObject )
a_brush.DeleteObject();

a_brush.CreatePatternBrush( &bkgndBitmap );

a_pDlg->ReleaseDC( pTempDC );

return (HBRUSH) a_brush;
}