GDI - Graphics Device Interface
Graphics device interface (GDI - графический интерфейс устройства) - это базовая система вывода двухмерной графики Windows. Под системой вывода графики мы будем понимать рисование геометрических фигур и вывод текста. Т.е. GDI отвечает за рисование картинок и вывод текста.
GDI написана на winAPI, т.е. это просто набор функций и структур на чистом C. Сначала мы познакомимся с GDI, а потом рассмотрим более сложные системы вывода двухмерной графики: GDI+ и Direct2D.
Device context - контекст устройства
Контекст устройства (Device context) - это то место, куда рисуется графика, плюс средства рисования графики. Мы можем получить контекст устройства окна и тогда можем рисовать что-то в этом окне. Можно получить контекст устройства принтера и рисовать фигуры на печатаемой странице. Контекст устройства позволяет использовать кисти (brushes), перья (pens), картинки (bitmaps) для вывода графики.
Получение контекста устройства окна
Для получения контекста устройства окна используется описатель окна (HWND). Контекст устройства представлен в программе переменной типа HDC - переопределённый указатель на void. Для получения контекста устройства окна используется функция getDC:
!1?HDC hDC = GetDC(hWnd);?1!После этого можно использовать переменную hDC для рисования в окне hWnd. После завершения рисования, нужно "отпустить" контекст устройства с помощью функции ReleaseDC. Давайте посмотрим на код, который рисует прямоугольник и выводит текстовую строку в окне:
!1?WNDCLASS wc; wc.style = CS_OWNDC; wc.lpfnWndProc = WndProc; wc.cbClsExtra = 0; wc.cbWndExtra = 0; wc.hInstance = hInstance; wc.hIcon = LoadIcon(NULL, IDI_APPLICATION); wc.hCursor = LoadCursor(NULL, IDC_ARROW); wc.hbrBackground = (HBRUSH)(6); wc.lpszMenuName = 0; wc.lpszClassName = L"class"; RegisterClass(&wc); HWND hWnd = CreateWindow(L"class", L"GDI", WS_OVERLAPPEDWINDOW, 100, 100, 300, 300, NULL, NULL, hInstance, NULL); ShowWindow(hWnd, nCmdShow); UpdateWindow(hWnd); HDC hDC = GetDC(hWnd); // получение контекста устройства Rectangle(hDC, 50, 50, 200, 200); // рисование прямоугольника TextOut(hDC, 5, 5, L"Привет!!!", 9); // вывод текста ReleaseDC(hWnd, hDC); // освобождение контекста устройства?1!Функция Rectangle принимает следующие аргументы: контекст устройства, координаты левого верхнего угла, координаты правого нижнего угла.
Функция TextOut принимает аргументы: контекст устройства, координаты левого верхнего угла текста, текстовая строка, количество символов в текстовой строке.
Функция Release принимает аргументы: окно, контекст устройства.

В данном примере рисование происходит до основного цикла while. Т.е. рисование будет произведено только один раз. Если вы свернёте и развернёте окно, то нарисованное исчезнет. Просто нужно поместить рисование внутрь цикла while, как это сделано в прикреплённом проекте gdi_0.1, тогда окно будет перерисовываться при каждой итерации.
Вывод графики в нескольких окнах
Когда мы заполняем структуру WNDCLASS, чтобы зарегистрировать класс окна программы в Windows, мы заполняем поле style:
!1?wc.style = CS_OWNDC;?1!Данное поле задаёт стиль класса окон. Значение CS_OWNDC говорит, что для каждого окна данного класса будет создан свой контекст устройства.
Рассмотрим пример gdi_0.2. В данной программе создаётся два окна:
Заметьте, что второе окно нельзя растягивать, у него нет системного меню и кнопки закрытия. Просто при создании второго окна я не стал указывать стиль (передал ноль в третий аргумент):
!1?HWND hWnd2 = CreateWindow(L"class", L"GDI2", 0, 300, 100, 200, 200, NULL, NULL, hInstance, NULL);?1!У каждого окна этой программы свой контекст устройства:
!1?HWND hWnd1 = CreateWindow(L"class", L"GDI", WS_OVERLAPPEDWINDOW, 100, 100, 200, 200, NULL, NULL, hInstance, NULL); HWND hWnd2 = CreateWindow(L"class", L"GDI2", 0, 300, 100, 200, 200, NULL, NULL, hInstance, NULL); ShowWindow(hWnd1, nCmdShow); UpdateWindow(hWnd1); ShowWindow(hWnd2, nCmdShow); UpdateWindow(hWnd2); MSG msg; HDC hDC = GetDC(hWnd1); Rectangle(hDC, 50, 50, 100, 100); TextOut(hDC, 5, 5, L"Первое окно!!!", 14); ReleaseDC(hWnd1, hDC); while (true) { if (PeekMessage(&msg, 0, 0, 0, PM_REMOVE)) { if (msg.message == WM_QUIT) break; TranslateMessage(&msg); DispatchMessage(&msg); } hDC = GetDC(hWnd2); Rectangle(hDC, 50, 50, 100, 100); TextOut(hDC, 5, 5, L"Второе окно!!!", 14); ReleaseDC(hWnd2, hDC); }?1!
Рисование в первом окне происходит до основного цикла. Поэтому, если свернуть, а затем развернуть окно, то всё нарисованное исчезнет. Рисование во втором окне происходит при каждой итерации основного цикла.
Заключение
В данном уроке мы познакомились с GDI - базовой системой вывода двухмерной графики в Windows. В следующих уроках мы научимся работать с различными возможностями GDI: перьями и кистями.
В основном мы будем рисовать графику в главном цикле - такой вывод графики больше подходит для игр. Но это нехарактерно для программ Windows. Чуть позже мы познакомимся со стандартным способом использования GDI в Windows программах.
Комментарии