如何将位图alphableble到与其他窗口重叠的所有者绘制按钮?

时间:2011-10-12 14:10:22

标签: windows winapi transparency

我正在尝试使用Alpha通道(通过AlphaBlend)绘制一个位图,作为所有者绘制按钮的面。问题是我不知道如何绘制按钮的背景。按钮的位图是圆形的,按钮位于静态控件的顶部,该控件绘制矩形位图(通过SS_BITMAP)。第一次绘制它看起来很好,但随后的绘图最终将位图与其残留在DC中进行混合,因此边缘(alpha像素所在的边缘)变得难看。我尝试将对话框背景复制到我在WM_DRAWITEM中获得的DC,但这只能获得对话框背景;它不会让我成为按钮下静态控件的一部分。我该怎么做?

我的位图与this类似,只是对话框有自定义背景(WM_ERASEBKGND期间绘制的位图),矩形水平延伸得更远。

2 个答案:

答案 0 :(得分:1)

我找到了更好的解决方案。它与我之前的解决方案基本相同,只是将设备上下文中已有的内容复制到位图而不是发送所有相关控件WM_ERASEBKGND和WM_PRINTCLIENT消息。我的基础是this KB article中的代码。

答案 1 :(得分:0)

好吧,我找到了一种适合我需要的方法;我不知道这是否是理想的解决方案,但如果没有人能提出更好的解决方案,我会在几天内接受我自己的答案。

所以这是我正在使用的技巧(从使用ATL的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;
}