Я хотел бы создать приложение Direct2D с прозрачным фоном, на котором размещены несколько непрозрачных сложных элементов управления.
Проблема может быть разбита на несколько подзадач:
Архитектура: Должны ли элементы управления быть реализованы как дочерние окна? Я думаю, что это правильный подход, а не создание полигонов Direct2D, которые реализуют функциональность дочернего окна.
Я попытался реализовать это, инициализируя родительское окно:
SetWindowLong(m_hwnd, GWL_EXSTYLE, GetWindowLong(m_hwnd, GWL_EXSTYLE) | WS_EX_LAYERED);
SetLayeredWindowAttributes(m_hwnd, 0, (255 * 50) / 100, LWA_ALPHA);
И создайте дочернее окно как WS_CHILD. Это привело к ребенку, у которого все D2D-утопления, включая фон, прозрачны. Я не мог найти способ сделать ребенка непрозрачным.
Когда я создаю дочернее окно как WS_POPUP или же WS_OVERLAPPED проблема непрозрачности решена, но дочернее окно расположено на рабочем столе независимо от родителя.
Многослойное окно?
Я решил работать с многоуровневой Windows, но, поскольку я нацелился на VistaSP2 и выше, возможно, найдутся лучшие решения.
Я попробовал предложенное решение Вот но я тоже не смог реализовать это.
Вы хотите создать окно размером 32 бита на пиксель?
(Извините за невозможность комментировать, здесь недостаточно представителей)
В этом случае вы вынуждены использовать UpdateLayeredWindow (и вызов CreateDIBSection во время инициализации), независимо от того, что каждый раз, когда вы заканчиваете рисовать сцену, после того, как вы заканчиваете рисовать сцену, например:
// Draw to your D2D1 RenderTarget here
RECT rcWin = {0};
GetWindowRect(hWnd,&rcWin);
POINT ptw = {rcWin.left,rcWin.top};
SIZE pts = {rcWin.right-rcWin.left,rcWin.bottom-rcWin.top};
POINT ptsrc = {0};
HDC ScreenDC = GetDC(0);
UpdateLayeredWindow( hWnd, ScreenDC, &ptw, &pts, MemDC, &ptsrc, 0, &bf, ULW_ALPHA);
ReleaseDC(0,ScreenDC);
Об инициализации:
RECT r = {0};
GetWindowRect(hWnd,&r);
HDC scrDC = GetDC(0);
MemDC = CreateCompatibleDC(scrDC);
ReleaseDC(0,scrDC);
if(!MemDC)
{ FailInit(); }
BITMAPINFO bmi = {0};
bmi.bmiHeader.biBitCount = 32;
bmi.bmiHeader.biCompression = BI_RGB;
bmi.bmiHeader.biPlanes = 1;
bmi.bmiHeader.biWidth = r.right-r.left;
bmi.bmiHeader.biHeight = r.bottom-r.top;
bmi.bmiHeader.biSize = sizeof(bmi.bmiHeader);
DIBSectionBitmap = CreateDIBSection(MemDC,&bmi,DIB_RGB_COLORS,0,0,0);
if(!DIBSectionBitmap)
return 0;
OldBmp = (HBITMAP)SelectObject(MemDC,DIBSectionBitmap);
// Now create the HWND D2D1 RenderTarget.
По поводу освобождения ресурсов:
// Free the D2D1 RenderTarget here
if(MemDC && OldBmp)
SelectObject(MemDC,OldBmp);
if(DIBSectionBitmap)
DeleteObject(DIBSectionBitmap);
if(MemDC)
DeleteDC(MemDC);
MemDC = 0;
OldBmp = 0;
DIBSectionBitmap = 0;
РЕДАКТИРОВАТЬ: MemDC, OldBmp и DIBSectionBitmap для каждого окна.
MemDC — это HDC.
OldBmp — это HBITMAP.
DIBSectionBitmap является HBITMAP.
На этом этапе вы можете рисовать ваши дочерние окна, как если бы они были частью вашего собственного главного окна, с точностью до пикселя в пикселях, но вам нужно будет самостоятельно управлять фокусировкой и обменом сообщениями.
Других решений пока нет …