Pregunta

Deseo crear una ventana transparente sobre el escritorio.
Para ese propósito, he creado un HDC con un fondo del escritorio (creado HBITMAP del escritorio y lo apliqué a mi HDC) e invocado UpdateLayerDwindow.

Hasta aquí todo bien.
Para problemas de rendimiento, necesito mantener un objeto GDI+ persistente, lo que significa que mi HDC y HBITMAP deben mantener las mismas manijas entre las pinturas (suponiendo que el escritorio DC no cambió), igual que en esta pregunta.

En la primera iteración de pintura todo va bien. En la segunda iteración de pintura, dado que el HDC y el HBITMAP no han cambiado, repinto en el HDC existente, lo que significa que obtengo imágenes dobles (el fondo no se borra).

Aquí hay un ejemplo de código de lo que estoy haciendo:

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
}

¿Algunas ideas?

¿Fue útil?

Solución

Encontré la respuesta:

Para restablecer el HBITMAP persistente (Recordatorio: debe mantener el mismo mango), estableceremos los antecedentes de escritorio de esa área en un HBITMAP temporal y lo copiaremos en el HBITMAP persistente.
Para lograr eso (copiar de un HBITMAP al otro), crearemos un HDC temporal y seleccionaremos el HBITMAP temporal y copiaremos el HDC temporal al HDC persistente, USIST Bitblt

Aquí está el código:

        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);
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top