Reset existing HBITMAP as desktop background

EDN Admin

Well-known member
Joined
Aug 7, 2010
Messages
12,794
Location
In the Machine
<p style=" I wish to create a transparent window over the desktop.<br/>
For that purpose Ive created an HDC with a background of the desktop (created HBITMAP of the desktop and applied it to my HDC), and invoked <em style="vertical-align:baseline; background-color:transparent; padding:0px; margin:0px; border:0px initial initial UpdateLayeredWindow[/i].
<p style=" So far, so good.<br/>
for performance issues i need to keep a persistent GDI+ object, meaning my HDC and HBITMAP need to stay the same handles between paintings (assuming the desktop DC didnt change), same as in http://stackoverflow.com/questions/2074294/win32-does-a-window-have-the-same-hdc-for-its-entire-lifetime this
question .
<p style=" In the first painting iteration all goes well. in the second painting iteration, since the HDC and HBITMAP havent changed, I repaint on the existing HDC, meaning i get double images (the background is not erased).
<p style=" Heres a code example of what Im doing:
<p style="
<div style="color:Black;background-color:White; <pre>
<span style="color:Blue; bool SomeUI::Draw()
{
BLENDFUNCTION blend = {0};
POINT ptPos = {0};
SIZE sizeWnd = {0};
POINT ptSrc = {0};
BOOL bUpdate = FALSE;

<span style="color:Green; // Get the client rect
RECT rctWindow;
<span style="color:Blue; bool bGot = GetWindowRect(rctWindow);
<span style="color:Blue; if (!bGot)
<span style="color:Blue; return <span style="color:Blue; false;

<span style="color:Green; // Get the desktops device context
HDC hDCDesktop = GetDC(NULL);
<span style="color:Blue; if (!hDCDesktop)
<span style="color:Blue; return <span style="color:Blue; false;

<span style="color:Blue; int nWidth = abs(rctWindow.right - rctWindow.left);
<span style="color:Blue; int nHeight = abs(rctWindow.bottom - rctWindow.top);

<span style="color:Green; // Create 32Bit bitmap to apply PNG transparency
VOID *ppvBits = NULL;
BITMAPINFO BitmapInfo = {0};
BitmapInfo.bmiHeader.biSize = <span style="color:Blue; 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);
<span style="color:Blue; if (!hBmp || hBmp==(HBITMAP)ERROR_INVALID_PARAMETER)
<span style="color:Blue; goto releaseHandles;

<span style="color:Green; // Create a compatible DC and select the newly created bitmap
<span style="color:Blue; if (!m_hDC)
{
m_hDC = CreateCompatibleDC(hDCDesktop);
<span style="color:Blue; if (!m_hDC)
<span style="color:Blue; goto releaseHandles;

SelectObject(m_hDC, hBmp);
}
<span style="color:Blue; else
{
<span style="color:Green; ///////////////////////////////////////////////////////////////////////
<span style="color:Green; //
<span style="color:Green; // The problem lies here, this is where I need to reset the HBITMAP
<span style="color:Green; // according to the desktop here (to have a transparent DC to work on)
<span style="color:Green; //
<span style="color:Green; ///////////////////////////////////////////////////////////////////////
}

<span style="color:Green; // The drawing logic
<span style="color:Blue; bool bInnerDraw = Draw(m_hDC);
<span style="color:Blue; if (!bInnerDraw)
<span style="color:Blue; goto releaseHandles;

<span style="color:Green; // 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);
<span style="color:Blue; if (!bUpdate)
<span style="color:Blue; goto releaseHandles;

releaseHandles:
<span style="color:Green; // releasing handles
}
[/code]
<br/>
<br/>

<p style=" Ive tried several alternatives.
<p style=" For example, in the second painting iteration, I tried capturing the desktop background into a temporary HDC and copy it to my persistent HDC:
<p style="
<div style="color:Black;background-color:White; <pre>
HDC hTempDC = CreateCompatibleDC(hDCDesktop);
<span style="color:Blue; if (!hTempDC)
<span style="color:Blue; goto releaseBitMap;
SelectObject(hTempDC, hBmp); <span style="color:Green; // hBmp was created earlier by CreateDIBSection() with the desktop DC

::BitBlt(m_hDC, 0, 0, abs(rctClient.right-rctClient.left), abs(rctClient.bottom-rctClient.top), hTempDC, rctWindow.left, rctWindow.right, SRCCOPY);
::DeleteDC(hTempDC);
[/code]
<br/>
<br/>

<p style=" But since im using UpdateLayeredWindow, the desktop DC contains what i previously painted on it.
<p style=" Any ideas?

View the full article
 
Back
Top