2

デスクトップ上に透明なウィンドウを作成したいと考えています。
そのために、デスクトップの背景を持つ HDC を作成し (デスクトップの HBITMAP を作成して HDC に適用)、UpdateLayeredWindowを呼び出しました。

ここまでは順調ですね。パフォーマンスの問題については、この質問
と同じように、永続的な GDI+ オブジェクトを保持する必要があります。

最初の塗装の反復では、すべてうまくいきます。2 回目の描画では、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
}

何か案は?

4

1 に答える 1

2

答えを見つけました:

永続的な HBITMAP をリセットするには (注意: 同じハンドルを維持する必要があります)、その領域のデスクトップの背景を一時的な HBITMAP に設定し、それを永続的な HBITMAP にコピーします。これを実現するには (ある HBITMAP から別の HBITMAP にコピーする)、一時的な HDC を作成し、それに一時的な HBITMAP を選択し、 BitBlt
を使用して一時的な HDC を永続的な HDC にコピーします。

コードは次のとおりです。

        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);
于 2011-12-05T18:31:43.477 に答える