Status GdiplusStartup(ULONG_PTR* token, const GdiplusStartupInput* input, GdiplusStartupOutput* output);
Поля структуры GdiplusStartupInputуправляют различными аспектами инициализации: в частности, можно задать функцию, которая будет вызываться при возникновении ошибок, или перехватывать все обращения к функциям GDI+. Эти детали мы рассматривать не будем. К счастью, конструктор по умолчанию структуры GdiplusStartupInputвыполняет инициализацию, достаточную в большинстве случаев. При этом в качестве выходного параметра outputможно задать NULL.
"Магическое значение", на которое указывает выходной параметр token, необходимо сохранить.
Для завершения работы с библиотекой вызовите функцию GdiplusShutdown:
VOID GdiplusShutdown(ULONG_PTR token);
Здесь в качестве параметра и необходимо передать то самое число, которое возвратила GdiplusStartupв параметре token.
ПРИМЕЧАНИЕ
Вы можете вызвать GdiplusStartupи GdiplusShutdownиз разных потоков, но необходимо убедиться, что вне этой пары функций никакого обращения к объектам GDI+ не происходит. В частности, будьте осторожны, объявляя глобальными экземпляры классов – ведь их деструкторы выполнятся уже после WinMain. Кроме того, как обычно, нельзя вызывать функции инициализации и очистки из DllMain, поскольку это может привести ко входу в бесконечную рекурсию или другим неприятностям.
Создаем первое приложение
Настало время применить все эти сведения на практике. Для этого создадим в MS Visual C++ базовое WINAPI-приложение, которое послужит полигоном для дальнейших экспериментов. Ниже для этого приведена пошаговая процедура.
Итак, создаем новый проект Win32 Application. Выбираем опцию A typical "Hello, World!" applicationи нажимаем "finish". Получившееся приложение необходимо подготовить для использования GDI+. Для этого в файле stdafx.hпосле строки с комментарием:
// TODO: reference additional headers your program requires here
добавляем следующие строчки:
#include
using namespace Gdiplus;
и в конце файла stdafx.cppдобавляем строку
#pragma comment(lib, "GdiPlus.lib")
Кроме того, в файле stdafx.hнеобходимо удалить или закомментировать строку
#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
Иначе компилятор выдаст кучу ошибок об отсутствии символов MIDL_INTERFACE, PROPID, IStream и т.д.
Если полученное в результате приложение успешно собралось, значит, мы все сделали правильно. Пойдем дальше.
Найдем в сгенерированном основном .cppфайле нашего проекта функцию WinMainи добавим в начале ее код инициализации:
GdiplusStartupInput gdiplusStartupInput;
ULONG_PTR gdiplusToken;
GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);
а в конце, перед оператором return, добавим код очистки:
GdiplusShutdown(gdiplusToken);
Готово. Наконец-то мы можем что-нибудь нарисовать. Найдите в теле функции WndProcобработчик сообщения WM_PAINT и замените следующим кодом:
hdc = BeginPaint(hWnd, &ps);
OnPaint(hdc, ps.rcPaint);
EndPaint(hWnd, &ps);
return 0;
Теперь где-нибудь перед функцией WndProcсоздадим функцию OnPaintс кодом рисования:
void OnPaint(HDC hdc, const RECT& rc) {
// Все строки – в кодировке Unicode
WCHAR welcome[]=L"Welcome, GDI+ !";
// Создаем контекст рисования и устанавливаем
// пиксельную систему координат
Graphics g(hdc);
g.SetPageUnit(UnitPixel);
RectF bounds(0, 0, float(rc.right), float(rc.bottom));
// Загружаем фоновое изображение и растягиваем его на все окно Image
bg(L"BACKGRND.gif");
g.DrawImage(&bg, bounds);
// Создаем кисть с градиентом на все окно и полупрозрачностью
LinearGradientBrush brush(bounds, Color(130, 255, 0, 0), Color(255, 0, 0, 255), LinearGradientModeBackwardDiagonal);
// Готовим формат и параметры шрифта
StringFormat format;
format.SetAlignment(StringAlignmentCenter);
format.SetLineAlignment(StringAlignmentCenter);
Font font(L"Arial", 48, FontStyleBold);
// Выводим текст приветствия, длина –1 означает,
// что строка заканчивается нулем
g.DrawString(welcome, –1, &font, bounds, &format, &brush);
}
В результате у нас получится примерно вот что:
ПРИМЕЧАНИЕ
Приведенный пример носит только ознакомительный характер. В реальном приложении, для того чтобы нарисовать растр, его, как правило, не нужно каждый раз загружать с дискового файла :). Далее я буду пользоваться созданным макетом программы для создания других демонстрационных приложений. В качестве примера рисования будет приводиться только код функции OnPaint.
Пример WinForms – приложения с использованием GDI+
Для того чтобы можно было сравнить рассматриваемую реализацию GDI+ с той, что используется в .NET, приведу полный текст соответствующего приложения на новом языке C#:
Читать дальше