【问题标题】:Reset existing HBITMAP as desktop background (Win32)将现有 HBITMAP 重置为桌面背景 (Win32)
【发布时间】:2012-01-12 17:36:25
【问题描述】:

我希望在桌面上创建一个透明窗口。
为此,我创建了一个具有桌面背景的 HDC(创建了桌面的 HBITMAP 并将其应用于我的 HDC),并调用了 UpdateLayeredWindow

到目前为止,一切都很好。
对于性能问题,我需要保留一个持久的 GDI+ 对象,这意味着我的 HDC 和 HBITMAP 需要在绘画之间保持相同的句柄(假设桌面 DC 没有改变),与 this question 相同。

在第一次绘画迭代中一切顺利。在第二次绘画迭代中,由于 HDC 和 HBITMAP 没有改变,我在现有的 HDC 上重新绘画,这意味着我得到了双图像(背景没有被擦除)。

这是我正在做的代码示例:

bool SomeUI::Draw()
{
    BLENDFUNCTION blend = {0};
    POINT ptPos = {0};
    SIZE sizeWnd = {0};
    POINT ptSrc = {0};
    BOOL bUpdate = FALSE;

    // Get the client rect
    RECT rctWindow;
    bool bGot = GetWindowRect(rctWindow);
    if (!bGot)
        return false;

    // Get the desktop's device context
    HDC hDCDesktop = GetDC(NULL);
    if (!hDCDesktop)
        return false;

    int nWidth = abs(rctWindow.right - rctWindow.left);
    int nHeight = abs(rctWindow.bottom - rctWindow.top);

    // Create 32Bit bitmap to apply PNG transparency
    VOID *ppvBits = NULL;
    BITMAPINFO BitmapInfo = {0};
    BitmapInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
    BitmapInfo.bmiHeader.biWidth = nWidth;
    BitmapInfo.bmiHeader.biHeight = nHeight;
    BitmapInfo.bmiHeader.biPlanes = 1;
    BitmapInfo.bmiHeader.biBitCount = 32;
    BitmapInfo.bmiHeader.biCompression = BI_RGB;

    HBITMAP hBmp = CreateDIBSection(hDCDesktop, &BitmapInfo, DIB_RGB_COLORS, &ppvBits, NULL, 0);
    if (!hBmp || hBmp==(HBITMAP)ERROR_INVALID_PARAMETER)
        goto releaseHandles;

    // Create a compatible DC and select the newly created bitmap
    if (!m_hDC)
    {
        m_hDC = CreateCompatibleDC(hDCDesktop);
        if (!m_hDC)
            goto releaseHandles;

        SelectObject(m_hDC, hBmp);
    }
    else
    {
        ///////////////////////////////////////////////////////////////////////
        //
        // The problem lies here, this is where I need to reset the HBITMAP 
        // according to the desktop here (to have a transparent DC to work on)
        //
        ///////////////////////////////////////////////////////////////////////
    }

    // The drawing logic
    bool bInnerDraw = Draw(m_hDC);
    if (!bInnerDraw)
        goto releaseHandles;

    // Call UpdateLayeredWindow
    blend.BlendOp = AC_SRC_OVER;
    blend.SourceConstantAlpha = 255;
    blend.AlphaFormat = AC_SRC_ALPHA;
    sizeWnd.cx = nWidth;
    sizeWnd.cy = nHeight;
    ptPos.x = rctWindow.left;
    ptPos.y = rctWindow.top;
    bUpdate = UpdateLayeredWindow(m_hWnd, hDCDesktop, &ptPos, &sizeWnd, m_hDC, &ptSrc, 0, &blend, ULW_ALPHA);
    if (!bUpdate)
        goto releaseHandles;

releaseHandles:
    // releasing handles
}

有什么想法吗?

【问题讨论】:

    标签: c++ c winapi hbitmap gdi


    【解决方案1】:

    找到答案:

    为了重置持久 HBITMAP,(提醒:它需要保持相同的句柄),我们将该区域的桌面背景设置为临时 HBITMAP,并将其复制到持久 HBITMAP。
    为了实现这一点(从一个 HBITMAP 复制到另一个),我们将创建一个临时 HDC 并选择临时 HBITMAP 到它,然后将临时 HDC 复制到持久 HDC,使用 BitBlt

    代码如下:

            hBmpTemp = CreateDIBSection(hDCDesktop, &BitmapInfo, DIB_RGB_COLORS, &ppvBits, NULL, 0);
            if (!hBmpTemp || hBmpTemp==(HBITMAP)ERROR_INVALID_PARAMETER)
                goto releaseHandles;
    
            HDC hTempDC = CreateCompatibleDC(NULL);
            if (!hTempDC)
                goto releaseHandles;
    
            SelectObject(hTempDC, hBmpTemp);
    
            ::BitBlt(m_hPersistentDC, 0, 0, nWidth, nHeight, hTempDC, rctWindow.left, rctWindow.top, SRCCOPY);
    
            ::DeleteDC(hTempDC);
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2010-12-27
      • 1970-01-01
      • 2021-10-02
      • 1970-01-01
      • 2021-01-14
      • 1970-01-01
      • 2020-03-13
      • 1970-01-01
      相关资源
      最近更新 更多