【问题标题】:How do I alphablend a bitmap onto an owner-drawn button that overlaps other windows?如何将位图 alphablend 到与其他窗口重叠的自绘按钮上?
【发布时间】:2011-10-12 14:10:21
【问题描述】:

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

我的位图类似于this,除了对话框具有自定义背景(在 WM_ERASEBKGND 期间绘制的位图)并且矩形进一步水平延伸。

【问题讨论】:

    标签: windows winapi transparency


    【解决方案1】:

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

    【讨论】:

      【解决方案2】:

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

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

      【讨论】:

      • 糟糕,当对话框最初位于另一个窗口(例如,任务栏)下方时,这不起作用;它最终将另一个窗口的位复制到快照中。
      猜你喜欢
      • 2013-02-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-07-15
      相关资源
      最近更新 更多