Как я могу добавить растровое изображение на нарисованную владельцем кнопку, которая перекрывает другие окна? - PullRequest
0 голосов
/ 12 октября 2011

Я пытаюсь нарисовать растровое изображение с альфа-каналом (через AlphaBlend) в качестве лица нарисованной владельцем кнопки. Проблема в том, что я не уверен, как нарисовать фон кнопки. Растровое изображение кнопки является круглым, а кнопка находится поверх статического элемента управления, который рисует прямоугольное растровое изображение (через SS_BITMAP). Он выглядит нормально при первом рисовании, но последующие рисунки заканчиваются наложением растрового изображения с его остатками в DC, поэтому края (где лежат альфа-пиксели) становятся некрасивыми. Я попытался скопировать фон диалога в DC, который я получаю в WM_DRAWITEM, но это только дает мне фон диалога; это не дает мне ту часть статического контроля, которая находится под кнопкой. Как мне это сделать?

Мои растровые изображения аналогичны этим , за исключением того, что в диалоговом окне есть пользовательский фон (растровое изображение, нарисованное во время WM_ERASEBKGND) и прямоугольник расширяется по горизонтали.

Ответы [ 2 ]

1 голос
/ 23 октября 2011

Я нашел лучшее решение.По сути, это та же структура, что и в моем предыдущем решении, но вместо того, чтобы копировать то, что уже находится в контексте устройства, в растровое изображение, я отправляю все соответствующие элементы управления WM_ERASEBKGND и WM_PRINTCLIENT.Я основал его на коде этой статьи KB .

0 голосов
/ 13 октября 2011

Ну, я нашел один метод, который работает для моих нужд;Я не знаю, является ли это идеальным решением, но если никто не может придумать что-то лучшее, я приму свой собственный ответ через несколько дней.

Итак, вот трюк, который я использую (перенесено изиспользование 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;
}
...