Пререндеринг? Предварительное формирование изображения в CDC
От: titov_alex  
Дата: 31.05.06 09:40
Оценка:
Здраствуйте.

Хочется сделать предендеринг содержимого окна, в котором находится несколько отдельных элементов, не имеющих собственного 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);


Вот примерно так. Естественно, это только не работающая намётка — в окне получается просто чёрный фон. Как заставить эту схему работать? Или может я иду не по тому пути?

Заранее благодарен.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.