Назад | Начало урока | Вперед
Содержание

Глава 5

Функция DrawObject рисует взрыв на палубе. Эта функция заметно отличается
от функции DrawShip(). Если применить такой-же код, что и в функции DrawShip(),
то взрыв на палубе тоже будет изображен, но при этом будет совсем иной фон рисунка.
А это некрасиво и неестественно, поэтому применяйте именно данный код.
Как он работает, я откровенно до конца не понимаю, но взрыв на палубе рисует!
void CField::DrawObject(RECT rect, CDC *dc, HBITMAP hbm) {
CDC memDC;
CBitmap bmp, *oldbmp;
BITMAP bm, bmist;
unsigned char *bitspr, *bitsist, r_i, r_p, g_i, g_p, b_i, b_p;
CBitmap bmpist, bmpmono;
int i, j, cnt;

//сделать новый контекст устройства совместимым с реальным
//контектом устройства
memDC.CreateCompatibleDC(dc);
//сделать точечный рисунок совместимым с реальным
//контектом устройства
bmp.CreateCompatibleBitmap(dc, rect.right-rect.left, rect.bottom-rect.top);
oldbmp = memDC.SelectObject(&bmp);
//копируем
memDC.BitBlt(0, 0, rect.right-rect.left, rect.bottom-rect.top, dc,

rect.left, rect.top, SRCCOPY);

bmp.GetBitmap(&bm);
bitspr = new unsigned char[bm.bmHeight*bm.bmWidthBytes];
bmp.GetBitmapBits(bm.bmHeight*bm.bmWidthBytes, bitspr);

// присоединяем рисунок к источнику
bmpist.Attach(hbm);

bmpist.GetBitmap(&bmist);
bitsist = new unsigned char[bmist.bmHeight*bmist.bmWidthBytes];
bmpist.GetBitmapBits(bmist.bmHeight*bmist.bmWidthBytes, bitsist);

cnt = bm.bmBitsPixel/8;
if(cnt > 2)

for(i=0; i < rect.bottom-rect.top; i++)
for(j=0; j < rect.right-rect.left; j++) {
r_i = bitsist[j*cnt+i*bmist.bmWidthBytes];
g_i = bitsist[j*cnt+1+i*bmist.bmWidthBytes];
b_i = bitsist[j*cnt+2+i*bmist.bmWidthBytes];
if(!(r_i == 255 && g_i == 255 && b_i == 255)) {
bitspr[j*cnt+i*bmist.bmWidthBytes] = r_i;
bitspr[j*cnt+1+i*bmist.bmWidthBytes] = g_i;
bitspr[j*cnt+2+i*bmist.bmWidthBytes] = b_i;
}
}

else if(cnt == 2)
for(i=0; i < rect.bottom-rect.top; i++)
for(j=0; j < rect.right-rect.left; j++) {
r_i = bitsist[j*cnt+i*bmist.bmWidthBytes];
g_i = bitsist[j*cnt+1+i*bmist.bmWidthBytes];
if(!(r_i == 255 && g_i == 255)) {
bitspr[j*cnt+i*bmist.bmWidthBytes] = r_i;
bitspr[j*cnt+1+i*bmist.bmWidthBytes] = g_i;
}
}

bmp.SetBitmapBits(bm.bmHeight*bm.bmWidthBytes, bitspr);
dc->BitBlt(rect.left, rect.top, rect.right-rect.left,
rect.bottom-rect.top, &memDC, 0, 0, SRCCOPY);
memDC.SelectObject(oldbmp);
memDC.DeleteDC();
bmpist.Detach();
bmp.DeleteObject();
delete[] bitspr;
delete[] bitsist;
}

Анализ:

Функции передается холст, контекст для рисования и рисунок:
void CField::DrawObject(RECT rect, CDC *dc, HBITMAP hbm) {

CDC memDC;//новый контекст устройства (для рисования) CBitmap bmp, *oldbmp;
BITMAP bm, bmist;
unsigned char *bitspr, *bitsist, r_i, r_p, g_i, g_p, b_i, b_p;
CBitmap bmpist, bmpmono;
int i, j, cnt;

Здесь задействовано довольно много функций.

//сделать новый контекст устройства совместимым с реальным
//контектом устройства
memDC.CreateCompatibleDC(dc);

//сделать точечный рисунок совместимым с реальным
//контектом устройства
bmp.CreateCompatibleBitmap(dc, rect.right-rect.left, rect.bottom-rect.top);

//выбрать точечный рисунок в новый контекст устройства
oldbmp = memDC.SelectObject(&bmp);

//копировать точечный рисунок в новый контекст устройства
memDC.BitBlt(0, 0, rect.right - rect.left, rect.bottom - rect.top, dc,
rect.left, rect.top, SRCCOPY);

Далее что то с битами и отншением типов CBitmap и BITMAP
bmp.GetBitmap(&bm);
bitspr = new unsigned char[bm.bmHeight*bm.bmWidthBytes];
bmp.GetBitmapBits(bm.bmHeight*bm.bmWidthBytes, bitspr);

//прикрепить загружаемое изображение (образ), переданный через параметр к объекту CBitmap

bmpist.Attach(hbm);

bmpist.GetBitmap(&bmist);
bitsist = new unsigned char[bmist.bmHeight*bmist.bmWidthBytes];
bmpist.GetBitmapBits(bmist.bmHeight*bmist.bmWidthBytes, bitsist);

В конечном итоге изображение оказывается в объектах типа CBitmap (bmpist,bmp)
cnt = bm.bmBitsPixel/8;

Далее двойные циклы перерисовок.
Тонкостей этого кода не понимаю. Знаю, что работает!


Назад | Начало урока | Вверх | Вперед
Содержание

Hosted by uCoz