我如何将位图字母混合到与其他窗口重叠的所有者绘制的按钮上



我试图用alpha通道(通过AlphaBlend)绘制位图作为自己绘制的按钮的面。问题是我不确定如何绘制按钮的背景。按钮的位图是圆形的,按钮位于静态控件的顶部,该控件绘制矩形位图(通过SS_BITMAP)。它在第一次绘制时看起来很好,但随后的绘图最终将位图与DC中的剩余部分进行字母混合,因此边缘(alpha像素所在的地方)变得丑陋。我尝试将对话框背景复制到我在WM_DRAWITEM中获得的DC,但这只会让我获得对话框背景;它不能让我得到按钮下的静态控制部分。我该怎么做呢?

我的位图与此相似,除了对话框有一个自定义背景(在WM_ERASEBKGND期间绘制的位图),矩形进一步向水平方向扩展。

我找到了一个更好的解决方案。它基本上与我以前的解决方案结构相同,只是没有复制设备上下文中已经存在的内容到位图,我发送所有相关控件WM_ERASEBKGND和WM_PRINTCLIENT消息。我基于这篇知识库文章中的代码。

嗯,我找到了一个适合我需要的方法;我不知道这是不是理想的解决方案,但如果没人能想出更好的办法,那么几天后我会接受我自己的答案。

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

最新更新