Сбросить существующий HBITMAP в качестве фона рабочего стола (Win32)
Я хочу создать прозрачное окно поверх рабочего стола.
Для этого я создал HDC с фоном рабочего стола (создал HBITMAP рабочего стола и применил его к моему HDC) и вызвал UpdateLayeredWindow.
Все идет нормально.
из-за проблем с производительностью мне нужно сохранить постоянный объект GDI+, что означает, что мои HDC и HBITMAP должны оставаться одинаковыми маркерами между картинами (при условии, что рабочий стол DC не изменился), так же, как в этом вопросе.
В первой итерации покраски все идет хорошо. во второй итерации рисования, поскольку 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
}
Есть идеи?
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);