Здраствуйте.
Хочется сделать предендеринг содержимого окна, в котором находится несколько отдельных элементов, не имеющих собственного DC, и при этом отрисовываемых независимо друг от друга.
При этом, формируя изображение элемента, хочется иметь возможность выводить в нём текст, масштабировать и т.п., используя все те функции которые можно использовать при обычном отображении.
Вижу следующий путь. Каждый элемент окна формурует изображение в своём совместимом контексте. Окно создаёт своё отдельное CDC, в которое помещает изображения всех элементов. При получении сообщения WM_PAINT идёт копирование полечунного общего изображения в DC окна
Т.е. суть задачи сводится к тому, чтобы сделать независимый пререндеринг изображений отдельных элементов окна (не имеющих своего собственного DC), которые потом помещаются в DC окна в нужном месте с масштабированием и т.д.
Вот к чему я на данный момент пришёл. Ранее у меня не было случая познакомиться с работой в CDC, так что тут, уверен, множество косяков
Подготовка в окне.
HDC hdc = GetDC(m_hWnd);
hCDC = CreateCompatibleDC(hdc);
BITMAPINFOHEADER bmih;
bmih.biSize = sizeof(BITMAPINFOHEADER);
bmih.biWidth = dx;
bmih.biHeight = -dy;
bmih.biPlanes = 1;
bmih.biBitCount = 32;
bmih.biCompression = BI_RGB;
bmih.biSizeImage = 0;
bmih.biXPelsPerMeter = 0;
bmih.biYPelsPerMeter = 0;
bmih.biClrUsed = 0;
bmih.biClrImportant = 1024;
BITMAPINFO bminfo;
memset(&bminfo, 0, sizeof(BITMAPINFO));
memcpy(&bminfo.bmiHeader, &bmih, sizeof(BITMAPINFO));
hBmp = CreateDIBSection(hCDC, &bminfo, DIB_RGB_COLORS, &lpBits, NULL, 0);
Подготовка в элементе
// создаём CDC для элемента - в нём будет формироваться его изображение
hDCObj = CreateCompatibleDC(GetWindowDC(lpDoc->GetHWND()));
Рендеринг изображения в элементе — пытаемся сделать это похожим на обычную отрисовку окна
Тут есть большое сомнение — можно ли рисовать в совместимом DC так же как и в обычном?
int CD_VObject::OnPaint(HDC hDCObj) {
// hDCObj - контекст совместимого устройства, созданного для данного элемента
int i, j;
for (i = 0; i < mPos.dy; i++) {
for (j = 0; j < mPos.dx; j++) {
SetPixelV(hDCObj, j, i, (COLORREF)i);
}
}
return 0;
}
Во время пререндеринга в окне, для каждого элемена — просто вызываем его метод, отдавая ему координаты, размеры, hDC и hBMP
lpVObject->DVO_Render(hPrerenderedDC, hBmp, lpVObject->x, lpVObject->y, lpVObject->dx, lpVObject->dy);
В элементе:
// Функция добавления содержимого элемента в преденндинговый hBMP окна
int CD_VObject::DVO_Render(HDC hDC, HBITMAP hBmp, int x, int y, int dx, int dy) {
if (!hDCObj) return 0;
if (!hBmp) return 0;
if (!SelectObject(hDC, hBmp)) return 0;
SetStretchBltMode(hDC, HALFTONE);
StretchBlt(hDC, x, y, dx, dy, hDCObj, 0, 0, mPos.dx, mPos.dy, SRCCOPY);
return 0;
}
Непосредственная отрисовка всего общего изображения в окне
PAINTSTRUCT ps;
RECT rc; GetClientRect(m_hWnd, &rc);
HDC hdc;
if (!hBmp) return 0L;
if (!hPrerenderedDC) return 0L;
SIZE sz = {rc.right - rc.left, rc.bottom - rc.top};
if ((sz.cx <=0)||(sz.cy <= 0)) return 0L;
hdc = BeginPaint(m_hWnd, &ps);
SetMapMode(hdc, MM_ANISOTROPIC);
SetWindowExtEx(hdc, mWidth, mHeight, &sz);
SetViewportExtEx(hdc, rc.right, rc.bottom, NULL);
HBITMAP hDIB = (HBITMAP)SelectObject(hPrerenderedDC, hBmp);
BitBlt(hdc, 0, 0, mWidth, mHeight, hPrerenderedDC, 0, 0, SRCCOPY);
EndPaint(m_hWnd, &ps);
Вот примерно так. Естественно, это только не работающая намётка — в окне получается просто чёрный фон. Как заставить эту схему работать? Или может я иду не по тому пути?
Заранее благодарен.
Уже разобрался, надо было просто рендерить элементы в собственные битмапы — и всё сразу заработало