Я пытаюсь нарисовать растровое изображение (хранится в виде массива байтов) в окне.
Типичная процедура следующая:
Получите контекст устройства в обработчике OnPaint ().
CPaintDC dc(this);
Создайте из него совместимый контекст устройства,
CDC pMemDC->CreateCompatibleDC(&dc);
Создайте совместимое растровое изображение размером с клиентскую область (GetClientRect(&WinRect)
).
CBitmap pNewBitmap->CreateCompatibleBitmap(&dc, WinRect.Width(), WinRect.Height());
Теперь, если размер окна клиента точно такой же, как у растрового изображения, я могу просто позвонить pNewBitmap->SetBitmapBits
«кормить» мой массив в растровое изображение.
Следуйте за этим с BitBlt
и растровое изображение появляется в окне.
dc->BitBlt(0, 0, WinRect.Width(), WinRect.Height(), pMemDC, 0, 0, SRCCOPY);
Если вы хотите, чтобы размер окна изменялся независимо от размера изображения, то сначала вы должны убедиться, что pNewBitmap
правильный размер (клиентский прямоугольник), но теперь вы не можете просто вставить массив в растровое изображение.
В этой ситуации я нашел решение, повторив вышеописанную процедуру, чтобы создать точечный рисунок точного размера изображения, чтобы я мог «засунуть» в него свои биты, а затем BitBlt
что в больший, размером с клиент растровое изображение, которое затем получает BitBlt
в окно
Есть ли другой способ сделать это? Актуальный код следует.
void CAnimateWnd::OnPaint()
{
CPaintDC dc(this); // device context for painting
DrawScene(&dc);
// Do not call CWnd::OnPaint() for painting messages
}
void CAnimateWnd::DrawScene(CDC *pDrawDC)
{
CRect WinRect;
GetClientRect(&WinRect);
if (pNewBitmap == NULL)
{
pMemDC = new CDC();
pMemDC->CreateCompatibleDC(pDrawDC);
pNewBitmap = new CBitmap();
pNewBitmap->CreateCompatibleBitmap(pDrawDC, WinRect.Width(), WinRect.Height());
pMemDC->SelectObject(pNewBitmap);
}
CRect BMPRect;
GetBitmapDrawSize(&BMPRect);
if (BMPRect != NULL)
{
if (!(BMPRect.Width() >= WinRect.Width() && BMPRect.Height() >= WinRect.Height()))
{
//The bitmap is smaller than the window, so fill the window with the background color.
CBrush BackBrush(BackGndColor);
CPen BackPen(PS_SOLID, 1, BackGndColor);
pMemDC->SelectObject(&BackBrush);
pMemDC->SelectObject(&BackPen);
pMemDC->Rectangle(&WinRect);
BackBrush.DeleteObject();
BackPen.DeleteObject();
}
}
OverrideAndDrawInHere(pMemDC, resize);
pDrawDC->BitBlt(0,0,WinRect.right,WinRect.bottom,pMemDC,0,0,SRCCOPY);
}
template <class T>
void ImageWindow<T>::OverrideAndDrawInHere(CDC *pDC, int resize)
{
if (this->sourceImage == NULL) return;
CRect clientRect;
GetClientRect(&clientRect);
if (this->dispBMP == NULL)
{
this->dispDC = new CDC();
this->dispDC->CreateCompatibleDC(pDC);
this->dispBMP = new CBitmap();
this->dispBMP->CreateCompatibleBitmap(pDC, this->sourceImage->GetWidth(), this->sourceImage->GetHeight());
this->dispDC->SelectObject(this->dispBMP);
}
this->dispBMP->SetBitmapBits(this->sourceImage->GetArea() * 4, this->translatedImage);
pDC->BitBlt(0, 0, this->sourceImage->GetWidth(), this->sourceImage->GetHeight(), this->dispDC, 0, 0, SRCCOPY);
}
Вместо использования BitBlt попробуйте StretchBlt если вы хотите нарисовать растровое изображение в окне, которое не совпадает с размером исходного изображения:
Из MSDN:
Копирует растровое изображение из исходного прямоугольника в целевой прямоугольник,
растяжение или сжатие растрового изображения, если необходимо, чтобы соответствовать
Размеры целевого прямоугольника.
Если вам нужны те же результаты, которые вы показали, то вы, вероятно, делаете это наилучшим образом. Вы можете использовать что-то вроде FillRect, чтобы рисовать непосредственно во фрейм (или обрабатывать OnEraseBkgnd), а затем BitBlt изображение исходного размера, но вы, вероятно, получите некоторое мерцание, которое решает ваше решение с двойной буферизацией.