Картинки...
Когда-то я перерыл горы литературы, чтобы изучить форматы файлов BMP и JPG для
добавления картинок в свои программы. Поскольку программирование для Windows
в достаточной степени унифицированно, операционная система берёт на себя чтение
формата файла, и нам практически ничего не придётся делать вручную!
Это самая благодарная работа, потому что она видна сразу. Начиная от маленького
окошечка "О программе", где вы можете скромно разместить свою фотографию
и заканчивая 2-х мерными играми, где всё: фон, герой, призы, враги будут отдельными
картинками. Умело включив в свою игру красивые рисунки, вы избежите необходимости
ломать голову над разработкой дружественного и интерфейса!
Так называемые "скины" (scins) - это картинки, натянутые на окно.
Многие программы позволяют менять эти скины, например известный медаплеер WinAmp.
Сама Windows позволяет натягивать изображения на кнопки, что бесконечно их преображает.
Кроме кнопок, изображения выводятся почти куда угодно: в меню, в прокручиваемых
и выпадающих списках, в панели управления, в контекстных меню.
Наломав руки с выводом картинок PCX и BMP в MS-DOS, я думал, что в Windows их
выводить ещё сложнее. Каково же было моё удивление, когда я узнал, что загружать
картинки ничуть не сложнее, чем курсоры и иконки!
Итак, вы уже знаете, как включать файлы в проект. Знаете и про файлы ресурсов.
Новый проект создавать не обязательно. Скопируйте файл с расширением BMP в папку
с вашим проектом. Добавьте этот файл в проект через команды меню Project->Add
Resource (Project->Add To Project->New) или нажмите Ctrl+R.
В стандартном окне выбора ресурсов выберите Bitmap. Однако наш компилятор считает,
что bitmap - это маленькая картинка вроде иконки. Если вы нажмёте New, он предложит
вам её нарисовать самому, размером 16Х16. Вы гордо откажетесь и выберите Import.
Указав файл картинки в окне "Открыть..", вы тем самым добавите его
в проект. По умолчанию, ему присвоится имя IDB_MYIMAGE. Вы можете его
изменить на BMImage, например.
Файл ресурсов у вас теперь будет такой:
//First1.rc
#include "windows.h"
IDI_MYICON ICON "serdechko.ico"
IDC_MYCURSOR "dagger.cur"
IDB_MYIMAGE BITMAP "1.bmp"
В проекте уже присутствует файл 1.bmp, который мы назвали BMImage,
Теперь призовём всю мощь API функций и выведем на экран эту картинку.
int WINAPI WinMain( ... )
{
HWND hWnd;
MSG lpMsg;
WNDCLASS w;
HBITMAP hBitmap=LoadBitmap(hInstance, szImageName); //Связываем идентификатор
картинки с ресурсом
LRESULT
CALLBACK WndProc(...)
{
HDC hdc, hmdc; //объявляем ещё один контекст изображения hmdc
PAINTSTRUCT ps;
BITMAP bm;
switch(messg)
{
case WM_PAINT:
hdc=BeginPaint(hWnd, &ps);
//здесь начинаются строки, связанные с рисованием картинки
hmdc=CreateCompatibleDC(hdc); //Создаёт совместимый с оконным контекст памяти
SelectObject(hmdc, hBitmap); //Выбирает объект картинку
GetObject(hBitmap, sizeof(bm), (LPSTR) &bm); //получаем высоту и ширину
картинки
BitBlt(hdc, 10,10, bm.Width, bm.bmHeight, hmdc, 0,0, SRCCOPY); //Помещает картинку
на экран в точку 10, 10
//из памяти (hmdc)
DeleteDC(hmdc); //удаляем из памяти контекст
//Конец рисования картинки
Итак, немного поподробней о том, что мы сделали:
Шаг 1. Перемення szImage[] будет содержать в себе строку с именем ресурса IDB_MYIMAGE.
Шаг 2. HBITMAP hBitmap=LoadBitmap(hInstance, szImageName);
Тип данных HBITMAP подобен HCURSOR и HICON тем, что переменного этого
типа служит для связи программы с каким-то ресурсом. В данном случае, изображением.
Шаг 3. Для вывода на экран картинки, ей выделяется свой личный контекст, отличный
от HDC. Тем не менее, он должен быть совместим с HDC, для этого на 5-м шаге
мы применяем функцию CreateCompatibleDC(HDC), значение которой приравниваем
контексту изображения. Теперь, выводя картинку в hmdc, всё равно, что мы выводим
её в HDC.
Шаг 4. Все данные об изображении: размер, количество планов, высоту, ширину,
количество бит, выделенных для описания пикселя, содержит структура BITMAP.
Создавая её экземпляр BITMAP bm, мы заполняем эту структуру информацией о нашей
многострадальной картинке из ресурса 1.bmp. После выполнения на пятом шаге GetObject(hBitmap,
sizeof(bm), &bm), cтруктура BITMAP будет заполнена всем, что связано
с hBitmap. Вторым аргументом функции GetObject, мы указываем размер структуры,
получив её размер через sizeof(bm).
Шаг 5. Здесь мы создаём совместимый контекст функцией CreateCompatibleDC(),
делаем активным объект hBitmap в контексте hmdc, заполняем структуру BITMAP
с помощью GetObject(), выводим на экран картинку с помощью BitBlt().
Функция BitBlt широко применяется во всевозможных графических редакторах
и программах. Её достоинство в том, что она копирует область из памяти куда
угодно и с какими угодно размерами. Это удобно для игровых программ, когда надо
постоянно выводить картинку с изображением игрока в разных местах.
Первый аргумент функции контекст куда мы выводим - HDC.Второй и третий - координаты
левого верхнего угла картинки. Четвёртый - ширина и высота картинки, пятый -
контекст из которого выводим - hmdc. Шестой и седьмой - с какого места контекста
hmdc копируем - естественно с самого начала (0,0). Последний аргмуент - режим
копирования. Их несколько:
BLACKNESS
- чёрный квадрат DSTINVERT - инверсия фона MERGECOPY - слитное копирование MERGEPAINT - цвет фона - самый чёрный цвет, изображение негативно NOTSRCCOPY - негатив NOTSRCERASE - самый чёрный цвет - цвет инверсный фоновому. Изображение негативно PATCOPY- белый квадрат PATINVERT - инверсия фону PATPAINT - белый квадрат SRCAND - белый цвет - цвет фона SRCCOPY - простое копирование SRCERASE - белый цвет инверсный фону SRCINVERT - инверсия исходнику SRCPAINT - изображение двух цветов - цвет фона и белый WHITENESS - белый квадрат |
|
Как видите,
спецэффектов много, но они не богатые. Конечно они хороши для простых игр, но
для больших "наворотов" используются возможности библиотеки DirectX,
а точнее DirectDraw. Это очень обширная тема, и по ней одной можно написать
отдельную книгу.
Небольшая оговорочка. Всё это очень хорошо, если у нас картинки хранятся в ресурсе
и совершенно непригодно для открытия файла картинки с диска, например, через
стандартное окно "Открыть". Для открытия любой картинки из файла нам
необходимо так же, как и в DOS знать формат файла: PCX, JPG, TIFF или BMP. Дело
облегчается тем, что давно уже написаны классы для работы с этими форматами,
поэтому изобретать велосипед не нужно. Часто в книгах по Visual C++ эти классы
приведены целиком.
Создав экземпляр такого класса, например:
CBitmаp *cbmp = new CBitmap;
вы сможете пользоваться всеми его методами для открытия, сохранения, получения
информации о картинке и др.
cbmp->OpenBmp("c:\MyPics\sexy.bmp"); //использованиe
метода открытия картинки
cbmp->SaveToFile("default.bmp"); //использованиe метода сохранения
картинки
bmpInfo = cbmp.BmpInfo(); //информация о файле
И, пожалуй, это будет лучший выход из положения. Названия функций могут быть
различны, но суть у них одна. И здесь процедурное программирование проигрывает
перед объектно-ориентированным.
1. Поменяв
последний параметр BitBlt, добиться вывода картинки в негативном отображении.
2. Разместите в ресурсах три изображения 200Х400 точек, в которых будут нарисованы
три карты (создать и нарисовать карты можно в редакторе Paint, в котором есть
средство изменения размера картинки). Карты должны быть: 2 червей, 6 пик и 10
треф. Используя полученные знания, разместите карты в середине экрана. Над ними
выведите надпись (функция TextOut): "Выберит любую карту".