Чтение онлайн

на главную - закладки

Жанры

Применение Windows API

Легалов А. И.

Шрифт:

bmp.GetSize(_width, _height);

 }

 void SetMode(DWORD mode) {

_mode = mode;

 }

 void SetDest(int x, int y) {

_xDst = x;

_yDst = y;

 }

 void SetSrc(int x, int y) {

_xSrc = x;

_ySrc = y;

 }

 void SetArea(int width, int height) {

_width = width;

_height = height;

 }

 // transfer bitmap to canvas

 void BlitTo(Canvas & canvas);

private:

 Bitmap& _bmp;

 int _xDst, _yDst;

 int _xSrc, _ySrc;

 int _width, _height;

 DWORD _mode;

};

The BlitTo method performs the transfer from the bitmap to the window (or printer) as described by its Canvas.

void Blitter::BlitTo(Canvas& canvas) {

 // Create canvas in memory using target canvas as template

 MemCanvas memCanvas (canvas);

 // Convert bitmap to the format appropriate for this canvas

 memCanvas.SelectObject(_bmp);

 // Transfer bitmap from memory canvas to target canvas

 ::BitBlt(canvas, _xDst, _yDst, _width, _height, memCanvas, _xSrc, _ySrc, _mode);

}

The API, BitBlt, transfers bits from one device to another. That's why we have to set up a fake source device. This "memory canvas" is based on the actual canvas--in this case we use target canvas as a template. So, for instance, if the target canvas describes a True Color device, our MemCanvas will also behave like a True Color device. In particular, when our bitmap is selected into it, it will be converted to True Color, even if initially it was a monochrome or a 256-color bitmap.

The simplest program that loads and displays a bitmap might look something like this: There is a View object that contains a bitmap (I assume that the file "picture.bmp" is located in the current directory). It blits it to screen in the Paint method.

class View {

public:

 View {

_background.Load("picture.bmp");

 }

 void Paint(Canvas& canvas) {

Blitter blitter(_background);

blitter.BlitTo(canvas);

 }

private:

 Bitmap _background;

};

A sprite is an animated bitmap that moves over some background. We already know how to display bitmaps — we could blit the background first and then blit the sprite bitmap over it. This will work as long as the sprite is rectangular. If you want to be more sophisticated and use a non-rectangular sprite, you need a mask.

The two pictures below are that of a sprite (my personal pug, Fanny) and its mask. The mask is a monochrome bitmap that has black areas where we want the sprite to be transparent. The sprite, on the other hand, must be white in these areas. What we want is to be able to see the background through these areas.

The trick is to first blit the background, then blit the mask using logical OR, and then blit the sprite over it using logical AND.

ORing a black mask pixel (all zero bits) with a background pixel will give back the background pixel. ORing a white mask pixel (all one bits) with a background will give a white pixel. So after blitting the mask, we'll have a white ghost in the shape of our sprite floating over the background.

ANDing a white sprite pixel (all ones) with a background pixel will give back the background pixel. ANDing a non-white sprite pixel with the white (all ones) background (the ghost from previous step) will give the sprite pixel. We'll end up with the sprite superimposed on the background.

What remains is to implement the animation. The naive implementation would be to keep re-drawing the image: background, mask and sprite, changing the position of the mask and the sprite in each frame. The problem with this approach is that it results in unacceptable flutter. The trick with good animation is to prepare the whole picture off-line, as a single bitmap, and then blit it to screen in one quick step. This technique is called double buffering — the first buffer being the screen buffer, the second one — our bitmap.

We'll also use Windows timer to time the display of frames.

class WinTimer {

public:

 WinTimer(HWND hwnd = 0, int id = -1) : _hwnd (hwnd), _id (id) {}

 void Create(HWND hwnd, int id) {

_hwnd = hwnd;

_id = id;

 }

 void Set(int milliSec) {

::SetTimer(_hwnd, _id, milliSec, 0);

Поделиться:
Популярные книги

Отряд

Валериев Игорь
5. Ермак
Фантастика:
альтернативная история
5.25
рейтинг книги
Отряд

Звездная Кровь. Экзарх I

Рокотов Алексей
1. Экзарх
Фантастика:
боевая фантастика
рпг
фэнтези
фантастика: прочее
попаданцы
5.00
рейтинг книги
Звездная Кровь. Экзарх I

Московское золото или нежная попа комсомолки. Часть Вторая

Хренов Алексей
2. Летчик Леха
Фантастика:
попаданцы
5.00
рейтинг книги
Московское золото или нежная попа комсомолки. Часть Вторая

Газлайтер. Том 19

Володин Григорий Григорьевич
19. История Телепата
Фантастика:
попаданцы
аниме
фэнтези
5.00
рейтинг книги
Газлайтер. Том 19

Двойник Короля 8

Скабер Артемий
8. Двойник Короля
Фантастика:
аниме
фэнтези
фантастика: прочее
попаданцы
5.00
рейтинг книги
Двойник Короля 8

Я князь. Книга XVIII

Дрейк Сириус
18. Дорогой барон!
Фантастика:
юмористическое фэнтези
попаданцы
аниме
5.00
рейтинг книги
Я князь. Книга XVIII

Чернильно-Черное Сердце

Роулинг Джоан Кэтлин
6. Корморан Страйк
Детективы:
триллеры
крутой детектив
5.00
рейтинг книги
Чернильно-Черное Сердце

Запрети любить

Джейн Анна
1. Навсегда в моем сердце
Любовные романы:
современные любовные романы
5.00
рейтинг книги
Запрети любить

Лекарь Империи 5

Карелин Сергей Витальевич
5. Лекарь Империи
Фантастика:
городское фэнтези
аниме
героическая фантастика
попаданцы
5.00
рейтинг книги
Лекарь Империи 5

Корректировщик

Головачев Василий Васильевич
Фантастика:
научная фантастика
6.25
рейтинг книги
Корректировщик

Кодекс Охотника. Книга XXV

Винокуров Юрий
25. Кодекс Охотника
Фантастика:
фэнтези
попаданцы
аниме
6.25
рейтинг книги
Кодекс Охотника. Книга XXV

Сын счастья

Вассму Хербьёрг
2. Книга Дины
Проза:
современная проза
5.00
рейтинг книги
Сын счастья

Я все еще барон

Дрейк Сириус
4. Дорогой барон!
Фантастика:
боевая фантастика
5.00
рейтинг книги
Я все еще барон

Курсант: назад в СССР 2

Дамиров Рафаэль
2. Курсант
Фантастика:
попаданцы
альтернативная история
6.33
рейтинг книги
Курсант: назад в СССР 2